MethodDefinition.java revision 7f9cfb3a6863ebc5a1024b7ce2a9b63b34625956
1/* 2 * [The "BSD licence"] 3 * Copyright (c) 2009 Ben Gruver 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. The name of the author may not be used to endorse or promote products 15 * derived from this software without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 * INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29package org.jf.baksmali.Adaptors; 30 31import org.jf.baksmali.Adaptors.Format.*; 32import org.jf.baksmali.baksmali; 33import org.jf.dexlib.*; 34import org.jf.dexlib.Debug.DebugInstructionIterator; 35import org.jf.dexlib.Code.Format.*; 36import org.jf.dexlib.Code.Instruction; 37import org.jf.dexlib.Code.Opcode; 38import org.jf.dexlib.Code.OffsetInstruction; 39import org.jf.dexlib.Util.AccessFlags; 40import org.antlr.stringtemplate.StringTemplateGroup; 41import org.antlr.stringtemplate.StringTemplate; 42 43import java.util.*; 44 45public class MethodDefinition { 46 public static StringTemplate makeTemplate(StringTemplateGroup stg, ClassDataItem.EncodedMethod encodedMethod, 47 AnnotationSetItem annotationSet, 48 AnnotationSetRefList parameterAnnotations) { 49 50 CodeItem codeItem = encodedMethod.codeItem; 51 52 StringTemplate template = stg.getInstanceOf("method"); 53 54 template.setAttribute("AccessFlags", getAccessFlags(encodedMethod)); 55 template.setAttribute("MethodName", encodedMethod.method.getMethodName().getStringValue()); 56 template.setAttribute("Prototype", encodedMethod.method.getPrototype().getPrototypeString()); 57 template.setAttribute("HasCode", codeItem != null); 58 template.setAttribute("RegistersDirective", baksmali.useLocalsDirective?".locals":".registers"); 59 template.setAttribute("RegisterCount", codeItem==null?"0":Integer.toString(getRegisterCount(encodedMethod))); 60 template.setAttribute("Parameters", getParameters(stg, codeItem, parameterAnnotations)); 61 template.setAttribute("Annotations", getAnnotations(stg, annotationSet)); 62 template.setAttribute("MethodItems", getMethodItems(encodedMethod.method.getDexFile(), stg, codeItem)); 63 64 return template; 65 } 66 67 private static int getRegisterCount(ClassDataItem.EncodedMethod encodedMethod) 68 { 69 int totalRegisters = encodedMethod.codeItem.getRegisterCount(); 70 if (baksmali.useLocalsDirective) { 71 int parameterRegisters = encodedMethod.method.getPrototype().getParameterRegisterCount(); 72 if ((encodedMethod.accessFlags & AccessFlags.STATIC.getValue()) == 0) { 73 parameterRegisters++; 74 } 75 return totalRegisters - parameterRegisters; 76 } 77 return totalRegisters; 78 } 79 80 private static List<String> getAccessFlags(ClassDataItem.EncodedMethod encodedMethod) { 81 List<String> accessFlags = new ArrayList<String>(); 82 83 for (AccessFlags accessFlag: AccessFlags.getAccessFlagsForMethod(encodedMethod.accessFlags)) { 84 accessFlags.add(accessFlag.toString()); 85 } 86 87 return accessFlags; 88 } 89 90 private static List<StringTemplate> getParameters(StringTemplateGroup stg, CodeItem codeItem, 91 AnnotationSetRefList parameterAnnotations) { 92 DebugInfoItem debugInfoItem = null; 93 if (baksmali.outputDebugInfo && codeItem != null) { 94 debugInfoItem = codeItem.getDebugInfo(); 95 } 96 97 int parameterCount = 0; 98 99 List<AnnotationSetItem> annotations = new ArrayList<AnnotationSetItem>(); 100 if (parameterAnnotations != null) { 101 AnnotationSetItem[] _annotations = parameterAnnotations.getAnnotationSets(); 102 if (_annotations != null) { 103 annotations.addAll(Arrays.asList(_annotations)); 104 } 105 106 parameterCount = annotations.size(); 107 } 108 109 List<String> parameterNames = new ArrayList<String>(); 110 if (debugInfoItem != null) { 111 StringIdItem[] _parameterNames = debugInfoItem.getParameterNames(); 112 if (_parameterNames != null) { 113 for (StringIdItem parameterName: _parameterNames) { 114 parameterNames.add(parameterName==null?null:parameterName.getStringValue()); 115 } 116 } 117 118 if (parameterCount < parameterNames.size()) { 119 parameterCount = parameterNames.size(); 120 } 121 } 122 123 List<StringTemplate> parameters = new ArrayList<StringTemplate>(); 124 for (int i=0; i<parameterCount; i++) { 125 AnnotationSetItem annotationSet = null; 126 if (i < annotations.size()) { 127 annotationSet = annotations.get(i); 128 } 129 130 String parameterName = null; 131 if (i < parameterNames.size()) { 132 parameterName = parameterNames.get(i); 133 } 134 135 parameters.add(ParameterAdaptor.makeTemplate(stg, parameterName, annotationSet)); 136 } 137 138 return parameters; 139 } 140 141 private static List<StringTemplate> getAnnotations(StringTemplateGroup stg, AnnotationSetItem annotationSet) { 142 if (annotationSet == null) { 143 return null; 144 } 145 146 List<StringTemplate> annotationAdaptors = new ArrayList<StringTemplate>(); 147 148 for (AnnotationItem annotationItem: annotationSet.getAnnotations()) { 149 annotationAdaptors.add(AnnotationAdaptor.makeTemplate(stg, annotationItem)); 150 } 151 return annotationAdaptors; 152 } 153 154 private static List<MethodItem> getMethodItems(DexFile dexFile, StringTemplateGroup stg, CodeItem codeItem) { 155 List<MethodItem> methodItems = new ArrayList<MethodItem>(); 156 157 MethodItemList methodItemList = new MethodItemList(dexFile, stg, codeItem); 158 methodItemList.generateMethodItemList(); 159 160 for (LabelMethodItem labelMethodItem: methodItemList.labels.getLabels()) { 161 if (labelMethodItem.isCommentedOut()) { 162 methodItems.add(new CommentedOutMethodItem(stg, labelMethodItem)); 163 } else { 164 methodItems.add(labelMethodItem); 165 } 166 } 167 168 methodItems.addAll(methodItemList.instructions); 169 methodItems.addAll(methodItemList.blanks); 170 methodItems.addAll(methodItemList.catches); 171 if (baksmali.outputDebugInfo) { 172 methodItems.addAll(methodItemList.debugItems); 173 } 174 Collections.sort(methodItems); 175 176 return methodItems; 177 } 178 179 180 private static class MethodItemList { 181 private final DexFile dexFile; 182 private final StringTemplateGroup stg; 183 private final CodeItem codeItem; 184 185 public LabelCache labels = new LabelCache(); 186 187 public List<MethodItem> instructions = new ArrayList<MethodItem>(); 188 public List<BlankMethodItem> blanks = new ArrayList<BlankMethodItem>(); 189 public List<CatchMethodItem> catches = new ArrayList<CatchMethodItem>(); 190 public List<MethodItem> debugItems = new ArrayList<MethodItem>(); 191 192 private HashMap<Integer, Integer> packedSwitchMap = new HashMap<Integer, Integer>(); 193 private HashMap<Integer, Integer> sparseSwitchMap = new HashMap<Integer, Integer>(); 194 195 public MethodItemList(DexFile dexFile, StringTemplateGroup stg, CodeItem codeItem) { 196 this.dexFile = dexFile; 197 this.stg = stg; 198 this.codeItem = codeItem; 199 } 200 201 public void generateMethodItemList() { 202 if (codeItem == null) { 203 return; 204 } 205 206 if (baksmali.deodexUtil != null && dexFile.isOdex()) { 207 List<Instruction> instructions = baksmali.deodexUtil.deodexerizeCode(codeItem); 208 209 int offset = 0; 210 for (Instruction instruction: instructions) { 211 if (instruction.opcode == Opcode.PACKED_SWITCH) { 212 Instruction31t ins = (Instruction31t)instruction; 213 packedSwitchMap.put(offset + ins.getOffset(), offset); 214 } else if (instruction.opcode == Opcode.SPARSE_SWITCH) { 215 Instruction31t ins = (Instruction31t)instruction; 216 sparseSwitchMap.put(offset + ins.getOffset(), offset); 217 } 218 219 offset += instruction.getSize(offset*2)/2; 220 } 221 222 offset = 0; 223 for (Instruction instruction: instructions) { 224 addMethodItemsForInstruction(offset, instruction, false); 225 blanks.add(new BlankMethodItem(stg, offset)); 226 227 offset += instruction.getSize(offset*2)/2; 228 } 229 230 /* 231 * Look for the last uncommented instruction. If it is an UnresolvedNullReference, 232 * then set IsLastInstruction, so a goto will be added after it, to avoid validation 233 * issues 234 */ 235 for (int i=this.instructions.size()-1; i>=0; i--) { 236 MethodItem ins = this.instructions.get(i); 237 if (ins instanceof UnresolvedNullReferenceMethodItem) { 238 ((UnresolvedNullReferenceMethodItem)ins).setIsLastInstruction(true); 239 break; 240 } 241 242 if (!(ins instanceof CommentedOutMethodItem)) { 243 break; 244 } 245 } 246 } else { 247 int currentCodeOffset = 0; 248 for (Instruction instruction: codeItem.getInstructions()) { 249 if (instruction.opcode == Opcode.PACKED_SWITCH) { 250 OffsetInstruction offsetInstruction = (OffsetInstruction)instruction; 251 packedSwitchMap.put(currentCodeOffset/2 + offsetInstruction.getOffset(), currentCodeOffset/2); 252 } else if (instruction.opcode == Opcode.SPARSE_SWITCH) { 253 OffsetInstruction offsetInstruction = (OffsetInstruction)instruction; 254 sparseSwitchMap.put(currentCodeOffset/2 + offsetInstruction.getOffset(), currentCodeOffset/2); 255 } 256 257 currentCodeOffset += instruction.getSize(currentCodeOffset); 258 } 259 260 currentCodeOffset = 0; 261 for (Instruction instruction: codeItem.getInstructions()) { 262 int offset = currentCodeOffset/2; 263 addMethodItemsForInstruction(offset, instruction, false); 264 blanks.add(new BlankMethodItem(stg, offset)); 265 currentCodeOffset += instruction.getSize(currentCodeOffset); 266 } 267 268 } 269 270 blanks.remove(blanks.size()-1); 271 272 addTries(); 273 274 addDebugInfo(); 275 276 if (baksmali.useSequentialLabels) { 277 setLabelSequentialNumbers(); 278 } 279 } 280 281 private void addOffsetInstructionMethodItem(OffsetInstructionFormatMethodItem methodItem, 282 boolean commentedOut) { 283 if (commentedOut) { 284 instructions.add(new CommentedOutMethodItem(stg, methodItem)); 285 } else { 286 instructions.add(methodItem); 287 LabelMethodItem label = methodItem.getLabel(); 288 label.setUncommented(); 289 } 290 } 291 292 293 private void addInstructionMethodItem(InstructionFormatMethodItem methodItem, boolean commentedOut) { 294 if (commentedOut) { 295 instructions.add(new CommentedOutMethodItem(stg, methodItem)); 296 } else { 297 instructions.add(methodItem); 298 } 299 } 300 301 private void addMethodItemsForInstruction(int offset, Instruction instruction, boolean commentedOut) { 302 switch (instruction.getFormat()) { 303 case Format10t: 304 addOffsetInstructionMethodItem( 305 new Instruction10tMethodItem(labels, codeItem, offset, stg,(Instruction10t)instruction), 306 commentedOut); 307 return; 308 case Format10x: 309 addInstructionMethodItem( 310 new Instruction10xMethodItem(codeItem, offset, stg, (Instruction10x)instruction), 311 commentedOut); 312 return; 313 case Format11n: 314 addInstructionMethodItem( 315 new Instruction11nMethodItem(codeItem, offset, stg, (Instruction11n)instruction), 316 commentedOut); 317 return; 318 case Format11x: 319 addInstructionMethodItem( 320 new Instruction11xMethodItem(codeItem, offset, stg, (Instruction11x)instruction), 321 commentedOut); 322 return; 323 case Format12x: 324 addInstructionMethodItem( 325 new Instruction12xMethodItem(codeItem, offset, stg, (Instruction12x)instruction), 326 commentedOut); 327 return; 328 case Format20t: 329 addOffsetInstructionMethodItem( 330 new Instruction20tMethodItem(labels, codeItem, offset, stg, (Instruction20t)instruction), 331 commentedOut); 332 return; 333 case Format21c: 334 addInstructionMethodItem( 335 new Instruction21cMethodItem(codeItem, offset, stg, (Instruction21c)instruction), 336 commentedOut); 337 return; 338 case Format21h: 339 addInstructionMethodItem( 340 new Instruction21hMethodItem(codeItem, offset, stg, (Instruction21h)instruction), 341 commentedOut); 342 return; 343 case Format21s: 344 addInstructionMethodItem( 345 new Instruction21sMethodItem(codeItem, offset, stg, (Instruction21s)instruction), 346 commentedOut); 347 return; 348 case Format21t: 349 addOffsetInstructionMethodItem( 350 new Instruction21tMethodItem(labels, codeItem, offset, stg, (Instruction21t)instruction), 351 commentedOut); 352 return; 353 case Format22b: 354 addInstructionMethodItem( 355 new Instruction22bMethodItem(codeItem, offset, stg, (Instruction22b)instruction), 356 commentedOut); 357 return; 358 case Format22c: 359 addInstructionMethodItem( 360 new Instruction22cMethodItem(codeItem, offset, stg, (Instruction22c)instruction), 361 commentedOut); 362 return; 363 case Format22cs: 364 addInstructionMethodItem( 365 new Instruction22csMethodItem(codeItem, offset, stg, (Instruction22cs)instruction), 366 commentedOut); 367 return; 368 case Format22csf: 369 addInstructionMethodItem( 370 new Instruction22csfMethodItem(codeItem, offset, stg, (Instruction22csf)instruction), 371 commentedOut); 372 return; 373 case Format22s: 374 addInstructionMethodItem( 375 new Instruction22sMethodItem(codeItem, offset, stg, (Instruction22s)instruction), 376 commentedOut); 377 return; 378 case Format22t: 379 addOffsetInstructionMethodItem( 380 new Instruction22tMethodItem(labels, codeItem, offset, stg, (Instruction22t)instruction), 381 commentedOut); 382 return; 383 case Format22x: 384 addInstructionMethodItem( 385 new Instruction22xMethodItem(codeItem, offset, stg, (Instruction22x)instruction), 386 commentedOut); 387 return; 388 case Format23x: 389 addInstructionMethodItem( 390 new Instruction23xMethodItem(codeItem, offset, stg, (Instruction23x)instruction), 391 commentedOut); 392 return; 393 case Format30t: 394 addOffsetInstructionMethodItem( 395 new Instruction30tMethodItem(labels, codeItem, offset, stg, (Instruction30t)instruction), 396 commentedOut); 397 return; 398 case Format31c: 399 addInstructionMethodItem( 400 new Instruction31cMethodItem(codeItem, offset, stg, (Instruction31c)instruction), 401 commentedOut); 402 return; 403 case Format31i: 404 addInstructionMethodItem( 405 new Instruction31iMethodItem(codeItem, offset, stg, (Instruction31i)instruction), 406 commentedOut); 407 return; 408 case Format31t: 409 addOffsetInstructionMethodItem( 410 new Instruction31tMethodItem(labels, codeItem, offset, stg, (Instruction31t)instruction), 411 commentedOut); 412 return; 413 case Format32x: 414 addInstructionMethodItem( 415 new Instruction32xMethodItem(codeItem, offset, stg, (Instruction32x)instruction), 416 commentedOut); 417 return; 418 case Format35c: 419 addInstructionMethodItem( 420 new Instruction35cMethodItem(codeItem, offset, stg, (Instruction35c)instruction), 421 commentedOut); 422 return; 423 case Format35s: 424 addInstructionMethodItem( 425 new Instruction35sMethodItem(codeItem, offset, stg, (Instruction35s)instruction), 426 commentedOut); 427 return; 428 case Format35sf: 429 addInstructionMethodItem( 430 new Instruction35sfMethodItem(codeItem, offset, stg, (Instruction35sf)instruction), 431 commentedOut); 432 return; 433 case Format35ms: 434 addInstructionMethodItem( 435 new Instruction35msMethodItem(codeItem, offset, stg, (Instruction35ms)instruction), 436 commentedOut); 437 return; 438 case Format35msf: 439 addInstructionMethodItem( 440 new Instruction35msfMethodItem(codeItem, offset, stg, (Instruction35msf)instruction), 441 commentedOut); 442 return; 443 case Format3rc: 444 addInstructionMethodItem( 445 new Instruction3rcMethodItem(codeItem, offset, stg, (Instruction3rc)instruction), 446 commentedOut); 447 return; 448 case Format3rms: 449 addInstructionMethodItem( 450 new Instruction3rmsMethodItem(codeItem, offset, stg, (Instruction3rms)instruction), 451 commentedOut); 452 return; 453 case Format3rmsf: 454 addInstructionMethodItem( 455 new Instruction3rmsfMethodItem(codeItem, offset, stg, (Instruction3rmsf)instruction), 456 commentedOut); 457 return; 458 case Format51l: 459 addInstructionMethodItem( 460 new Instruction51lMethodItem(codeItem, offset, stg, (Instruction51l)instruction), 461 commentedOut); 462 return; 463 case ArrayData: 464 addInstructionMethodItem( 465 new ArrayDataMethodItem(codeItem, offset, stg, (ArrayDataPseudoInstruction)instruction), 466 commentedOut); 467 return; 468 case PackedSwitchData: 469 { 470 final Integer baseAddress = packedSwitchMap.get(offset); 471 472 if (baseAddress != null) { 473 PackedSwitchDataPseudoInstruction packedSwitchInstruction = 474 (PackedSwitchDataPseudoInstruction)instruction; 475 476 PackedSwitchMethodItem packedSwitch = new PackedSwitchMethodItem(labels, codeItem, offset, stg, 477 packedSwitchInstruction, baseAddress); 478 addInstructionMethodItem(packedSwitch, commentedOut); 479 480 if (!commentedOut) { 481 for (LabelMethodItem label: packedSwitch) { 482 label.setUncommented(); 483 } 484 } 485 } 486 return; 487 } 488 case SparseSwitchData: 489 { 490 final Integer baseAddress = sparseSwitchMap.get(offset); 491 492 if (baseAddress != null) { 493 SparseSwitchDataPseudoInstruction sparseSwitchInstruction = 494 (SparseSwitchDataPseudoInstruction)instruction; 495 496 SparseSwitchMethodItem sparseSwitch = new SparseSwitchMethodItem(labels, codeItem, offset, stg, 497 sparseSwitchInstruction, baseAddress); 498 addInstructionMethodItem(sparseSwitch, commentedOut); 499 500 if (!commentedOut) { 501 for (LabelMethodItem label: sparseSwitch) { 502 label.setUncommented(); 503 } 504 } 505 } 506 return; 507 } 508 case UnresolvedNullReference: 509 { 510 addInstructionMethodItem(new UnresolvedNullReferenceMethodItem(codeItem, offset, stg, 511 (UnresolvedNullReference)instruction), commentedOut); 512 addMethodItemsForInstruction(offset, ((UnresolvedNullReference)instruction).OriginalInstruction, 513 true); 514 return; 515 } 516 case DeadInstruction: 517 { 518 //TODO: what about try/catch blocks inside the dead code? those will need to be commented out too. ugh. 519 addMethodItemsForInstruction(offset, ((DeadInstruction)instruction).OriginalInstruction, true); 520 return; 521 } 522 } 523 } 524 525 private void addTries() { 526 if (codeItem.getTries() == null) { 527 return; 528 } 529 for (CodeItem.TryItem tryItem: codeItem.getTries()) { 530 int startAddress = tryItem.getStartAddress(); 531 int endAddress = tryItem.getStartAddress() + tryItem.getInstructionCount(); 532 533 /** 534 * The end address points to the address immediately after the end of the last 535 * instruction that the try block covers. We want the .catch directive and end_try 536 * label to be associated with the last covered instruction, so we need to get 537 * the offset for that instruction 538 */ 539 int index = Collections.binarySearch(instructions, new BlankMethodItem(stg, endAddress)); 540 if (index < 0) { 541 index = (index * -1) - 1; 542 } 543 //index should never be 0, so this should be safe 544 if (index == instructions.size()) { 545 //if the end address is the same as the address of the last instruction, then 546 //this try item ends at the next to last instruction. 547 //otherwise, if the end address is past the address of the last instruction, 548 //thin this try item ends at the last instruction 549 if (instructions.get(instructions.size() - 1).getOffset() == endAddress) { 550 //get the address for the next to last instruction 551 index -= 2; 552 } else { 553 //get the address for the last instruction 554 index--; 555 } 556 } else { 557 index -= 2; 558 } 559 560 int lastInstructionOffset = instructions.get(index).getOffset(); 561 562 //add the catch all handler if it exists 563 int catchAllAddress = tryItem.encodedCatchHandler.getCatchAllHandlerAddress(); 564 if (catchAllAddress != -1) { 565 CatchMethodItem catchMethodItem = new CatchMethodItem(labels, lastInstructionOffset, stg, null, 566 startAddress, endAddress, catchAllAddress); 567 catches.add(catchMethodItem); 568 } 569 570 //add the rest of the handlers 571 for (CodeItem.EncodedTypeAddrPair handler: tryItem.encodedCatchHandler.handlers) { 572 //use the offset from the last covered instruction 573 CatchMethodItem catchMethodItem = new CatchMethodItem(labels, lastInstructionOffset, stg, 574 handler.exceptionType, startAddress, endAddress, handler.getHandlerAddress()); 575 catches.add(catchMethodItem); 576 } 577 } 578 } 579 580 private void addDebugInfo() { 581 DebugInfoItem debugInfoItem = codeItem.getDebugInfo(); 582 if (debugInfoItem == null) { 583 return; 584 } 585 586 DebugInstructionIterator.DecodeInstructions(debugInfoItem, codeItem.getRegisterCount(), 587 new DebugInstructionIterator.ProcessDecodedDebugInstructionDelegate() { 588 @Override 589 public void ProcessStartLocal(int codeAddress, int length, int registerNum, StringIdItem name, 590 TypeIdItem type) { 591 debugItems.add(new LocalDebugMethodItem(codeItem, codeAddress, stg, "StartLocal", -1, 592 registerNum, name, type, null)); 593 } 594 595 @Override 596 public void ProcessStartLocalExtended(int codeAddress, int length, int registerNum, 597 StringIdItem name, TypeIdItem type, 598 StringIdItem signature) { 599 debugItems.add(new LocalDebugMethodItem(codeItem, codeAddress, stg, "StartLocal", -1, 600 registerNum, name, type, signature)); 601 } 602 603 @Override 604 public void ProcessEndLocal(int codeAddress, int length, int registerNum, StringIdItem name, 605 TypeIdItem type, StringIdItem signature) { 606 debugItems.add(new LocalDebugMethodItem(codeItem, codeAddress, stg, "EndLocal", -1, 607 registerNum, name, type, signature)); 608 } 609 610 @Override 611 public void ProcessRestartLocal(int codeAddress, int length, int registerNum, StringIdItem name, 612 TypeIdItem type, StringIdItem signature) { 613 debugItems.add(new LocalDebugMethodItem(codeItem, codeAddress, stg, "RestartLocal", -1, 614 registerNum, name, type, signature)); 615 } 616 617 @Override 618 public void ProcessSetPrologueEnd(int codeAddress) { 619 debugItems.add(new DebugMethodItem(codeAddress, stg, "EndPrologue", -4)); 620 } 621 622 @Override 623 public void ProcessSetEpilogueBegin(int codeAddress) { 624 debugItems.add(new DebugMethodItem(codeAddress, stg, "StartEpilogue", -4)); 625 } 626 627 @Override 628 public void ProcessSetFile(int codeAddress, int length, final StringIdItem name) { 629 debugItems.add(new DebugMethodItem(codeAddress, stg, "SetFile", -3) { 630 @Override 631 protected void setAttributes(StringTemplate template) { 632 template.setAttribute("FileName", name.getStringValue()); 633 } 634 }); 635 } 636 637 @Override 638 public void ProcessLineEmit(int codeAddress, final int line) { 639 debugItems.add(new DebugMethodItem(codeAddress, stg, "Line", -2) { 640 @Override 641 protected void setAttributes(StringTemplate template) { 642 template.setAttribute("Line", line); 643 } 644 }); 645 } 646 }); 647 } 648 649 private void setLabelSequentialNumbers() { 650 HashMap<String, Integer> nextLabelSequenceByType = new HashMap<String, Integer>(); 651 ArrayList<LabelMethodItem> sortedLabels = new ArrayList<LabelMethodItem>(labels.getLabels()); 652 653 //sort the labels by their location in the method 654 Collections.sort(sortedLabels); 655 656 for (LabelMethodItem labelMethodItem: sortedLabels) { 657 Integer labelSequence = nextLabelSequenceByType.get(labelMethodItem.getLabelPrefix()); 658 if (labelSequence == null) { 659 labelSequence = 0; 660 } 661 labelMethodItem.setLabelSequence(labelSequence); 662 nextLabelSequenceByType.put(labelMethodItem.getLabelPrefix(), labelSequence + 1); 663 } 664 } 665 } 666 667 public static class LabelCache { 668 protected HashMap<LabelMethodItem, LabelMethodItem> labels = new HashMap<LabelMethodItem, LabelMethodItem>(); 669 670 public LabelCache() { 671 } 672 673 public LabelMethodItem internLabel(LabelMethodItem labelMethodItem) { 674 LabelMethodItem internedLabelMethodItem = labels.get(labelMethodItem); 675 if (internedLabelMethodItem != null) { 676 if (!labelMethodItem.isCommentedOut()) { 677 internedLabelMethodItem.setUncommented(); 678 } 679 return internedLabelMethodItem; 680 } 681 labels.put(labelMethodItem, labelMethodItem); 682 return labelMethodItem; 683 } 684 685 686 public Collection<LabelMethodItem> getLabels() { 687 return labels.values(); 688 } 689 } 690} 691