MethodDefinition.java revision 19b601436ac846b039318a69b5d13f4291d0bb45
1eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi/* 2eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi * [The "BSD licence"] 3eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi * Copyright (c) 2010 Ben Gruver (JesusFreke) 4eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi * All rights reserved. 5eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi * 6eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi * Redistribution and use in source and binary forms, with or without 7eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi * modification, are permitted provided that the following conditions 8eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi * are met: 9eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi * 1. Redistributions of source code must retain the above copyright 10eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi * notice, this list of conditions and the following disclaimer. 11eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi * 2. Redistributions in binary form must reproduce the above copyright 12eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi * notice, this list of conditions and the following disclaimer in the 13eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi * documentation and/or other materials provided with the distribution. 14eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi * 3. The name of the author may not be used to endorse or promote products 15eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi * derived from this software without specific prior written permission. 16eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi * 17eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 202b06e20ae32388f6e1dfd088d9773c34e6b1cb45Jean-Michel Trivi * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 212b06e20ae32388f6e1dfd088d9773c34e6b1cb45Jean-Michel Trivi * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 222b06e20ae32388f6e1dfd088d9773c34e6b1cb45Jean-Michel Trivi * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 232b06e20ae32388f6e1dfd088d9773c34e6b1cb45Jean-Michel Trivi * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi * INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2737dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi */ 28581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi 29c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kastenpackage org.jf.baksmali.Adaptors; 30c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten 31c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kastenimport org.jf.baksmali.Adaptors.Format.*; 32c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kastenimport org.jf.baksmali.IndentingWriter; 33c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kastenimport org.jf.baksmali.Renderers.IntegerRenderer; 34c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kastenimport org.jf.baksmali.baksmali; 35c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kastenimport org.jf.dexlib.*; 36581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Triviimport org.jf.dexlib.Code.*; 37581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Triviimport org.jf.dexlib.Code.Analysis.AnalyzedInstruction; 38581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Triviimport org.jf.dexlib.Code.Analysis.MethodAnalyzer; 39581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Triviimport org.jf.dexlib.Code.Analysis.ValidationException; 40581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Triviimport org.jf.dexlib.Code.Format.Format; 419d8a98601357c0669dca4de63e43196c0a70553dGlenn Kastenimport org.jf.dexlib.Debug.DebugInstructionIterator; 429d8a98601357c0669dca4de63e43196c0a70553dGlenn Kastenimport org.jf.dexlib.Util.AccessFlags; 439d8a98601357c0669dca4de63e43196c0a70553dGlenn Kastenimport org.jf.dexlib.Util.ExceptionWithContext; 449d8a98601357c0669dca4de63e43196c0a70553dGlenn Kastenimport org.jf.dexlib.Util.SparseIntArray; 45c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten 46c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kastenimport java.io.IOException; 47c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kastenimport java.util.*; 48c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten 49c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kastenpublic class MethodDefinition { 50c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten private final ClassDataItem.EncodedMethod encodedMethod; 51c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten private final MethodAnalyzer methodAnalyzer; 52581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi 53581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi private final LabelCache labelCache = new LabelCache(); 5437dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi 557f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten private final SparseIntArray packedSwitchMap; 56c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten private final SparseIntArray sparseSwitchMap; 57c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten private final SparseIntArray instructionMap; 58c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten 597f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten public MethodDefinition(ClassDataItem.EncodedMethod encodedMethod) { 607f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten 61c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten 62c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten try { 637f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten this.encodedMethod = encodedMethod; 647f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten 657f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten //TODO: what about try/catch blocks inside the dead code? those will need to be commented out too. ugh. 66c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten 67c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten if (encodedMethod.codeItem != null) { 687f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten methodAnalyzer = new MethodAnalyzer(encodedMethod, baksmali.deodex); 697f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten List<AnalyzedInstruction> instructions = methodAnalyzer.getInstructions(); 707f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten 717f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten packedSwitchMap = new SparseIntArray(1); 727f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten sparseSwitchMap = new SparseIntArray(1); 737f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten instructionMap = new SparseIntArray(instructions.size()); 747f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten 757f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten int currentCodeAddress = 0; 767f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten for (int i=0; i<instructions.size(); i++) { 777f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten AnalyzedInstruction instruction = instructions.get(i); 787f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten if (instruction.getInstruction().opcode == Opcode.PACKED_SWITCH) { 797f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten packedSwitchMap.append( 807f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten currentCodeAddress + 817f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten ((OffsetInstruction)instruction.getInstruction()).getTargetAddressOffset(), 827f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten currentCodeAddress); 837f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten } else if (instruction.getInstruction().opcode == Opcode.SPARSE_SWITCH) { 847f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten sparseSwitchMap.append( 857f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten currentCodeAddress + 86c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten ((OffsetInstruction)instruction.getInstruction()).getTargetAddressOffset(), 87581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi currentCodeAddress); 887f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten } 89c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten instructionMap.append(currentCodeAddress, i); 90c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten currentCodeAddress += instruction.getInstruction().getSize(currentCodeAddress); 91c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten } 92c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten } else { 937f250a17c145382b866d5d4d7ef23d65fada6236Glenn Kasten packedSwitchMap = null; 94581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi sparseSwitchMap = null; 95c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten instructionMap = null; 9637dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi methodAnalyzer = null; 9737dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi } 9837dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi }catch (Exception ex) { 9937dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi throw ExceptionWithContext.withContext(ex, String.format("Error while processing method %s", 10037dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi encodedMethod.method.getMethodString())); 10137dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi } 10237dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi } 10337dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi 10437dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi public void writeTo(IndentingWriter writer, AnnotationSetItem annotationSet, 10537dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi AnnotationSetRefList parameterAnnotations) throws IOException { 10637dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi final CodeItem codeItem = encodedMethod.codeItem; 10737dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi 10837dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi writer.write(".method "); 10937dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi writeAccessFlags(writer, encodedMethod); 11037dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi writer.write(encodedMethod.method.getMethodName().getStringValue()); 11137dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi writer.write(encodedMethod.method.getPrototype().getPrototypeString()); 11237dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi writer.write('\n'); 11337dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi 11437dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi writer.indent(4); 11537dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi if (codeItem != null) { 11637dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi if (baksmali.useLocalsDirective) { 11737dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi writer.write(".locals "); 11837dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi } else { 119cb441acdda6f8e81d44fcdaadd4ff7ab3d3e367bGlenn Kasten writer.write(".registers "); 12037dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi } 12137dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi writer.printIntAsDec(getRegisterCount(encodedMethod)); 12237dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi writer.write('\n'); 12337dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi writeParameters(writer, codeItem, parameterAnnotations); 12437dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi if (annotationSet != null) { 125e2e8fa36bd7448b59fbcdf141e0b6d21e5401d91Glenn Kasten AnnotationFormatter.writeTo(writer, annotationSet); 12637dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi } 12737dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi 12837dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi writer.write('\n'); 12937dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi 13037dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi for (MethodItem methodItem: getMethodItems()) { 13185133c817f6f387cd7d072988a8818f18bb53702Jean-Michel Trivi if (methodItem.writeTo(writer)) { 13237dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi writer.write('\n'); 133dd177e2d3923d4653eaa4226f07b89a999907970Glenn Kasten } 13437dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi } 13537dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi } else { 13637dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi if (annotationSet != null) { 13737dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi AnnotationFormatter.writeTo(writer, annotationSet); 13885133c817f6f387cd7d072988a8818f18bb53702Jean-Michel Trivi } 13985133c817f6f387cd7d072988a8818f18bb53702Jean-Michel Trivi } 14085133c817f6f387cd7d072988a8818f18bb53702Jean-Michel Trivi writer.deindent(4); 14185133c817f6f387cd7d072988a8818f18bb53702Jean-Michel Trivi writer.write(".end method\n"); 14285133c817f6f387cd7d072988a8818f18bb53702Jean-Michel Trivi } 14385133c817f6f387cd7d072988a8818f18bb53702Jean-Michel Trivi 14485133c817f6f387cd7d072988a8818f18bb53702Jean-Michel Trivi private static int getRegisterCount(ClassDataItem.EncodedMethod encodedMethod) 145dd177e2d3923d4653eaa4226f07b89a999907970Glenn Kasten { 146dd177e2d3923d4653eaa4226f07b89a999907970Glenn Kasten int totalRegisters = encodedMethod.codeItem.getRegisterCount(); 147dd177e2d3923d4653eaa4226f07b89a999907970Glenn Kasten if (baksmali.useLocalsDirective) { 14885133c817f6f387cd7d072988a8818f18bb53702Jean-Michel Trivi int parameterRegisters = encodedMethod.method.getPrototype().getParameterRegisterCount(); 149581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi if ((encodedMethod.accessFlags & AccessFlags.STATIC.getValue()) == 0) { 150581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi parameterRegisters++; 15137dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi } 152581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi return totalRegisters - parameterRegisters; 15392b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi } 15492b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi return totalRegisters; 15592b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi } 15692b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi 15792b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi private static void writeAccessFlags(IndentingWriter writer, ClassDataItem.EncodedMethod encodedMethod) 15892b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi throws IOException { 15992b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi for (AccessFlags accessFlag: AccessFlags.getAccessFlagsForMethod(encodedMethod.accessFlags)) { 16092b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi writer.write(accessFlag.toString()); 16192b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi writer.write(' '); 16292b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi } 16392b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi } 16492b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi 165e37c62f0691f9a137afae60f9d6dbd1a65d36aedGlenn Kasten private static void writeParameters(IndentingWriter writer, CodeItem codeItem, 16692b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi AnnotationSetRefList parameterAnnotations) throws IOException { 16792b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi DebugInfoItem debugInfoItem = null; 16885133c817f6f387cd7d072988a8818f18bb53702Jean-Michel Trivi if (baksmali.outputDebugInfo && codeItem != null) { 16992b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi debugInfoItem = codeItem.getDebugInfo(); 170dd177e2d3923d4653eaa4226f07b89a999907970Glenn Kasten } 17192b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi 17285133c817f6f387cd7d072988a8818f18bb53702Jean-Michel Trivi int parameterCount = 0; 17385133c817f6f387cd7d072988a8818f18bb53702Jean-Michel Trivi AnnotationSetItem[] annotations; 17485133c817f6f387cd7d072988a8818f18bb53702Jean-Michel Trivi StringIdItem[] parameterNames = null; 17585133c817f6f387cd7d072988a8818f18bb53702Jean-Michel Trivi 176c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten if (parameterAnnotations != null) { 17785133c817f6f387cd7d072988a8818f18bb53702Jean-Michel Trivi annotations = parameterAnnotations.getAnnotationSets(); 17885133c817f6f387cd7d072988a8818f18bb53702Jean-Michel Trivi parameterCount = annotations.length; 17992b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi } else { 180581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi annotations = new AnnotationSetItem[0]; 18192b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi } 18292b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi 18399b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten if (debugInfoItem != null) { 18499b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten parameterNames = debugInfoItem.getParameterNames(); 18599b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten } 18699b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten if (parameterNames == null) { 18799b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten parameterNames = new StringIdItem[0]; 18899b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten } 18999b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten 19099b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten if (parameterCount < parameterNames.length) { 19199b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten parameterCount = parameterNames.length; 19299b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten } 19399b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten 19499b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten for (int i=0; i<parameterCount; i++) { 19599b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten AnnotationSetItem annotationSet = null; 196c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten if (i < annotations.length) { 197c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten annotationSet = annotations[i]; 198c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten } 199c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten 200c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten StringIdItem parameterName = null; 201c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten if (i < parameterNames.length) { 202c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten parameterName = parameterNames[i]; 203c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten } 204c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten 205c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten writer.write(".parameter"); 206c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten 207c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten if (parameterName != null) { 208c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten writer.write('"'); 209c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten writer.write(parameterName.getStringValue()); 210c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten writer.write('"'); 211c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten } 212c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten 213c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten writer.write('\n'); 214c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten if (annotationSet != null) { 215c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten writer.indent(4); 21699b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten AnnotationFormatter.writeTo(writer, annotationSet); 21799b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten writer.deindent(4); 21899b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten 21999b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten writer.write(".end parameter\n"); 22099b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten } 221c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten } 222c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten } 223c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten 224c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten public LabelCache getLabelCache() { 225c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten return labelCache; 226c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten } 227c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten 228c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten public ValidationException getValidationException() { 229c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten if (methodAnalyzer == null) { 230c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten return null; 231c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten } 232c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten 233c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten return methodAnalyzer.getValidationException(); 234c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten } 235c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten 236c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten public int getPackedSwitchBaseAddress(int packedSwitchDataAddress) { 237c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten int packedSwitchBaseAddress = this.packedSwitchMap.get(packedSwitchDataAddress, -1); 238c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten 239c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten if (packedSwitchBaseAddress == -1) { 240c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten throw new RuntimeException("Could not find the packed switch statement corresponding to the packed " + 241c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten "switch data at address " + packedSwitchDataAddress); 242c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten } 243c623c89c0a32c5fc77c998f1742d58e7be69e8c1Glenn Kasten 24499b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten return packedSwitchBaseAddress; 24599b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten } 24699b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten 247bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten public int getSparseSwitchBaseAddress(int sparseSwitchDataAddress) { 248bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten int sparseSwitchBaseAddress = this.sparseSwitchMap.get(sparseSwitchDataAddress, -1); 249bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten 250bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten if (sparseSwitchBaseAddress == -1) { 251bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten throw new RuntimeException("Could not find the sparse switch statement corresponding to the sparse " + 252bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten "switch data at address " + sparseSwitchDataAddress); 253bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten } 254bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten 255bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten return sparseSwitchBaseAddress; 256bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten } 257bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten 258bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten /** 259bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten * @param instructions The instructions array for this method 26099b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten * @param instruction The instruction 2615e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten * @return true if the specified instruction is a NOP, and the next instruction is one of the variable sized 2625e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten * switch/array data structures 2635e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten */ 2645e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten private boolean isInstructionPaddingNop(List<AnalyzedInstruction> instructions, AnalyzedInstruction instruction) { 2655e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten if (instruction.getInstruction().opcode != Opcode.NOP || 2665e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten instruction.getInstruction().getFormat().variableSizeFormat) { 2675e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten 2685e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten return false; 2695e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten } 2705e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten 2715e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten if (instruction.getInstructionIndex() == instructions.size()-1) { 2725e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten return false; 2735e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten } 2745e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten 2755e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten AnalyzedInstruction nextInstruction = instructions.get(instruction.getInstructionIndex()+1); 2765e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten if (nextInstruction.getInstruction().getFormat().variableSizeFormat) { 2775e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten return true; 2785e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten } 2795e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten return false; 2805e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten } 2815e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten 2825e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten private List<MethodItem> getMethodItems() { 2835e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten List<MethodItem> methodItems = new ArrayList<MethodItem>(); 2845e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten 2855e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten if (encodedMethod.codeItem == null) { 2865e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten return methodItems; 2875e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten } 2885e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten 2895e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten if (baksmali.registerInfo != 0 || baksmali.deodex || baksmali.verify) { 2905e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten methodAnalyzer.analyze(); 2915e4d65e369f28746767aba11b618dee314bb8197Glenn Kasten 29292b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi ValidationException validationException = methodAnalyzer.getValidationException(); 29392b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi if (validationException != null) { 29492b245bf8828db9e469febebbe8774c00570b5b9Jean-Michel Trivi methodItems.add(new CommentMethodItem( 295581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi String.format("ValidationException: %s" ,validationException.getMessage()), 2969d8a98601357c0669dca4de63e43196c0a70553dGlenn Kasten validationException.getCodeAddress(), Integer.MIN_VALUE)); 2979d8a98601357c0669dca4de63e43196c0a70553dGlenn Kasten } else if (baksmali.verify) { 298581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi methodAnalyzer.verify(); 299581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi 300eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi validationException = methodAnalyzer.getValidationException(); 301eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi if (validationException != null) { 302d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi methodItems.add(new CommentMethodItem( 303d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi String.format("ValidationException: %s" ,validationException.getMessage()), 304d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi validationException.getCodeAddress(), Integer.MIN_VALUE)); 305d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi } 306d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi } 307d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi } 308d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi List<AnalyzedInstruction> instructions = methodAnalyzer.getInstructions(); 309d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi 310d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi AnalyzedInstruction lastInstruction = null; 311d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi 312d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi for (int i=instructions.size()-1; i>=0; i--) { 313d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi AnalyzedInstruction instruction = instructions.get(i); 314d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi 315d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi if (!instruction.isDead()) { 316d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi lastInstruction = instruction; 317d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi break; 318d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi } 319d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi } 320d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi 321d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi boolean lastIsUnreachable = false; 322d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi 323d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi int currentCodeAddress = 0; 324d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi for (int i=0; i<instructions.size(); i++) { 325d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi AnalyzedInstruction instruction = instructions.get(i); 326d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi 327d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi MethodItem methodItem = InstructionMethodItemFactory.makeInstructionFormatMethodItem(this, 328d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi encodedMethod.codeItem, currentCodeAddress, instruction.isDead(), instruction.getInstruction(), 329d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi instruction == lastInstruction); 330d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi 331d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi if (instruction.isDead() && !instruction.getInstruction().getFormat().variableSizeFormat) { 332d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi methodItems.add(new CommentedOutMethodItem(methodItem)); 333d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi lastIsUnreachable = false; 334d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi } else if ( instruction.getPredecessorCount() == 0 && 335d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi !instruction.getInstruction().getFormat().variableSizeFormat && 336d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi !isInstructionPaddingNop(instructions, instruction)) { 337d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi 338d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi if (!lastIsUnreachable) { 339d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi methodItems.add( 340d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi new CommentMethodItem("Unreachable code", currentCodeAddress, Double.MIN_VALUE)); 341d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi } 342d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi 343d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi methodItems.add(new CommentedOutMethodItem(methodItem)); 344d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi lastIsUnreachable = true; 345d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi } else { 346d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi methodItems.add(methodItem); 347d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi lastIsUnreachable = false; 348d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi } 349d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi 350d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi if (instruction.getInstruction().getFormat() == Format.UnresolvedNullReference) { 351d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi methodItems.add(new CommentedOutMethodItem( 352d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi InstructionMethodItemFactory.makeInstructionFormatMethodItem(this, encodedMethod.codeItem, 353d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi currentCodeAddress, instruction.isDead(), instruction.getOriginalInstruction(), 354d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi false))); 355d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi } 356d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi 357d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi if (i != instructions.size() - 1) { 358d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi methodItems.add(new BlankMethodItem(currentCodeAddress)); 359d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi } 360d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi 361d158d31a6bbb06426b71c3d097b7768bc3fb79a3Jean-Michel Trivi if (baksmali.addCodeOffsets) { 362eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi methodItems.add(new MethodItem(currentCodeAddress) { 363eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi 364eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi @Override 365eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi public double getSortOrder() { 366eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi return -1000; 367eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi } 368eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi 369eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi @Override 370eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi public boolean writeTo(IndentingWriter writer) throws IOException { 371eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi writer.write("#@"); 372eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi writer.printLongAsHex(codeAddress & 0xFFFFFFFF); 37397876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi return true; 374eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi } 37597876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi }); 376f271eea20f9fff6c101213b34652399f457bcd50Jean-Michel Trivi } 377b05ea38e5131001884aa226f90fd50cf594a23f3Jean-Michel Trivi 378eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi if (baksmali.registerInfo != 0 && !instruction.getInstruction().getFormat().variableSizeFormat) { 379f271eea20f9fff6c101213b34652399f457bcd50Jean-Michel Trivi methodItems.add( 38097876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi new PreInstructionRegisterInfoMethodItem(instruction, methodAnalyzer, currentCodeAddress)); 381b05ea38e5131001884aa226f90fd50cf594a23f3Jean-Michel Trivi 38297876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi methodItems.add( 383f271eea20f9fff6c101213b34652399f457bcd50Jean-Michel Trivi new PostInstructionRegisterInfoMethodItem(instruction, methodAnalyzer, currentCodeAddress)); 384eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi } 38572042d4448cee63528c619537321ba73944c6382Glenn Kasten 386a8179ea15c4ff78db589d742b135649f0eda7ef2Glenn Kasten currentCodeAddress += instruction.getInstruction().getSize(currentCodeAddress); 387eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi } 388eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi 389eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi addTries(methodItems); 390eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi addDebugInfo(methodItems); 39164621eac543d714d4d3f7cb9c24205f2ddc59201Glenn Kasten 392f271eea20f9fff6c101213b34652399f457bcd50Jean-Michel Trivi if (baksmali.useSequentialLabels) { 393f271eea20f9fff6c101213b34652399f457bcd50Jean-Michel Trivi setLabelSequentialNumbers(); 394f271eea20f9fff6c101213b34652399f457bcd50Jean-Michel Trivi } 395eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi 39672042d4448cee63528c619537321ba73944c6382Glenn Kasten 39772042d4448cee63528c619537321ba73944c6382Glenn Kasten for (LabelMethodItem labelMethodItem: labelCache.getLabels()) { 39872042d4448cee63528c619537321ba73944c6382Glenn Kasten if (labelMethodItem.isCommentedOut()) { 399485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten methodItems.add(new CommentedOutMethodItem(labelMethodItem)); 400485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten } else { 401eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi methodItems.add(labelMethodItem); 402eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi } 403eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi } 404eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi 405eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi Collections.sort(methodItems); 406eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi 407eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi return methodItems; 408ecc4fe22e076c4e5c891d823b01db1a683ba6690Glenn Kasten } 409eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi 410eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi private void addTries(List<MethodItem> methodItems) { 411eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi if (encodedMethod.codeItem == null || encodedMethod.codeItem.getTries() == null) { 412eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi return; 413eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi } 414eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi 415f271eea20f9fff6c101213b34652399f457bcd50Jean-Michel Trivi Instruction[] instructions = encodedMethod.codeItem.getInstructions(); 416f271eea20f9fff6c101213b34652399f457bcd50Jean-Michel Trivi 417eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi for (CodeItem.TryItem tryItem: encodedMethod.codeItem.getTries()) { 418f271eea20f9fff6c101213b34652399f457bcd50Jean-Michel Trivi int startAddress = tryItem.getStartCodeAddress(); 419b05ea38e5131001884aa226f90fd50cf594a23f3Jean-Michel Trivi int endAddress = tryItem.getStartCodeAddress() + tryItem.getTryLength(); 4207133228a478e16458b659946f2180ecddd13fda7Glenn Kasten 4217133228a478e16458b659946f2180ecddd13fda7Glenn Kasten /** 422581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi * The end address points to the address immediately after the end of the last 423eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi * instruction that the try block covers. We want the .catch directive and end_try 424eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi * label to be associated with the last covered instruction, so we need to get 425b05ea38e5131001884aa226f90fd50cf594a23f3Jean-Michel Trivi * the address for that instruction 42668d56b8ebaf60184a3aef988e3d2b09ed8b88c05Jean-Michel Trivi */ 42797876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi 42897876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi int index = instructionMap.get(endAddress, -1); 42997876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi int lastInstructionAddress; 43097876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi 43197876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi /** 43297876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi * If we couldn't find the index, then the try block probably extends to the last instruction in the 43397876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi * method, and so endAddress would be the address immediately after the end of the last instruction. 43497876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi * Check to make sure this is the case, if not, throw an exception. 43597876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi */ 43697876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi if (index == -1) { 43797876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi Instruction lastInstruction = instructions[instructions.length - 1]; 43897876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi lastInstructionAddress = instructionMap.keyAt(instructionMap.size() - 1); 43997876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi 44097876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi if (endAddress != lastInstructionAddress + lastInstruction.getSize(lastInstructionAddress)) { 44197876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi throw new RuntimeException("Invalid code offset " + endAddress + " for the try block end address"); 44297876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi } 443a8179ea15c4ff78db589d742b135649f0eda7ef2Glenn Kasten } else { 44497876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi if (index == 0) { 44597876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi throw new RuntimeException("Unexpected instruction index"); 44697876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi } 44797876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi Instruction lastInstruction = instructions[index - 1]; 44897876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi 449321f2cffd7dd560bf2e5c898be6953e19bed8496Jean-Michel Trivi if (lastInstruction.getFormat().variableSizeFormat) { 450eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi throw new RuntimeException("This try block unexpectedly ends on a switch/array data block."); 451f271eea20f9fff6c101213b34652399f457bcd50Jean-Michel Trivi } 452eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi 453eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi //getSize for non-variable size formats should return the same size regardless of code address, so just 454eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi //use a dummy address of "0" 455eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi lastInstructionAddress = endAddress - lastInstruction.getSize(0); 45635ac702ee1ad91e5c8748c12450222d50b366a52Glenn Kasten } 45735ac702ee1ad91e5c8748c12450222d50b366a52Glenn Kasten 45835ac702ee1ad91e5c8748c12450222d50b366a52Glenn Kasten //add the catch all handler if it exists 45935ac702ee1ad91e5c8748c12450222d50b366a52Glenn Kasten int catchAllAddress = tryItem.encodedCatchHandler.getCatchAllHandlerAddress(); 46035ac702ee1ad91e5c8748c12450222d50b366a52Glenn Kasten if (catchAllAddress != -1) { 46135ac702ee1ad91e5c8748c12450222d50b366a52Glenn Kasten CatchMethodItem catchAllMethodItem = new CatchMethodItem(labelCache, lastInstructionAddress, null, 46235ac702ee1ad91e5c8748c12450222d50b366a52Glenn Kasten startAddress, endAddress, catchAllAddress); 46335ac702ee1ad91e5c8748c12450222d50b366a52Glenn Kasten methodItems.add(catchAllMethodItem); 46435ac702ee1ad91e5c8748c12450222d50b366a52Glenn Kasten } 46535ac702ee1ad91e5c8748c12450222d50b366a52Glenn Kasten 46635ac702ee1ad91e5c8748c12450222d50b366a52Glenn Kasten //add the rest of the handlers 46735ac702ee1ad91e5c8748c12450222d50b366a52Glenn Kasten for (CodeItem.EncodedTypeAddrPair handler: tryItem.encodedCatchHandler.handlers) { 46835ac702ee1ad91e5c8748c12450222d50b366a52Glenn Kasten //use the address from the last covered instruction 46935ac702ee1ad91e5c8748c12450222d50b366a52Glenn Kasten CatchMethodItem catchMethodItem = new CatchMethodItem(labelCache, lastInstructionAddress, 470eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi handler.exceptionType, startAddress, endAddress, handler.getHandlerAddress()); 471eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi methodItems.add(catchMethodItem); 472eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi } 473485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten } 474485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten } 475485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten 476485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten private void addDebugInfo(final List<MethodItem> methodItems) { 477b66dfcb9e7b944c45927314ef2282d6cc95cfa0aGlenn Kasten if (encodedMethod.codeItem == null || encodedMethod.codeItem.getDebugInfo() == null) { 478485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten return; 479485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten } 480485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten 481485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten final CodeItem codeItem = encodedMethod.codeItem; 482485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten DebugInfoItem debugInfoItem = codeItem.getDebugInfo(); 483485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten 484b66dfcb9e7b944c45927314ef2282d6cc95cfa0aGlenn Kasten DebugInstructionIterator.DecodeInstructions(debugInfoItem, codeItem.getRegisterCount(), 485b66dfcb9e7b944c45927314ef2282d6cc95cfa0aGlenn Kasten new DebugInstructionIterator.ProcessDecodedDebugInstructionDelegate() { 486b66dfcb9e7b944c45927314ef2282d6cc95cfa0aGlenn Kasten @Override 487b66dfcb9e7b944c45927314ef2282d6cc95cfa0aGlenn Kasten public void ProcessStartLocal(final int codeAddress, final int length, final int registerNum, 488b66dfcb9e7b944c45927314ef2282d6cc95cfa0aGlenn Kasten final StringIdItem name, final TypeIdItem type) { 489485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten methodItems.add(new DebugMethodItem(codeAddress, -1) { 490485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten @Override 491485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten public boolean writeTo(IndentingWriter writer) throws IOException { 49297876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi writeStartLocal(writer, codeItem, registerNum, name, type, null); 49397876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi return true; 494ecc4fe22e076c4e5c891d823b01db1a683ba6690Glenn Kasten } 49597876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi }); 496485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten } 49772042d4448cee63528c619537321ba73944c6382Glenn Kasten 49872042d4448cee63528c619537321ba73944c6382Glenn Kasten @Override 49972042d4448cee63528c619537321ba73944c6382Glenn Kasten public void ProcessStartLocalExtended(final int codeAddress, final int length, 50072042d4448cee63528c619537321ba73944c6382Glenn Kasten final int registerNum, final StringIdItem name, 501485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten final TypeIdItem type, final StringIdItem signature) { 50297876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi methodItems.add(new DebugMethodItem(codeAddress, -1) { 503485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten @Override 504485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten public boolean writeTo(IndentingWriter writer) throws IOException { 505485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten writeStartLocal(writer, codeItem, registerNum, name, type, signature); 506485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten return true; 507485a038f9f0f898227b8ab4218e94c5d56b6ed0bGlenn Kasten } 50897876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi }); 509eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi } 510ad1ab1d13a9b043202b9d5cdc1d8c4ef66cbbca8Glenn Kasten 511bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten @Override 512bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten public void ProcessEndLocal(final int codeAddress, final int length, final int registerNum, 513bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten final StringIdItem name, final TypeIdItem type, 514bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten final StringIdItem signature) { 515bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten methodItems.add(new DebugMethodItem(codeAddress, -1) { 516bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten @Override 517bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten public boolean writeTo(IndentingWriter writer) throws IOException { 518bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten writeEndLocal(writer, codeItem, registerNum, name, type, signature); 519bcfe680db1e392f3bb29382c2e15e89c3af783edGlenn Kasten return true; 52070c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi } 52170c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi }); 52270c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi } 52370c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi 52470c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi @Override 525b05ea38e5131001884aa226f90fd50cf594a23f3Jean-Michel Trivi public void ProcessRestartLocal(final int codeAddress, final int length, final int registerNum, 5263d332ff421e7179c36fb652771cc8ded53383729Glenn Kasten final StringIdItem name, final TypeIdItem type, 52770c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi final StringIdItem signature) { 52870c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi methodItems.add(new DebugMethodItem(codeAddress, -1) { 52970c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi @Override 53035a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi public boolean writeTo(IndentingWriter writer) throws IOException { 53135a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi writeRestartLocal(writer, codeItem, registerNum, name, type, signature); 53270c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi return true; 53370c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi } 53470c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi }); 53570c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi } 53670c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi 5373d332ff421e7179c36fb652771cc8ded53383729Glenn Kasten @Override 53870c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi public void ProcessSetPrologueEnd(int codeAddress) { 5393d332ff421e7179c36fb652771cc8ded53383729Glenn Kasten methodItems.add(new DebugMethodItem(codeAddress, -4) { 54035a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi @Override 54135a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi public boolean writeTo(IndentingWriter writer) throws IOException { 54235a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi writeEndPrologue(writer); 5433d332ff421e7179c36fb652771cc8ded53383729Glenn Kasten return true; 54435a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi } 54535a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi }); 54635a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi } 54735a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi 54835a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi @Override 54935a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi public void ProcessSetEpilogueBegin(int codeAddress) { 55035a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi methodItems.add(new DebugMethodItem(codeAddress, -4) { 55135a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi @Override 55235a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi public boolean writeTo(IndentingWriter writer) throws IOException { 55335a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi writeBeginEpilogue(writer); 55435a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi return true; 55535a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi } 556136965c92c625d52a6cbad42f82a2091d7769c9cGlenn Kasten }); 55735a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi } 55835a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi 55935a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi @Override 56035a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi public void ProcessSetFile(int codeAddress, int length, final StringIdItem name) { 561136965c92c625d52a6cbad42f82a2091d7769c9cGlenn Kasten methodItems.add(new DebugMethodItem(codeAddress, -3) { 56235a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi @Override 56335a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi public boolean writeTo(IndentingWriter writer) throws IOException { 56435a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi writeSetFile(writer, name.getStringValue()); 56535a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi return true; 56635a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi } 56735a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi }); 56835a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi } 56935a5a30fdad179ccf38d8d756590411326159a89Jean-Michel Trivi 57070c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi @Override 57170c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi public void ProcessLineEmit(int codeAddress, final int line) { 57270c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi methodItems.add(new DebugMethodItem(codeAddress, -2) { 57370c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi @Override 57470c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi public boolean writeTo(IndentingWriter writer) throws IOException { 57570c49ae2867094072a4365423417ea452bf82231Jean-Michel Trivi writeLine(writer, line); 57637dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi return true; 57737dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi } 57837dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi }); 57999b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten } 58037dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi }); 58199b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten } 58237dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi 58399b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten private void setLabelSequentialNumbers() { 58499b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten HashMap<String, Integer> nextLabelSequenceByType = new HashMap<String, Integer>(); 58599b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten ArrayList<LabelMethodItem> sortedLabels = new ArrayList<LabelMethodItem>(labelCache.getLabels()); 58699b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten 58799b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten //sort the labels by their location in the method 58899b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten Collections.sort(sortedLabels); 58999b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten 59099b927751677abfb60a388d65dfeed1fed1db12cGlenn Kasten for (LabelMethodItem labelMethodItem: sortedLabels) { 59137dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi Integer labelSequence = nextLabelSequenceByType.get(labelMethodItem.getLabelPrefix()); 59237dc2fccf3f122b79ebd554de209d0a3c94ae161Jean-Michel Trivi if (labelSequence == null) { 5930e47a0657162bbff48886ea2f5c68d9edb607768Jean-Michel Trivi labelSequence = 0; 5940e47a0657162bbff48886ea2f5c68d9edb607768Jean-Michel Trivi } 59536b700a829b7a02b873b4cd0cdb0a95342b20a31Jean-Michel Trivi labelMethodItem.setLabelSequence(labelSequence); 596f271eea20f9fff6c101213b34652399f457bcd50Jean-Michel Trivi nextLabelSequenceByType.put(labelMethodItem.getLabelPrefix(), labelSequence + 1); 59736b700a829b7a02b873b4cd0cdb0a95342b20a31Jean-Michel Trivi } 59836b700a829b7a02b873b4cd0cdb0a95342b20a31Jean-Michel Trivi } 599b05ea38e5131001884aa226f90fd50cf594a23f3Jean-Michel Trivi 600eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi public static class LabelCache { 601eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi protected HashMap<LabelMethodItem, LabelMethodItem> labels = new HashMap<LabelMethodItem, LabelMethodItem>(); 602b05ea38e5131001884aa226f90fd50cf594a23f3Jean-Michel Trivi 603eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi public LabelCache() { 604eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi } 605eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi 606f271eea20f9fff6c101213b34652399f457bcd50Jean-Michel Trivi public LabelMethodItem internLabel(LabelMethodItem labelMethodItem) { 60736b700a829b7a02b873b4cd0cdb0a95342b20a31Jean-Michel Trivi LabelMethodItem internedLabelMethodItem = labels.get(labelMethodItem); 60897876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi if (internedLabelMethodItem != null) { 60997876858aa17c7f24c6a1d60be09a57bc1824ba3Jean-Michel Trivi if (!labelMethodItem.isCommentedOut()) { 610eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi internedLabelMethodItem.setUncommented(); 611f271eea20f9fff6c101213b34652399f457bcd50Jean-Michel Trivi } 612eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi return internedLabelMethodItem; 613e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi } 614581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi labels.put(labelMethodItem, labelMethodItem); 61536b700a829b7a02b873b4cd0cdb0a95342b20a31Jean-Michel Trivi return labelMethodItem; 616581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi } 617e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi 618eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi 619e7bfcdc183454ec959ff51342f0973cabba219b2Jean-Michel Trivi public Collection<LabelMethodItem> getLabels() { 62036b700a829b7a02b873b4cd0cdb0a95342b20a31Jean-Michel Trivi return labels.values(); 621581a0f550f15f6fc22199cb85775a220f668b480Jean-Michel Trivi } 622eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi } 623f271eea20f9fff6c101213b34652399f457bcd50Jean-Michel Trivi} 624eae4df541ba1d46f65d37e959baf2127aa632c93Jean-Michel Trivi