MethodDefinition.java revision ff80035f438dd2a70330931bb87e37bb8b42f9e0
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.InstructionIterator; 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 int temp = encodedMethod.method.getPrototype().getParameterRegisterCount(); 53 54 StringTemplate template = stg.getInstanceOf("method"); 55 56 template.setAttribute("AccessFlags", getAccessFlags(encodedMethod)); 57 template.setAttribute("MethodName", encodedMethod.method.getMethodName().getStringValue()); 58 template.setAttribute("Prototype", encodedMethod.method.getPrototype().getPrototypeString()); 59 template.setAttribute("HasCode", codeItem != null); 60 template.setAttribute("RegistersDirective", baksmali.useLocalsDirective?".locals":".registers"); 61 template.setAttribute("RegisterCount", codeItem==null?"0":Integer.toString(getRegisterCount(encodedMethod))); 62 template.setAttribute("Parameters", getParameters(stg, codeItem, parameterAnnotations)); 63 template.setAttribute("Annotations", getAnnotations(stg, annotationSet)); 64 template.setAttribute("MethodItems", getMethodItems(encodedMethod.method.getDexFile(), stg, codeItem)); 65 66 return template; 67 } 68 69 private static int getRegisterCount(ClassDataItem.EncodedMethod encodedMethod) 70 { 71 int totalRegisters = encodedMethod.codeItem.getRegisterCount(); 72 if (baksmali.useLocalsDirective) { 73 int parameterRegisters = encodedMethod.method.getPrototype().getParameterRegisterCount(); 74 if ((encodedMethod.accessFlags & AccessFlags.STATIC.getValue()) == 0) { 75 parameterRegisters++; 76 } 77 return totalRegisters - parameterRegisters; 78 } 79 return totalRegisters; 80 } 81 82 private static List<String> getAccessFlags(ClassDataItem.EncodedMethod encodedMethod) { 83 List<String> accessFlags = new ArrayList<String>(); 84 85 for (AccessFlags accessFlag: AccessFlags.getAccessFlagsForMethod(encodedMethod.accessFlags)) { 86 accessFlags.add(accessFlag.toString()); 87 } 88 89 return accessFlags; 90 } 91 92 private static List<StringTemplate> getParameters(StringTemplateGroup stg, CodeItem codeItem, 93 AnnotationSetRefList parameterAnnotations) { 94 DebugInfoItem debugInfoItem = null; 95 if (codeItem != null) { 96 debugInfoItem = codeItem.getDebugInfo(); 97 } 98 99 int parameterCount = 0; 100 101 List<AnnotationSetItem> annotations = new ArrayList<AnnotationSetItem>(); 102 if (parameterAnnotations != null) { 103 AnnotationSetItem[] _annotations = parameterAnnotations.getAnnotationSets(); 104 if (_annotations != null) { 105 annotations.addAll(Arrays.asList(_annotations)); 106 } 107 108 parameterCount = annotations.size(); 109 } 110 111 List<String> parameterNames = new ArrayList<String>(); 112 if (debugInfoItem != null) { 113 StringIdItem[] _parameterNames = debugInfoItem.getParameterNames(); 114 if (_parameterNames != null) { 115 for (StringIdItem parameterName: _parameterNames) { 116 parameterNames.add(parameterName==null?null:parameterName.getStringValue()); 117 } 118 } 119 120 if (parameterCount < parameterNames.size()) { 121 parameterCount = parameterNames.size(); 122 } 123 } 124 125 List<StringTemplate> parameters = new ArrayList<StringTemplate>(); 126 for (int i=0; i<parameterCount; i++) { 127 AnnotationSetItem annotationSet = null; 128 if (i < annotations.size()) { 129 annotationSet = annotations.get(i); 130 } 131 132 String parameterName = null; 133 if (i < parameterNames.size()) { 134 parameterName = parameterNames.get(i); 135 } 136 137 parameters.add(ParameterAdaptor.makeTemplate(stg, parameterName, annotationSet)); 138 } 139 140 return parameters; 141 } 142 143 private static List<StringTemplate> getAnnotations(StringTemplateGroup stg, AnnotationSetItem annotationSet) { 144 if (annotationSet == null) { 145 return null; 146 } 147 148 List<StringTemplate> annotationAdaptors = new ArrayList<StringTemplate>(); 149 150 for (AnnotationItem annotationItem: annotationSet.getAnnotations()) { 151 annotationAdaptors.add(AnnotationAdaptor.makeTemplate(stg, annotationItem)); 152 } 153 return annotationAdaptors; 154 } 155 156 private static List<MethodItem> getMethodItems(DexFile dexFile, StringTemplateGroup stg, CodeItem codeItem) { 157 List<MethodItem> methodItems = new ArrayList<MethodItem>(); 158 159 MethodItemList methodItemList = new MethodItemList(dexFile, stg, codeItem); 160 methodItemList.generateMethodItemList(); 161 162 methodItems.addAll(methodItemList.labels.values()); 163 methodItems.addAll(methodItemList.instructions); 164 methodItems.addAll(methodItemList.blanks); 165 methodItems.addAll(methodItemList.catches); 166 methodItems.addAll(methodItemList.debugItems); 167 Collections.sort(methodItems); 168 169 return methodItems; 170 } 171 172 173 private static class MethodItemList { 174 private final DexFile dexFile; 175 private final StringTemplateGroup stg; 176 private final CodeItem codeItem; 177 178 public HashMap<LabelMethodItem, LabelMethodItem> labels = new HashMap<LabelMethodItem, LabelMethodItem>(); 179 public List<MethodItem> instructions = new ArrayList<MethodItem>(); 180 public List<BlankMethodItem> blanks = new ArrayList<BlankMethodItem>(); 181 public List<CatchMethodItem> catches = new ArrayList<CatchMethodItem>(); 182 public List<MethodItem> debugItems = new ArrayList<MethodItem>(); 183 184 private HashMap<Integer, Integer> packedSwitchMap = new HashMap<Integer, Integer>(); 185 private HashMap<Integer, Integer> sparseSwitchMap = new HashMap<Integer, Integer>(); 186 187 public MethodItemList(DexFile dexFile, StringTemplateGroup stg, CodeItem codeItem) { 188 this.dexFile = dexFile; 189 this.stg = stg; 190 this.codeItem = codeItem; 191 } 192 193 public void generateMethodItemList() { 194 if (codeItem == null) { 195 return; 196 } 197 198 if (baksmali.deodexUtil != null && dexFile.isOdex()) { 199 List<Instruction> instructions = baksmali.deodexUtil.deodexerizeCode(codeItem); 200 201 int offset = 0; 202 for (Instruction instruction: instructions) { 203 if (instruction.opcode == Opcode.PACKED_SWITCH) { 204 Instruction31t ins = (Instruction31t)instruction; 205 packedSwitchMap.put(offset + ins.getOffset(), offset); 206 } else if (instruction.opcode == Opcode.SPARSE_SWITCH) { 207 Instruction31t ins = (Instruction31t)instruction; 208 sparseSwitchMap.put(offset + ins.getOffset(), offset); 209 } 210 211 offset += instruction.getSize()/2; 212 } 213 214 offset = 0; 215 for (Instruction instruction: instructions) { 216 addMethodItemsForInstruction(offset, instruction, false, null); 217 blanks.add(new BlankMethodItem(stg, offset)); 218 219 offset += instruction.getSize()/2; 220 } 221 } else { 222 final byte[] encodedInstructions = codeItem.getEncodedInstructions(); 223 224 InstructionIterator.IterateInstructions(encodedInstructions, 225 new InstructionIterator.ProcessRawInstructionDelegate() { 226 public void ProcessNormalInstruction(Opcode opcode, int index) { 227 if (opcode == Opcode.PACKED_SWITCH) { 228 Instruction31t ins = (Instruction31t)opcode.format.Factory.makeInstruction( 229 dexFile, opcode, encodedInstructions, index); 230 packedSwitchMap.put(index/2 + ins.getOffset(), index/2); 231 } else if (opcode == Opcode.SPARSE_SWITCH) { 232 Instruction31t ins = (Instruction31t)opcode.format.Factory.makeInstruction( 233 dexFile, opcode, encodedInstructions, index); 234 sparseSwitchMap.put(index/2 + ins.getOffset(), index/2); 235 } 236 } 237 238 public void ProcessReferenceInstruction(Opcode opcode, int index) { 239 } 240 241 public void ProcessPackedSwitchInstruction(int index, int targetCount, int instructionLength) { 242 } 243 244 public void ProcessSparseSwitchInstruction(int index, int targetCount, int instructionLength) { 245 } 246 247 public void ProcessFillArrayDataInstruction(int index, int elementWidth, int elementCount, 248 int instructionLength) { 249 } 250 }); 251 252 InstructionIterator.IterateInstructions(dexFile, encodedInstructions, 253 new InstructionIterator.ProcessInstructionDelegate() { 254 public void ProcessInstruction(int index, Instruction instruction) { 255 int offset = index/2; 256 addMethodItemsForInstruction(offset, instruction, false, null); 257 blanks.add(new BlankMethodItem(stg, offset)); 258 } 259 }); 260 } 261 262 blanks.remove(blanks.size()-1); 263 264 addTries(); 265 266 addDebugInfo(); 267 } 268 269 private void addInstructionMethodItem(InstructionFormatMethodItem methodItem, boolean commentedOut, 270 String comment) { 271 if (commentedOut) { 272 instructions.add(new CommentedOutMethodItem(stg, methodItem)); 273 } else { 274 instructions.add(methodItem); 275 } 276 } 277 278 private void addLabelMethodItem(LabelMethodItem labelMethodItem) { 279 LabelMethodItem internedLabelMethodItem = labels.get(labelMethodItem); 280 if (internedLabelMethodItem != null) { 281 if (!labelMethodItem.isCommentedOut() && internedLabelMethodItem.isCommentedOut()) { 282 internedLabelMethodItem.setCommentedOut(false); 283 } 284 } else { 285 labels.put(labelMethodItem, labelMethodItem); 286 } 287 } 288 289 private void addMethodItemsForInstruction(int offset, Instruction instruction, boolean commentedOut, 290 String comment) { 291 switch (instruction.getFormat()) { 292 case Format10t: 293 addInstructionMethodItem( 294 new Instruction10tMethodItem(codeItem, offset, stg,(Instruction10t)instruction), 295 commentedOut, comment); 296 addLabelMethodItem(new LabelMethodItem(offset + ((Instruction10t)instruction).getOffset(), stg, 297 "goto_", commentedOut)); 298 return; 299 case Format10x: 300 addInstructionMethodItem( 301 new Instruction10xMethodItem(codeItem, offset, stg, (Instruction10x)instruction), 302 commentedOut, comment); 303 return; 304 case Format11n: 305 addInstructionMethodItem( 306 new Instruction11nMethodItem(codeItem, offset, stg, (Instruction11n)instruction), 307 commentedOut, comment); 308 return; 309 case Format11x: 310 addInstructionMethodItem( 311 new Instruction11xMethodItem(codeItem, offset, stg, (Instruction11x)instruction), 312 commentedOut, comment); 313 return; 314 case Format12x: 315 addInstructionMethodItem( 316 new Instruction12xMethodItem(codeItem, offset, stg, (Instruction12x)instruction), 317 commentedOut, comment); 318 return; 319 case Format20t: 320 addInstructionMethodItem( 321 new Instruction20tMethodItem(codeItem, offset, stg, (Instruction20t)instruction), 322 commentedOut, comment); 323 addLabelMethodItem(new LabelMethodItem(offset + ((Instruction20t)instruction).getOffset(), stg, 324 "goto_", commentedOut)); 325 return; 326 case Format21c: 327 addInstructionMethodItem( 328 new Instruction21cMethodItem(codeItem, offset, stg, (Instruction21c)instruction), 329 commentedOut, comment); 330 return; 331 case Format21h: 332 addInstructionMethodItem( 333 new Instruction21hMethodItem(codeItem, offset, stg, (Instruction21h)instruction), 334 commentedOut, comment); 335 return; 336 case Format21s: 337 addInstructionMethodItem( 338 new Instruction21sMethodItem(codeItem, offset, stg, (Instruction21s)instruction), 339 commentedOut, comment); 340 return; 341 case Format21t: 342 addInstructionMethodItem( 343 new Instruction21tMethodItem(codeItem, offset, stg, (Instruction21t)instruction), 344 commentedOut, comment); 345 addLabelMethodItem(new LabelMethodItem(offset + ((Instruction21t)instruction).getOffset(), stg, 346 "cond_", commentedOut)); 347 return; 348 case Format22b: 349 addInstructionMethodItem( 350 new Instruction22bMethodItem(codeItem, offset, stg, (Instruction22b)instruction), 351 commentedOut, comment); 352 return; 353 case Format22c: 354 addInstructionMethodItem( 355 new Instruction22cMethodItem(codeItem, offset, stg, (Instruction22c)instruction), 356 commentedOut, comment); 357 return; 358 case Format22cs: 359 addInstructionMethodItem( 360 new Instruction22csMethodItem(codeItem, offset, stg, (Instruction22cs)instruction), 361 commentedOut, comment); 362 return; 363 case Format22csf: 364 addInstructionMethodItem( 365 new Instruction22csfMethodItem(codeItem, offset, stg, (Instruction22csf)instruction), 366 commentedOut, comment); 367 return; 368 case Format22s: 369 addInstructionMethodItem( 370 new Instruction22sMethodItem(codeItem, offset, stg, (Instruction22s)instruction), 371 commentedOut, comment); 372 return; 373 case Format22t: 374 addInstructionMethodItem( 375 new Instruction22tMethodItem(codeItem, offset, stg, (Instruction22t)instruction), 376 commentedOut, comment); 377 addLabelMethodItem(new LabelMethodItem(offset + ((Instruction22t)instruction).getOffset(), stg, 378 "cond_", commentedOut)); 379 return; 380 case Format22x: 381 addInstructionMethodItem( 382 new Instruction22xMethodItem(codeItem, offset, stg, (Instruction22x)instruction), 383 commentedOut, comment); 384 return; 385 case Format23x: 386 addInstructionMethodItem( 387 new Instruction23xMethodItem(codeItem, offset, stg, (Instruction23x)instruction), 388 commentedOut, comment); 389 return; 390 case Format30t: 391 addInstructionMethodItem( 392 new Instruction30tMethodItem(codeItem, offset, stg, (Instruction30t)instruction), 393 commentedOut, comment); 394 addLabelMethodItem(new LabelMethodItem(offset + ((Instruction30t)instruction).getOffset(), stg, 395 "goto_", commentedOut)); 396 return; 397 case Format31c: 398 addInstructionMethodItem( 399 new Instruction31cMethodItem(codeItem, offset, stg, (Instruction31c)instruction), 400 commentedOut, comment); 401 return; 402 case Format31i: 403 addInstructionMethodItem( 404 new Instruction31iMethodItem(codeItem, offset, stg, (Instruction31i)instruction), 405 commentedOut, comment); 406 return; 407 case Format31t: 408 addInstructionMethodItem( 409 new Instruction31tMethodItem(codeItem, offset, stg, (Instruction31t)instruction), 410 commentedOut, comment); 411 if (instruction.opcode == Opcode.FILL_ARRAY_DATA) { 412 addLabelMethodItem(new LabelMethodItem(offset + ((Instruction31t)instruction).getOffset(), stg, 413 "array_", commentedOut)); 414 } else if (instruction.opcode == Opcode.PACKED_SWITCH) { 415 addLabelMethodItem(new LabelMethodItem(offset + ((Instruction31t)instruction).getOffset(), stg, 416 "pswitch_data_", commentedOut)); 417 } else if (instruction.opcode == Opcode.SPARSE_SWITCH) { 418 addLabelMethodItem(new LabelMethodItem(offset + ((Instruction31t)instruction).getOffset(), stg, 419 "sswitch_data_", commentedOut)); 420 } 421 return; 422 case Format32x: 423 addInstructionMethodItem( 424 new Instruction32xMethodItem(codeItem, offset, stg, (Instruction32x)instruction), 425 commentedOut, comment); 426 return; 427 case Format35c: 428 addInstructionMethodItem( 429 new Instruction35cMethodItem(codeItem, offset, stg, (Instruction35c)instruction), 430 commentedOut, comment); 431 return; 432 case Format35s: 433 addInstructionMethodItem( 434 new Instruction35sMethodItem(codeItem, offset, stg, (Instruction35s)instruction), 435 commentedOut, comment); 436 return; 437 case Format35sf: 438 addInstructionMethodItem( 439 new Instruction35sfMethodItem(codeItem, offset, stg, (Instruction35sf)instruction), 440 commentedOut, comment); 441 return; 442 case Format35ms: 443 addInstructionMethodItem( 444 new Instruction35msMethodItem(codeItem, offset, stg, (Instruction35ms)instruction), 445 commentedOut, comment); 446 return; 447 case Format35msf: 448 addInstructionMethodItem( 449 new Instruction35msfMethodItem(codeItem, offset, stg, (Instruction35msf)instruction), 450 commentedOut, comment); 451 return; 452 case Format3rc: 453 addInstructionMethodItem( 454 new Instruction3rcMethodItem(codeItem, offset, stg, (Instruction3rc)instruction), 455 commentedOut, comment); 456 return; 457 case Format3rms: 458 addInstructionMethodItem( 459 new Instruction3rmsMethodItem(codeItem, offset, stg, (Instruction3rms)instruction), 460 commentedOut, comment); 461 return; 462 case Format3rmsf: 463 addInstructionMethodItem( 464 new Instruction3rmsfMethodItem(codeItem, offset, stg, (Instruction3rmsf)instruction), 465 commentedOut, comment); 466 return; 467 case Format51l: 468 addInstructionMethodItem( 469 new Instruction51lMethodItem(codeItem, offset, stg, (Instruction51l)instruction), 470 commentedOut, comment); 471 return; 472 case ArrayData: 473 addInstructionMethodItem( 474 new ArrayDataMethodItem(codeItem, offset, stg, (ArrayDataPseudoInstruction)instruction), 475 commentedOut, comment); 476 return; 477 case PackedSwitchData: 478 { 479 final Integer baseAddress = packedSwitchMap.get(offset); 480 481 if (baseAddress != null) { 482 PackedSwitchDataPseudoInstruction packedSwitchInstruction = 483 (PackedSwitchDataPseudoInstruction)instruction; 484 485 addInstructionMethodItem( 486 new PackedSwitchMethodItem(codeItem, offset, stg, packedSwitchInstruction, baseAddress), 487 commentedOut, comment); 488 489 Iterator<PackedSwitchDataPseudoInstruction.PackedSwitchTarget> iterator = 490 packedSwitchInstruction.getTargets(); 491 while (iterator.hasNext()) { 492 PackedSwitchDataPseudoInstruction.PackedSwitchTarget target = iterator.next(); 493 addLabelMethodItem(new LabelMethodItem(baseAddress + target.target, stg, "pswitch_", 494 commentedOut)); 495 } 496 } 497 return; 498 } 499 case SparseSwitchData: 500 { 501 final Integer baseAddress = sparseSwitchMap.get(offset); 502 503 if (baseAddress != null) { 504 SparseSwitchDataPseudoInstruction sparseSwitchInstruction = 505 (SparseSwitchDataPseudoInstruction)instruction; 506 507 addInstructionMethodItem( 508 new SparseSwitchMethodItem(codeItem, offset, stg, sparseSwitchInstruction, baseAddress), 509 commentedOut, comment); 510 511 Iterator<SparseSwitchDataPseudoInstruction.SparseSwitchTarget> iterator = 512 sparseSwitchInstruction.getTargets(); 513 while (iterator.hasNext()) { 514 SparseSwitchDataPseudoInstruction.SparseSwitchTarget target = iterator.next(); 515 addLabelMethodItem(new LabelMethodItem(baseAddress + target.target, stg, "sswitch_", 516 commentedOut)); 517 } 518 } 519 return; 520 } 521 case UnresolvedNullReference: 522 { 523 addInstructionMethodItem(new UnresolvedNullReferenceMethodItem(codeItem, offset, stg, 524 (UnresolvedNullReference)instruction), commentedOut, comment); 525 addMethodItemsForInstruction(offset, ((UnresolvedNullReference)instruction).OriginalInstruction, 526 true, null); 527 return; 528 } 529 case DeadInstruction: 530 { 531 //TODO: what about try/catch blocks inside the dead code? those will need to be commented out too. ugh. 532 addMethodItemsForInstruction(offset, ((DeadInstruction)instruction).OriginalInstruction, true, null); 533 return; 534 } 535 } 536 } 537 538 private void addTries() { 539 if (codeItem.getTries() == null) { 540 return; 541 } 542 for (CodeItem.TryItem tryItem: codeItem.getTries()) { 543 int startAddress = tryItem.startAddress; 544 int endAddress = tryItem.startAddress + tryItem.instructionCount; 545 546 /** 547 * The end address points to the address immediately after the end of the last 548 * instruction that the try block covers. We want the .catch directive and end_try 549 * label to be associated with the last covered instruction, so we need to get 550 * the offset for that instruction 551 */ 552 int index = Collections.binarySearch(instructions, new BlankMethodItem(stg, endAddress)); 553 if (index < 0) { 554 index = (index * -1) - 1; 555 } 556 //index should never by 0, so this should be safe 557 if (index == instructions.size()) { 558 //if the end address is the same as the address of the last instruction, then 559 //this try item ends at the next to last instruction. 560 //otherwise, if the end address is past the address of the last instruction, 561 //thin this try item ends at the last instruction 562 if (instructions.get(instructions.size() - 1).getOffset() == endAddress) { 563 //get the address for the next to last instruction 564 index -= 2; 565 } else { 566 //get the address for the last instruction 567 index--; 568 } 569 } else { 570 index -= 2; 571 } 572 573 int lastInstructionOffset = instructions.get(index).getOffset(); 574 575 //add the catch all handler if it exists 576 int catchAllAddress = tryItem.encodedCatchHandler.catchAllHandlerAddress; 577 if (catchAllAddress != -1) { 578 CatchMethodItem catchMethodItem = new CatchMethodItem(lastInstructionOffset, stg, null, 579 startAddress, endAddress, catchAllAddress) { 580 public String getTemplateName() { 581 return "CatchAll"; 582 } 583 }; 584 catches.add(catchMethodItem); 585 586 addLabelMethodItem(new LabelMethodItem(startAddress, stg, "try_start_", false)); 587 //use the offset from the last covered instruction, but make the label 588 //name refer to the address of the next instruction 589 addLabelMethodItem(new EndTryLabelMethodItem(lastInstructionOffset, stg, endAddress)); 590 addLabelMethodItem(new LabelMethodItem(catchAllAddress, stg, "handler_", false)); 591 592 } 593 594 //add the rest of the handlers 595 //TODO: find adjacent handlers for the same type and combine them 596 for (CodeItem.EncodedTypeAddrPair handler: tryItem.encodedCatchHandler.handlers) { 597 //use the offset from the last covered instruction 598 CatchMethodItem catchMethodItem = new CatchMethodItem(lastInstructionOffset, stg, 599 handler.exceptionType, startAddress, endAddress, handler.handlerAddress); 600 catches.add(catchMethodItem); 601 602 addLabelMethodItem(new LabelMethodItem(startAddress, stg, "try_start_", false)); 603 //use the offset from the last covered instruction, but make the label 604 //name refer to the address of the next instruction 605 addLabelMethodItem(new EndTryLabelMethodItem(lastInstructionOffset, stg, endAddress)); 606 addLabelMethodItem(new LabelMethodItem(handler.handlerAddress, stg, "handler_", false)); 607 } 608 } 609 } 610 611 private void addDebugInfo() { 612 DebugInfoItem debugInfoItem = codeItem.getDebugInfo(); 613 if (debugInfoItem == null) { 614 return; 615 } 616 617 DebugInstructionIterator.DecodeInstructions(debugInfoItem, codeItem.getRegisterCount(), 618 new DebugInstructionIterator.ProcessDecodedDebugInstructionDelegate() { 619 @Override 620 public void ProcessStartLocal(int codeAddress, int length, int registerNum, StringIdItem name, 621 TypeIdItem type) { 622 debugItems.add(new LocalDebugMethodItem(codeItem, codeAddress, stg, "StartLocal", -1, 623 registerNum, name, type, null)); 624 } 625 626 @Override 627 public void ProcessStartLocalExtended(int codeAddress, int length, int registerNum, 628 StringIdItem name, TypeIdItem type, 629 StringIdItem signature) { 630 debugItems.add(new LocalDebugMethodItem(codeItem, codeAddress, stg, "StartLocal", -1, 631 registerNum, name, type, signature)); 632 } 633 634 @Override 635 public void ProcessEndLocal(int codeAddress, int length, int registerNum, StringIdItem name, 636 TypeIdItem type, StringIdItem signature) { 637 debugItems.add(new LocalDebugMethodItem(codeItem, codeAddress, stg, "EndLocal", -1, 638 registerNum, name, type, signature)); 639 } 640 641 @Override 642 public void ProcessRestartLocal(int codeAddress, int length, int registerNum, StringIdItem name, 643 TypeIdItem type, StringIdItem signature) { 644 debugItems.add(new LocalDebugMethodItem(codeItem, codeAddress, stg, "RestartLocal", -1, 645 registerNum, name, type, signature)); 646 } 647 648 @Override 649 public void ProcessSetPrologueEnd(int codeAddress) { 650 debugItems.add(new DebugMethodItem(codeAddress, stg, "EndPrologue", -4)); 651 } 652 653 @Override 654 public void ProcessSetEpilogueBegin(int codeAddress) { 655 debugItems.add(new DebugMethodItem(codeAddress, stg, "StartEpilogue", -4)); 656 } 657 658 @Override 659 public void ProcessSetFile(int codeAddress, int length, final StringIdItem name) { 660 debugItems.add(new DebugMethodItem(codeAddress, stg, "SetFile", -3) { 661 @Override 662 protected void setAttributes(StringTemplate template) { 663 template.setAttribute("FileName", name.getStringValue()); 664 } 665 }); 666 } 667 668 @Override 669 public void ProcessLineEmit(int codeAddress, final int line) { 670 debugItems.add(new DebugMethodItem(codeAddress, stg, "Line", -2) { 671 @Override 672 protected void setAttributes(StringTemplate template) { 673 template.setAttribute("Line", line); 674 } 675 }); 676 } 677 }); 678 } 679 } 680} 681