MethodDefinition.java revision 7ab77bc90be62b0688c97d4476e3bd219eace0da
1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/* 2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * [The "BSD licence"] 3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Copyright (c) 2009 Ben Gruver 4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * All rights reserved. 5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Redistribution and use in source and binary forms, with or without 7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * modification, are permitted provided that the following conditions 8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * are met: 9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 1. Redistributions of source code must retain the above copyright 10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * notice, this list of conditions and the following disclaimer. 11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 2. Redistributions in binary form must reproduce the above copyright 12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * notice, this list of conditions and the following disclaimer in the 13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * documentation and/or other materials provided with the distribution. 14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 3. The name of the author may not be used to endorse or promote products 15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * derived from this software without specific prior written permission. 16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * 17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */ 28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgpackage org.jf.baksmali.Adaptors; 30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgimport org.jf.baksmali.Adaptors.Format.*; 32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgimport org.jf.dexlib.*; 33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgimport org.jf.dexlib.Debug.DebugInstructionIterator; 34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgimport org.jf.dexlib.Code.Format.*; 35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgimport org.jf.dexlib.Code.Instruction; 36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgimport org.jf.dexlib.Code.Opcode; 37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgimport org.jf.dexlib.Code.InstructionIterator; 38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgimport org.jf.dexlib.Util.AccessFlags; 39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgimport org.antlr.stringtemplate.StringTemplateGroup; 40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgimport org.antlr.stringtemplate.StringTemplate; 41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgimport java.util.*; 43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgpublic class MethodDefinition { 45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org public static StringTemplate makeTemplate(StringTemplateGroup stg, ClassDataItem.EncodedMethod encodedMethod, 46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org AnnotationSetItem annotationSet, 47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org AnnotationSetRefList parameterAnnotations) { 48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org CodeItem codeItem = encodedMethod.codeItem; 50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org StringTemplate template = stg.getInstanceOf("method"); 52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org 53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org template.setAttribute("AccessFlags", getAccessFlags(encodedMethod)); 54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org template.setAttribute("MethodName", encodedMethod.method.getMethodName().getStringValue()); 55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org template.setAttribute("Prototype", encodedMethod.method.getPrototype().getPrototypeString()); 56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org template.setAttribute("HasCode", codeItem != null); 57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org template.setAttribute("RegisterCount", codeItem==null?"0":Integer.toString(codeItem.getRegisterCount())); 58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org template.setAttribute("Parameters", getParameters(stg, codeItem, parameterAnnotations)); 59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org template.setAttribute("Annotations", getAnnotations(stg, annotationSet)); 60 template.setAttribute("MethodItems", getMethodItems(encodedMethod.method.getDexFile(), stg, codeItem)); 61 62 return template; 63 } 64 65 private static List<String> getAccessFlags(ClassDataItem.EncodedMethod encodedMethod) { 66 List<String> accessFlags = new ArrayList<String>(); 67 68 for (AccessFlags accessFlag: AccessFlags.getAccessFlagsForMethod(encodedMethod.accessFlags)) { 69 accessFlags.add(accessFlag.toString()); 70 } 71 72 return accessFlags; 73 } 74 75 private static List<StringTemplate> getParameters(StringTemplateGroup stg, CodeItem codeItem, 76 AnnotationSetRefList parameterAnnotations) { 77 DebugInfoItem debugInfoItem = null; 78 if (codeItem != null) { 79 debugInfoItem = codeItem.getDebugInfo(); 80 } 81 82 int parameterCount = 0; 83 84 List<AnnotationSetItem> annotations = new ArrayList<AnnotationSetItem>(); 85 if (parameterAnnotations != null) { 86 AnnotationSetItem[] _annotations = parameterAnnotations.getAnnotationSets(); 87 if (_annotations != null) { 88 annotations.addAll(Arrays.asList(_annotations)); 89 } 90 91 parameterCount = annotations.size(); 92 } 93 94 List<String> parameterNames = new ArrayList<String>(); 95 if (debugInfoItem != null) { 96 StringIdItem[] _parameterNames = debugInfoItem.getParameterNames(); 97 if (_parameterNames != null) { 98 for (StringIdItem parameterName: _parameterNames) { 99 parameterNames.add(parameterName==null?null:parameterName.getStringValue()); 100 } 101 } 102 103 if (parameterCount < parameterNames.size()) { 104 parameterCount = parameterNames.size(); 105 } 106 } 107 108 List<StringTemplate> parameters = new ArrayList<StringTemplate>(); 109 for (int i=0; i<parameterCount; i++) { 110 AnnotationSetItem annotationSet = null; 111 if (i < annotations.size()) { 112 annotationSet = annotations.get(i); 113 } 114 115 String parameterName = null; 116 if (i < parameterNames.size()) { 117 parameterName = parameterNames.get(i); 118 } 119 120 parameters.add(ParameterAdaptor.makeTemplate(stg, parameterName, annotationSet)); 121 } 122 123 return parameters; 124 } 125 126 private static List<StringTemplate> getAnnotations(StringTemplateGroup stg, AnnotationSetItem annotationSet) { 127 if (annotationSet == null) { 128 return null; 129 } 130 131 List<StringTemplate> annotationAdaptors = new ArrayList<StringTemplate>(); 132 133 for (AnnotationItem annotationItem: annotationSet.getAnnotations()) { 134 annotationAdaptors.add(AnnotationAdaptor.makeTemplate(stg, annotationItem)); 135 } 136 return annotationAdaptors; 137 } 138 139 private static List<MethodItem> getMethodItems(DexFile dexFile, StringTemplateGroup stg, CodeItem codeItem) { 140 List<MethodItem> methodItems = new ArrayList<MethodItem>(); 141 142 MethodItemList methodItemList = new MethodItemList(dexFile, stg, codeItem); 143 methodItemList.generateMethodItemList(); 144 145 methodItems.addAll(methodItemList.labels); 146 methodItems.addAll(methodItemList.instructions); 147 methodItems.addAll(methodItemList.blanks); 148 methodItems.addAll(methodItemList.catches); 149 methodItems.addAll(methodItemList.debugItems); 150 Collections.sort(methodItems); 151 152 return methodItems; 153 } 154 155 156 private static class MethodItemList { 157 private final DexFile dexFile; 158 private final StringTemplateGroup stg; 159 private final CodeItem codeItem; 160 161 public HashSet<LabelMethodItem> labels = new HashSet<LabelMethodItem>(); 162 public List<MethodItem> instructions = new ArrayList<MethodItem>(); 163 public List<BlankMethodItem> blanks = new ArrayList<BlankMethodItem>(); 164 public List<CatchMethodItem> catches = new ArrayList<CatchMethodItem>(); 165 public List<MethodItem> debugItems = new ArrayList<MethodItem>(); 166 167 private HashMap<Integer, Integer> packedSwitchMap = new HashMap<Integer, Integer>(); 168 private HashMap<Integer, Integer> sparseSwitchMap = new HashMap<Integer, Integer>(); 169 170 public MethodItemList(DexFile dexFile, StringTemplateGroup stg, CodeItem codeItem) { 171 this.dexFile = dexFile; 172 this.stg = stg; 173 this.codeItem = codeItem; 174 } 175 176 public void generateMethodItemList() { 177 if (codeItem == null) { 178 return; 179 } 180 181 final byte[] encodedInstructions = codeItem.getEncodedInstructions(); 182 183 InstructionIterator.IterateInstructions(encodedInstructions, 184 new InstructionIterator.ProcessRawInstructionDelegate() { 185 public void ProcessNormalInstruction(Opcode opcode, int index) { 186 if (opcode == Opcode.PACKED_SWITCH) { 187 Instruction31t ins = (Instruction31t)opcode.format.Factory.makeInstruction( 188 dexFile, opcode, encodedInstructions, index); 189 packedSwitchMap.put(index/2 + ins.getOffset(), index/2); 190 } else if (opcode == Opcode.SPARSE_SWITCH) { 191 Instruction31t ins = (Instruction31t)opcode.format.Factory.makeInstruction( 192 dexFile, opcode, encodedInstructions, index); 193 sparseSwitchMap.put(index/2 + ins.getOffset(), index/2); 194 } 195 } 196 197 public void ProcessReferenceInstruction(Opcode opcode, int index) { 198 } 199 200 public void ProcessPackedSwitchInstruction(int index, int targetCount, int instructionLength) { 201 } 202 203 public void ProcessSparseSwitchInstruction(int index, int targetCount, int instructionLength) { 204 } 205 206 public void ProcessFillArrayDataInstruction(int index, int elementWidth, int elementCount, 207 int instructionLength) { 208 } 209 }); 210 211 InstructionIterator.IterateInstructions(dexFile, encodedInstructions, 212 new InstructionIterator.ProcessInstructionDelegate() { 213 public void ProcessInstruction(int index, Instruction instruction) { 214 int offset = index/2; 215 addMethodItemsForInstruction(offset, instruction); 216 blanks.add(new BlankMethodItem(stg, offset)); 217 } 218 }); 219 220 blanks.remove(blanks.size()-1); 221 222 addTries(); 223 224 addDebugInfo(); 225 } 226 227 private void addMethodItemsForInstruction(int offset, Instruction instruction) { 228 switch (instruction.getFormat()) { 229 case Format10t: 230 instructions.add(new Instruction10tMethodItem(offset, stg,(Instruction10t)instruction)); 231 labels.add(new LabelMethodItem(offset + ((Instruction10t)instruction).getOffset(), stg, "goto_")); 232 return; 233 case Format10x: 234 instructions.add(new Instruction10xMethodItem(offset, stg, (Instruction10x)instruction)); 235 return; 236 case Format11n: 237 instructions.add(new Instruction11nMethodItem(offset, stg, (Instruction11n)instruction)); 238 return; 239 case Format11x: 240 instructions.add(new Instruction11xMethodItem(offset, stg, (Instruction11x)instruction)); 241 return; 242 case Format12x: 243 instructions.add(new Instruction12xMethodItem(offset, stg, (Instruction12x)instruction)); 244 return; 245 case Format20t: 246 instructions.add(new Instruction20tMethodItem(offset, stg, (Instruction20t)instruction)); 247 labels.add(new LabelMethodItem(offset + ((Instruction20t)instruction).getOffset(), stg, "goto_")); 248 return; 249 case Format21c: 250 instructions.add(new Instruction21cMethodItem(offset, stg, (Instruction21c)instruction)); 251 return; 252 case Format21h: 253 instructions.add(new Instruction21hMethodItem(offset, stg, (Instruction21h)instruction)); 254 return; 255 case Format21s: 256 instructions.add(new Instruction21sMethodItem(offset, stg, (Instruction21s)instruction)); 257 return; 258 case Format21t: 259 instructions.add(new Instruction21tMethodItem(offset, stg, (Instruction21t)instruction)); 260 labels.add(new LabelMethodItem(offset + ((Instruction21t)instruction).getOffset(), stg, "cond_")); 261 return; 262 case Format22b: 263 instructions.add(new Instruction22bMethodItem(offset, stg, (Instruction22b)instruction)); 264 return; 265 case Format22c: 266 instructions.add(new Instruction22cMethodItem(offset, stg, (Instruction22c)instruction)); 267 return; 268 case Format22s: 269 instructions.add(new Instruction22sMethodItem(offset, stg, (Instruction22s)instruction)); 270 return; 271 case Format22t: 272 instructions.add(new Instruction22tMethodItem(offset, stg, (Instruction22t)instruction)); 273 labels.add(new LabelMethodItem(offset + ((Instruction22t)instruction).getOffset(), stg, "cond_")); 274 return; 275 case Format22x: 276 instructions.add(new Instruction22xMethodItem(offset, stg, (Instruction22x)instruction)); 277 return; 278 case Format23x: 279 instructions.add(new Instruction23xMethodItem(offset, stg, (Instruction23x)instruction)); 280 return; 281 case Format30t: 282 instructions.add(new Instruction30tMethodItem(offset, stg, (Instruction30t)instruction)); 283 labels.add(new LabelMethodItem(offset + ((Instruction30t)instruction).getOffset(), stg, "goto_")); 284 return; 285 case Format31c: 286 instructions.add(new Instruction31cMethodItem(offset, stg, (Instruction31c)instruction)); 287 return; 288 case Format31i: 289 instructions.add(new Instruction31iMethodItem(offset, stg, (Instruction31i)instruction)); 290 return; 291 case Format31t: 292 instructions.add(new Instruction31tMethodItem(offset, stg, (Instruction31t)instruction)); 293 if (instruction.opcode == Opcode.FILL_ARRAY_DATA) { 294 labels.add(new LabelMethodItem(offset + ((Instruction31t)instruction).getOffset(), stg, 295 "array_")); 296 } else if (instruction.opcode == Opcode.PACKED_SWITCH) { 297 labels.add(new LabelMethodItem(offset + ((Instruction31t)instruction).getOffset(), stg, 298 "pswitch_data_")); 299 } else if (instruction.opcode == Opcode.SPARSE_SWITCH) { 300 labels.add(new LabelMethodItem(offset + ((Instruction31t)instruction).getOffset(), stg, 301 "sswitch_data_")); 302 } 303 return; 304 case Format32x: 305 instructions.add(new Instruction32xMethodItem(offset, stg, (Instruction32x)instruction)); 306 return; 307 case Format35c: 308 instructions.add(new Instruction35cMethodItem(offset, stg, (Instruction35c)instruction)); 309 return; 310 case Format3rc: 311 instructions.add(new Instruction3rcMethodItem(offset, stg, (Instruction3rc)instruction)); 312 return; 313 case Format51l: 314 instructions.add(new Instruction51lMethodItem(offset, stg, (Instruction51l)instruction)); 315 return; 316 case ArrayData: 317 instructions.add(new ArrayDataMethodItem(offset, stg, (ArrayDataPseudoInstruction)instruction)); 318 return; 319 case PackedSwitchData: 320 { 321 final Integer baseAddress = packedSwitchMap.get(offset); 322 323 if (baseAddress != null) { 324 PackedSwitchDataPseudoInstruction packedSwitchInstruction = 325 (PackedSwitchDataPseudoInstruction)instruction; 326 327 instructions.add(new PackedSwitchMethodItem(offset, stg, 328 packedSwitchInstruction, baseAddress)); 329 330 Iterator<PackedSwitchDataPseudoInstruction.PackedSwitchTarget> iterator = 331 packedSwitchInstruction.getTargets(); 332 while (iterator.hasNext()) { 333 PackedSwitchDataPseudoInstruction.PackedSwitchTarget target = iterator.next(); 334 labels.add(new LabelMethodItem(baseAddress + target.target, stg, "pswitch_")); 335 } 336 } 337 return; 338 } 339 case SparseSwitchData: 340 { 341 final Integer baseAddress = sparseSwitchMap.get(offset); 342 343 if (baseAddress != null) { 344 SparseSwitchDataPseudoInstruction sparseSwitchInstruction = 345 (SparseSwitchDataPseudoInstruction)instruction; 346 347 instructions.add(new SparseSwitchMethodItem(offset, stg, 348 sparseSwitchInstruction, baseAddress)); 349 350 Iterator<SparseSwitchDataPseudoInstruction.SparseSwitchTarget> iterator = 351 sparseSwitchInstruction.getTargets(); 352 while (iterator.hasNext()) { 353 SparseSwitchDataPseudoInstruction.SparseSwitchTarget target = iterator.next(); 354 labels.add(new LabelMethodItem(baseAddress + target.target, stg, "sswitch_")); 355 } 356 } 357 } 358 } 359 } 360 361 private void addTries() { 362 if (codeItem.getTries() == null) { 363 return; 364 } 365 for (CodeItem.TryItem tryItem: codeItem.getTries()) { 366 int startAddress = tryItem.startAddress; 367 int endAddress = tryItem.startAddress + tryItem.instructionCount; 368 369 /** 370 * The end address points to the address immediately after the end of the last 371 * instruction that the try block covers. We want the .catch directive and end_try 372 * label to be associated with the last covered instruction, so we need to get 373 * the offset for that instruction 374 */ 375 int index = Collections.binarySearch(instructions, new BlankMethodItem(stg, endAddress)); 376 if (index < 0) { 377 index = (index * -1) - 1; 378 } 379 //index should never by 0, so this should be safe 380 if (index == instructions.size()) { 381 //if the end address is the same as the address of the last instruction, then 382 //this try item ends at the next to last instruction. 383 //otherwise, if the end address is past the address of the last instruction, 384 //thin this try item ends at the last instruction 385 if (instructions.get(instructions.size() - 1).getOffset() == endAddress) { 386 //get the address for the next to last instruction 387 index -= 2; 388 } else { 389 //get the address for the last instruction 390 index--; 391 } 392 } else { 393 index -= 2; 394 } 395 396 int lastInstructionOffset = instructions.get(index).getOffset(); 397 398 //add the catch all handler if it exists 399 int catchAllAddress = tryItem.encodedCatchHandler.catchAllHandlerAddress; 400 if (catchAllAddress != -1) { 401 CatchMethodItem catchMethodItem = new CatchMethodItem(lastInstructionOffset, stg, null, 402 startAddress, endAddress, catchAllAddress) { 403 public String getTemplateName() { 404 return "CatchAll"; 405 } 406 }; 407 catches.add(catchMethodItem); 408 409 labels.add(new LabelMethodItem(startAddress, stg, "try_start_")); 410 //use the offset from the last covered instruction, but make the label 411 //name refer to the address of the next instruction 412 labels.add(new EndTryLabelMethodItem(lastInstructionOffset, stg, endAddress)); 413 labels.add(new LabelMethodItem(catchAllAddress, stg, "handler_")); 414 415 } 416 417 //add the rest of the handlers 418 //TODO: find adjacent handlers for the same type and combine them 419 for (CodeItem.EncodedTypeAddrPair handler: tryItem.encodedCatchHandler.handlers) { 420 //use the offset from the last covered instruction 421 CatchMethodItem catchMethodItem = new CatchMethodItem(lastInstructionOffset, stg, 422 handler.exceptionType, startAddress, endAddress, handler.handlerAddress); 423 catches.add(catchMethodItem); 424 425 labels.add(new LabelMethodItem(startAddress, stg, "try_start_")); 426 //use the offset from the last covered instruction, but make the label 427 //name refer to the address of the next instruction 428 labels.add(new EndTryLabelMethodItem(lastInstructionOffset, stg, endAddress)); 429 labels.add(new LabelMethodItem(handler.handlerAddress, stg, "handler_")); 430 } 431 } 432 } 433 434 private void addDebugInfo() { 435 DebugInfoItem debugInfoItem = codeItem.getDebugInfo(); 436 if (debugInfoItem == null) { 437 return; 438 } 439 440 DebugInstructionIterator.DecodeInstructions(debugInfoItem, codeItem.getRegisterCount(), 441 new DebugInstructionIterator.ProcessDecodedDebugInstructionDelegate() { 442 @Override 443 public void ProcessStartLocal(int codeAddress, int length, int registerNum, StringIdItem name, 444 TypeIdItem type) { 445 debugItems.add(new LocalDebugMethodItem(codeAddress, stg, "StartLocal", -1, registerNum, 446 name, type, null)); 447 } 448 449 @Override 450 public void ProcessStartLocalExtended(int codeAddress, int length, int registerNum, 451 StringIdItem name, TypeIdItem type, 452 StringIdItem signature) { 453 debugItems.add(new LocalDebugMethodItem(codeAddress, stg, "StartLocal", -1, registerNum, 454 name, type, signature)); 455 } 456 457 @Override 458 public void ProcessEndLocal(int codeAddress, int length, int registerNum, StringIdItem name, 459 TypeIdItem type, StringIdItem signature) { 460 debugItems.add(new LocalDebugMethodItem(codeAddress, stg, "EndLocal", -1, registerNum, name, 461 type, signature)); 462 } 463 464 @Override 465 public void ProcessRestartLocal(int codeAddress, int length, int registerNum, StringIdItem name, 466 TypeIdItem type, StringIdItem signature) { 467 debugItems.add(new LocalDebugMethodItem(codeAddress, stg, "RestartLocal", -1, registerNum, 468 name, type, signature)); 469 } 470 471 @Override 472 public void ProcessSetPrologueEnd(int codeAddress) { 473 debugItems.add(new DebugMethodItem(codeAddress, stg, "EndPrologue", -4)); 474 } 475 476 @Override 477 public void ProcessSetEpilogueBegin(int codeAddress) { 478 debugItems.add(new DebugMethodItem(codeAddress, stg, "StartEpilogue", -4)); 479 } 480 481 @Override 482 public void ProcessSetFile(int codeAddress, int length, final StringIdItem name) { 483 debugItems.add(new DebugMethodItem(codeAddress, stg, "SetFile", -3) { 484 @Override 485 protected void setAttributes(StringTemplate template) { 486 template.setAttribute("FileName", name.getStringValue()); 487 } 488 }); 489 } 490 491 @Override 492 public void ProcessLineEmit(int codeAddress, final int line) { 493 debugItems.add(new DebugMethodItem(codeAddress, stg, "Line", -2) { 494 @Override 495 protected void setAttributes(StringTemplate template) { 496 template.setAttribute("Line", line); 497 } 498 }); 499 } 500 }); 501 } 502 } 503} 504