136836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com/* 236836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com * [The "BSD licence"] 300fc68adf2e39aeb9fed35293f2576bbe729ec4bJesusFreke@JesusFreke.com * Copyright (c) 2010 Ben Gruver (JesusFreke) 436836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com * All rights reserved. 536836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com * 636836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com * Redistribution and use in source and binary forms, with or without 736836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com * modification, are permitted provided that the following conditions 836836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com * are met: 936836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com * 1. Redistributions of source code must retain the above copyright 1036836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com * notice, this list of conditions and the following disclaimer. 1136836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com * 2. Redistributions in binary form must reproduce the above copyright 1236836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com * notice, this list of conditions and the following disclaimer in the 1336836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com * documentation and/or other materials provided with the distribution. 1436836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com * 3. The name of the author may not be used to endorse or promote products 1536836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com * derived from this software without specific prior written permission. 1636836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com * 1736836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1836836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1936836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 2036836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 2136836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 2236836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2336836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2436836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2536836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com * INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2636836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2736836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com */ 2836836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com 296ef13753e78bb7abc7e7683d5e533c3395d4a9b6JesusFreke@JesusFreke.compackage org.jf.baksmali.Adaptors; 3036836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com 31d1662b67fecaf835227aff3a136949a2358ccd4eBen Gruverimport com.google.common.collect.ImmutableList; 32bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruverimport com.google.common.collect.Lists; 33754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruverimport org.jf.baksmali.Adaptors.Debug.DebugMethodItem; 34fbea4e751fa6f1748ded4379a4b64601cb53ba7bJesusFreke@JesusFreke.comimport org.jf.baksmali.Adaptors.Format.InstructionMethodItemFactory; 355a5eafb818cc18baeef8bdae1940401da3735f25Ben Gruverimport org.jf.baksmali.BaksmaliOptions; 36754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruverimport org.jf.dexlib2.AccessFlags; 37c91b03ba45ccacfa7b0ad52592a42e8fd8c18da1Ben Gruverimport org.jf.dexlib2.Format; 38754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruverimport org.jf.dexlib2.Opcode; 392b8845bb247e3e5ee154966866b53fa9887e2609Ben Gruverimport org.jf.dexlib2.ReferenceType; 40c91b03ba45ccacfa7b0ad52592a42e8fd8c18da1Ben Gruverimport org.jf.dexlib2.analysis.AnalysisException; 41c91b03ba45ccacfa7b0ad52592a42e8fd8c18da1Ben Gruverimport org.jf.dexlib2.analysis.AnalyzedInstruction; 42c91b03ba45ccacfa7b0ad52592a42e8fd8c18da1Ben Gruverimport org.jf.dexlib2.analysis.MethodAnalyzer; 434f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruverimport org.jf.dexlib2.dexbacked.DexBackedDexFile.InvalidItemIndex; 44754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruverimport org.jf.dexlib2.iface.*; 45754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruverimport org.jf.dexlib2.iface.debug.DebugItem; 46754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruverimport org.jf.dexlib2.iface.instruction.Instruction; 47754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruverimport org.jf.dexlib2.iface.instruction.OffsetInstruction; 482b8845bb247e3e5ee154966866b53fa9887e2609Ben Gruverimport org.jf.dexlib2.iface.instruction.ReferenceInstruction; 49bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruverimport org.jf.dexlib2.iface.instruction.formats.Instruction31t; 502b8845bb247e3e5ee154966866b53fa9887e2609Ben Gruverimport org.jf.dexlib2.iface.reference.MethodReference; 51bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruverimport org.jf.dexlib2.immutable.instruction.ImmutableInstruction31t; 52ffe82bdcb5c914b3a60b630c6d3abe6fc9229decBen Gruverimport org.jf.dexlib2.util.InstructionOffsetMap; 534f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruverimport org.jf.dexlib2.util.InstructionOffsetMap.InvalidInstructionOffset; 54ffe82bdcb5c914b3a60b630c6d3abe6fc9229decBen Gruverimport org.jf.dexlib2.util.ReferenceUtil; 55ffe82bdcb5c914b3a60b630c6d3abe6fc9229decBen Gruverimport org.jf.dexlib2.util.SyntheticAccessorResolver; 56bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruverimport org.jf.dexlib2.util.SyntheticAccessorResolver.AccessedMember; 57ffe82bdcb5c914b3a60b630c6d3abe6fc9229decBen Gruverimport org.jf.dexlib2.util.TypeUtils; 58bf95959ae43ddd003936a01dfaecc612a438d4b5Ben Gruverimport org.jf.util.ExceptionWithContext; 59ffe82bdcb5c914b3a60b630c6d3abe6fc9229decBen Gruverimport org.jf.util.IndentingWriter; 60ffe82bdcb5c914b3a60b630c6d3abe6fc9229decBen Gruverimport org.jf.util.SparseIntArray; 6136836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com 62754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruverimport javax.annotation.Nonnull; 63d33fd6773cc3e527b4dbb79245796d556b7facdeBen Gruverimport javax.annotation.Nullable; 646eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.comimport java.io.IOException; 659bc4978139ca38e422ae89065d3062146534132dJesusFreke@JesusFreke.comimport java.util.*; 660b2f7d6a57e90424b3ee455c041aab3996c05f2cJesusFreke@JesusFreke.com 6736836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.compublic class MethodDefinition { 68754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver @Nonnull public final ClassDefinition classDef; 69754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver @Nonnull public final Method method; 70754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver @Nonnull public final MethodImplementation methodImpl; 71d1662b67fecaf835227aff3a136949a2358ccd4eBen Gruver @Nonnull public final ImmutableList<Instruction> instructions; 72bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver @Nonnull public final List<Instruction> effectiveInstructions; 73bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver 747fe0543b660587a77f6013905a85e4f737a9a851Ben Gruver @Nonnull public final ImmutableList<MethodParameter> methodParameters; 75754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver public RegisterFormatter registerFormatter; 76b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com 77754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver @Nonnull private final LabelCache labelCache = new LabelCache(); 78b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com 79754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver @Nonnull private final SparseIntArray packedSwitchMap; 80754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver @Nonnull private final SparseIntArray sparseSwitchMap; 81754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver @Nonnull private final InstructionOffsetMap instructionOffsetMap; 8210a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com 83754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver public MethodDefinition(@Nonnull ClassDefinition classDef, @Nonnull Method method, 84754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver @Nonnull MethodImplementation methodImpl) { 85754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver this.classDef = classDef; 86754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver this.method = method; 87754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver this.methodImpl = methodImpl; 8810a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com 89754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver try { 9010a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com //TODO: what about try/catch blocks inside the dead code? those will need to be commented out too. ugh. 9110a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com 92d1662b67fecaf835227aff3a136949a2358ccd4eBen Gruver instructions = ImmutableList.copyOf(methodImpl.getInstructions()); 937fe0543b660587a77f6013905a85e4f737a9a851Ben Gruver methodParameters = ImmutableList.copyOf(method.getParameters()); 94754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver 95bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver effectiveInstructions = Lists.newArrayList(instructions); 96bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver 97754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver packedSwitchMap = new SparseIntArray(0); 98754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver sparseSwitchMap = new SparseIntArray(0); 99d1662b67fecaf835227aff3a136949a2358ccd4eBen Gruver instructionOffsetMap = new InstructionOffsetMap(instructions); 100754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver 101bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver int endOffset = instructionOffsetMap.getInstructionCodeOffset(instructions.size()-1) + 102bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver instructions.get(instructions.size()-1).getCodeUnits(); 103bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver 104754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver for (int i=0; i<instructions.size(); i++) { 105754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver Instruction instruction = instructions.get(i); 106754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver 107754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver Opcode opcode = instruction.getOpcode(); 108754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (opcode == Opcode.PACKED_SWITCH) { 1094f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver boolean valid = true; 110754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver int codeOffset = instructionOffsetMap.getInstructionCodeOffset(i); 111754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver int targetOffset = codeOffset + ((OffsetInstruction)instruction).getCodeOffset(); 1124f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver try { 113bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver targetOffset = findPayloadOffset(targetOffset, Opcode.PACKED_SWITCH_PAYLOAD); 1144f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver } catch (InvalidSwitchPayload ex) { 1154f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver valid = false; 1164f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver } 1174f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver if (valid) { 118bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver if (packedSwitchMap.get(targetOffset, -1) != -1) { 119bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver Instruction payloadInstruction = 120bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver findSwitchPayload(targetOffset, Opcode.PACKED_SWITCH_PAYLOAD); 121bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver targetOffset = endOffset; 122bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver effectiveInstructions.set(i, new ImmutableInstruction31t(opcode, 123bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver ((Instruction31t)instruction).getRegisterA(), targetOffset-codeOffset)); 124bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver effectiveInstructions.add(payloadInstruction); 125bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver endOffset += payloadInstruction.getCodeUnits(); 126bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver } 1274f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver packedSwitchMap.append(targetOffset, codeOffset); 1284f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver } 129754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver } else if (opcode == Opcode.SPARSE_SWITCH) { 1304f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver boolean valid = true; 131754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver int codeOffset = instructionOffsetMap.getInstructionCodeOffset(i); 132754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver int targetOffset = codeOffset + ((OffsetInstruction)instruction).getCodeOffset(); 1334f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver try { 134bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver targetOffset = findPayloadOffset(targetOffset, Opcode.SPARSE_SWITCH_PAYLOAD); 1354f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver } catch (InvalidSwitchPayload ex) { 1364f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver valid = false; 1374f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver // The offset to the payload instruction was invalid. Nothing to do, except that we won't 1384f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver // add this instruction to the map. 1394f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver } 1404f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver if (valid) { 141bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver if (sparseSwitchMap.get(targetOffset, -1) != -1) { 142bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver Instruction payloadInstruction = 143bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver findSwitchPayload(targetOffset, Opcode.SPARSE_SWITCH_PAYLOAD); 144bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver targetOffset = endOffset; 145bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver effectiveInstructions.set(i, new ImmutableInstruction31t(opcode, 146bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver ((Instruction31t)instruction).getRegisterA(), targetOffset-codeOffset)); 147bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver effectiveInstructions.add(payloadInstruction); 148bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver endOffset += payloadInstruction.getCodeUnits(); 149bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver } 1504f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver sparseSwitchMap.append(targetOffset, codeOffset); 1514f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver } 152b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com } 153b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com } 154bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver } catch (Exception ex) { 1556b93c7cc35141db5c70406b8af609ed0954135f9Ben Gruver String methodString; 1566b93c7cc35141db5c70406b8af609ed0954135f9Ben Gruver try { 157f3c33259dd0567294ef814be879b59a450c24f70Izzat Bahadirov methodString = ReferenceUtil.getMethodDescriptor(method); 1586b93c7cc35141db5c70406b8af609ed0954135f9Ben Gruver } catch (Exception ex2) { 1596b93c7cc35141db5c70406b8af609ed0954135f9Ben Gruver throw ExceptionWithContext.withContext(ex, "Error while processing method"); 1606b93c7cc35141db5c70406b8af609ed0954135f9Ben Gruver } 161754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver throw ExceptionWithContext.withContext(ex, "Error while processing method %s", methodString); 162b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com } 163b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com } 164b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com 16544c5c07c5724e9448d803b3585c9ef47117c3d4eBen Gruver public static void writeEmptyMethodTo(IndentingWriter writer, Method method, 1665a5eafb818cc18baeef8bdae1940401da3735f25Ben Gruver BaksmaliOptions options) throws IOException { 1676eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com writer.write(".method "); 168754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writeAccessFlags(writer, method.getAccessFlags()); 169754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write(method.getName()); 170754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write("("); 1717fe0543b660587a77f6013905a85e4f737a9a851Ben Gruver ImmutableList<MethodParameter> methodParameters = ImmutableList.copyOf(method.getParameters()); 1727fe0543b660587a77f6013905a85e4f737a9a851Ben Gruver for (MethodParameter parameter: methodParameters) { 173754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write(parameter.getType()); 174754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver } 175754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write(")"); 176754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write(method.getReturnType()); 1770b2f7d6a57e90424b3ee455c041aab3996c05f2cJesusFreke@JesusFreke.com writer.write('\n'); 17836836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com 1796eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com writer.indent(4); 18044c5c07c5724e9448d803b3585c9ef47117c3d4eBen Gruver writeParameters(writer, method, methodParameters, options); 181d33fd6773cc3e527b4dbb79245796d556b7facdeBen Gruver 182d33fd6773cc3e527b4dbb79245796d556b7facdeBen Gruver String containingClass = null; 1835a5eafb818cc18baeef8bdae1940401da3735f25Ben Gruver if (options.implicitReferences) { 184d33fd6773cc3e527b4dbb79245796d556b7facdeBen Gruver containingClass = method.getDefiningClass(); 185d33fd6773cc3e527b4dbb79245796d556b7facdeBen Gruver } 186d33fd6773cc3e527b4dbb79245796d556b7facdeBen Gruver AnnotationFormatter.writeTo(writer, method.getAnnotations(), containingClass); 187d33fd6773cc3e527b4dbb79245796d556b7facdeBen Gruver 1886eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com writer.deindent(4); 1890b2f7d6a57e90424b3ee455c041aab3996c05f2cJesusFreke@JesusFreke.com writer.write(".end method\n"); 19036836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com } 19136836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com 192754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver public void writeTo(IndentingWriter writer) throws IOException { 193754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver int parameterRegisterCount = 0; 194754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (!AccessFlags.STATIC.isSet(method.getAccessFlags())) { 195754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver parameterRegisterCount++; 19636836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com } 197fa07a1972e3cff56d5615c18a8797ff58fc9f739JesusFreke@JesusFreke.com 198754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write(".method "); 199754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writeAccessFlags(writer, method.getAccessFlags()); 200754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write(method.getName()); 201754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write("("); 2027fe0543b660587a77f6013905a85e4f737a9a851Ben Gruver for (MethodParameter parameter: methodParameters) { 203754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver String type = parameter.getType(); 204754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write(type); 205754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver parameterRegisterCount++; 206754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (TypeUtils.isWideType(type)) { 207754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver parameterRegisterCount++; 208754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver } 2093c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com } 210754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write(")"); 211754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write(method.getReturnType()); 212754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write('\n'); 2133c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com 214754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.indent(4); 2155a5eafb818cc18baeef8bdae1940401da3735f25Ben Gruver if (classDef.options.localsDirective) { 216754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write(".locals "); 217754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.printSignedIntAsDec(methodImpl.getRegisterCount() - parameterRegisterCount); 2186eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com } else { 219754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write(".registers "); 220754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.printSignedIntAsDec(methodImpl.getRegisterCount()); 2216eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com } 222754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write('\n'); 22344c5c07c5724e9448d803b3585c9ef47117c3d4eBen Gruver writeParameters(writer, method, methodParameters, classDef.options); 2243c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com 225754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (registerFormatter == null) { 22693aa50139c4641d931b05608f73af8879c0de1c2Ben Gruver registerFormatter = new RegisterFormatter(classDef.options, methodImpl.getRegisterCount(), 22793aa50139c4641d931b05608f73af8879c0de1c2Ben Gruver parameterRegisterCount); 2283c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com } 2293c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com 230d33fd6773cc3e527b4dbb79245796d556b7facdeBen Gruver String containingClass = null; 2315a5eafb818cc18baeef8bdae1940401da3735f25Ben Gruver if (classDef.options.implicitReferences) { 232d33fd6773cc3e527b4dbb79245796d556b7facdeBen Gruver containingClass = method.getDefiningClass(); 233d33fd6773cc3e527b4dbb79245796d556b7facdeBen Gruver } 234d33fd6773cc3e527b4dbb79245796d556b7facdeBen Gruver AnnotationFormatter.writeTo(writer, method.getAnnotations(), containingClass); 2353c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com 236754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write('\n'); 2376eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com 238db49fd7714893b35ba7de51fae8d8e386f3dc335Ben Gruver List<MethodItem> methodItems = getMethodItems(); 2394b171afedb983fb811990beeec6a15e30a90b455Ben Gruver for (MethodItem methodItem: methodItems) { 240754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (methodItem.writeTo(writer)) { 241754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write('\n'); 2426eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com } 2436eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com } 244754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.deindent(4); 245754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write(".end method\n"); 2463c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com } 2473c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com 248bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver public Instruction findSwitchPayload(int targetOffset, Opcode type) { 249bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver int targetIndex; 250bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver try { 251bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver targetIndex = instructionOffsetMap.getInstructionIndexAtCodeOffset(targetOffset); 252bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver } catch (InvalidInstructionOffset ex) { 253bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver throw new InvalidSwitchPayload(targetOffset); 254bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver } 255bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver 256bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver //TODO: does dalvik let you pad with multiple nops? 257bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver //TODO: does dalvik let a switch instruction point to a non-payload instruction? 258bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver 259bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver Instruction instruction = instructions.get(targetIndex); 260bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver if (instruction.getOpcode() != type) { 261bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver // maybe it's pointing to a NOP padding instruction. Look at the next instruction 262bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver if (instruction.getOpcode() == Opcode.NOP) { 263bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver targetIndex += 1; 264bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver if (targetIndex < instructions.size()) { 265bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver instruction = instructions.get(targetIndex); 266bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver if (instruction.getOpcode() == type) { 267bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver return instruction; 268bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver } 269bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver } 270bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver } 271bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver throw new InvalidSwitchPayload(targetOffset); 272bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver } else { 273bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver return instruction; 274bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver } 275bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver } 276bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver 277bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver public int findPayloadOffset(int targetOffset, Opcode type) { 2784f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver int targetIndex; 2794f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver try { 2804f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver targetIndex = instructionOffsetMap.getInstructionIndexAtCodeOffset(targetOffset); 2814f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver } catch (InvalidInstructionOffset ex) { 2824f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver throw new InvalidSwitchPayload(targetOffset); 2834f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver } 284754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver 285754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver //TODO: does dalvik let you pad with multiple nops? 286754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver //TODO: does dalvik let a switch instruction point to a non-payload instruction? 287754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver 288754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver Instruction instruction = instructions.get(targetIndex); 289754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (instruction.getOpcode() != type) { 290754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver // maybe it's pointing to a NOP padding instruction. Look at the next instruction 291754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (instruction.getOpcode() == Opcode.NOP) { 292754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver targetIndex += 1; 293754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (targetIndex < instructions.size()) { 294754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver instruction = instructions.get(targetIndex); 295754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (instruction.getOpcode() == type) { 296754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver return instructionOffsetMap.getInstructionCodeOffset(targetIndex); 297754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver } 298754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver } 299754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver } 3004f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver throw new InvalidSwitchPayload(targetOffset); 301754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver } else { 302754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver return targetOffset; 303c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com } 304c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com } 305c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com 306754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver private static void writeAccessFlags(IndentingWriter writer, int accessFlags) 307754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver throws IOException { 308754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver for (AccessFlags accessFlag: AccessFlags.getAccessFlagsForMethod(accessFlags)) { 309754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write(accessFlag.toString()); 310754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write(' '); 311b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com } 312b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com } 313b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com 3147fe0543b660587a77f6013905a85e4f737a9a851Ben Gruver private static void writeParameters(IndentingWriter writer, Method method, 31544c5c07c5724e9448d803b3585c9ef47117c3d4eBen Gruver List<? extends MethodParameter> parameters, 3165a5eafb818cc18baeef8bdae1940401da3735f25Ben Gruver BaksmaliOptions options) throws IOException { 317c3a3ee3799e354b6718ce8eee2cf20cbac1ca9d9Ben Gruver boolean isStatic = AccessFlags.STATIC.isSet(method.getAccessFlags()); 318c3a3ee3799e354b6718ce8eee2cf20cbac1ca9d9Ben Gruver int registerNumber = isStatic?0:1; 3197fe0543b660587a77f6013905a85e4f737a9a851Ben Gruver for (MethodParameter parameter: parameters) { 320754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver String parameterType = parameter.getType(); 321754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver String parameterName = parameter.getName(); 322c6e54994a7be1bdbdd751ede7c96e07e7fb1c84fBen Gruver Collection<? extends Annotation> annotations = parameter.getAnnotations(); 3235a5eafb818cc18baeef8bdae1940401da3735f25Ben Gruver if ((options.debugInfo && parameterName != null) || annotations.size() != 0) { 32416f257ee8f12974c62e50643b2f87533513da455Ben Gruver writer.write(".param p"); 325754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.printSignedIntAsDec(registerNumber); 3263e4e5ec7a4f2bcd82e21ba7caf93c60a981422abBen Gruver 3275a5eafb818cc18baeef8bdae1940401da3735f25Ben Gruver if (parameterName != null && options.debugInfo) { 32816f257ee8f12974c62e50643b2f87533513da455Ben Gruver writer.write(", "); 3293e4e5ec7a4f2bcd82e21ba7caf93c60a981422abBen Gruver ReferenceFormatter.writeStringReference(writer, parameterName); 330754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver } 331c3a3ee3799e354b6718ce8eee2cf20cbac1ca9d9Ben Gruver writer.write(" # "); 33216f257ee8f12974c62e50643b2f87533513da455Ben Gruver writer.write(parameterType); 333db81d89c2acbd8569f62a941ee2947eb5cd4c5b5Ben Gruver writer.write("\n"); 334754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (annotations.size() > 0) { 335754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.indent(4); 336d33fd6773cc3e527b4dbb79245796d556b7facdeBen Gruver 337d33fd6773cc3e527b4dbb79245796d556b7facdeBen Gruver String containingClass = null; 3385a5eafb818cc18baeef8bdae1940401da3735f25Ben Gruver if (options.implicitReferences) { 339d33fd6773cc3e527b4dbb79245796d556b7facdeBen Gruver containingClass = method.getDefiningClass(); 340d33fd6773cc3e527b4dbb79245796d556b7facdeBen Gruver } 341d33fd6773cc3e527b4dbb79245796d556b7facdeBen Gruver AnnotationFormatter.writeTo(writer, annotations, containingClass); 342754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.deindent(4); 34316f257ee8f12974c62e50643b2f87533513da455Ben Gruver writer.write(".end param\n"); 344754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver } 345754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver } 346cb3e0ea38a669633b8daefd538750c8ded46f524Ben Gruver 347754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver registerNumber++; 348754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (TypeUtils.isWideType(parameterType)) { 349754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver registerNumber++; 350cb3e0ea38a669633b8daefd538750c8ded46f524Ben Gruver } 351b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com } 352b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com } 353b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com 354754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver @Nonnull public LabelCache getLabelCache() { 355754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver return labelCache; 356754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver } 357db26b663aa3b5bb721185b8798b6767710d3c243JesusFreke@JesusFreke.com 358754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver public int getPackedSwitchBaseAddress(int packedSwitchPayloadCodeOffset) { 359754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver return packedSwitchMap.get(packedSwitchPayloadCodeOffset, -1); 360db26b663aa3b5bb721185b8798b6767710d3c243JesusFreke@JesusFreke.com } 361db26b663aa3b5bb721185b8798b6767710d3c243JesusFreke@JesusFreke.com 362754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver public int getSparseSwitchBaseAddress(int sparseSwitchPayloadCodeOffset) { 363754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver return sparseSwitchMap.get(sparseSwitchPayloadCodeOffset, -1); 364343df2f456f38c305ee7d6742f6601d9bde09715Ben Gruver } 365343df2f456f38c305ee7d6742f6601d9bde09715Ben Gruver 366b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com private List<MethodItem> getMethodItems() { 367f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com ArrayList<MethodItem> methodItems = new ArrayList<MethodItem>(); 3689bc4978139ca38e422ae89065d3062146534132dJesusFreke@JesusFreke.com 369827e2db34dc3b8b5504c148a09d594b5c0ddbd64Ben Gruver if ((classDef.options.registerInfo != 0) || (classDef.options.normalizeVirtualMethods) || 370827e2db34dc3b8b5504c148a09d594b5c0ddbd64Ben Gruver (classDef.options.deodex && needsAnalyzed())) { 371c91b03ba45ccacfa7b0ad52592a42e8fd8c18da1Ben Gruver addAnalyzedInstructionMethodItems(methodItems); 372c91b03ba45ccacfa7b0ad52592a42e8fd8c18da1Ben Gruver } else { 373c91b03ba45ccacfa7b0ad52592a42e8fd8c18da1Ben Gruver addInstructionMethodItems(methodItems); 374c91b03ba45ccacfa7b0ad52592a42e8fd8c18da1Ben Gruver } 375f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 376f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com addTries(methodItems); 3775a5eafb818cc18baeef8bdae1940401da3735f25Ben Gruver if (classDef.options.debugInfo) { 3788913c59363230bc1bf787b7e24941cb13209de0cJesusFreke@JesusFreke.com addDebugInfo(methodItems); 3798913c59363230bc1bf787b7e24941cb13209de0cJesusFreke@JesusFreke.com } 380f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 3815a5eafb818cc18baeef8bdae1940401da3735f25Ben Gruver if (classDef.options.sequentialLabels) { 382f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com setLabelSequentialNumbers(); 383f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com } 384f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 385f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com for (LabelMethodItem labelMethodItem: labelCache.getLabels()) { 386e01409c11f10de58a47df9bc02c6c715b75c6289JesusFreke@JesusFreke.com methodItems.add(labelMethodItem); 387f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com } 388f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 389f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com Collections.sort(methodItems); 390f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 391f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com return methodItems; 392f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com } 393f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 394c91b03ba45ccacfa7b0ad52592a42e8fd8c18da1Ben Gruver private boolean needsAnalyzed() { 395c91b03ba45ccacfa7b0ad52592a42e8fd8c18da1Ben Gruver for (Instruction instruction: methodImpl.getInstructions()) { 396c91b03ba45ccacfa7b0ad52592a42e8fd8c18da1Ben Gruver if (instruction.getOpcode().odexOnly()) { 397c91b03ba45ccacfa7b0ad52592a42e8fd8c18da1Ben Gruver return true; 398c91b03ba45ccacfa7b0ad52592a42e8fd8c18da1Ben Gruver } 399c91b03ba45ccacfa7b0ad52592a42e8fd8c18da1Ben Gruver } 400c91b03ba45ccacfa7b0ad52592a42e8fd8c18da1Ben Gruver return false; 401c91b03ba45ccacfa7b0ad52592a42e8fd8c18da1Ben Gruver } 402c91b03ba45ccacfa7b0ad52592a42e8fd8c18da1Ben Gruver 403f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com private void addInstructionMethodItems(List<MethodItem> methodItems) { 404f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com int currentCodeAddress = 0; 405bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver 406bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver for (int i=0; i<effectiveInstructions.size(); i++) { 407bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver Instruction instruction = effectiveInstructions.get(i); 408f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 409f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com MethodItem methodItem = InstructionMethodItemFactory.makeInstructionFormatMethodItem(this, 410754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver currentCodeAddress, instruction); 411f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 412f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com methodItems.add(methodItem); 413f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 414bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver if (i != effectiveInstructions.size() - 1) { 415f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com methodItems.add(new BlankMethodItem(currentCodeAddress)); 416f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com } 417f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 4185a5eafb818cc18baeef8bdae1940401da3735f25Ben Gruver if (classDef.options.codeOffsets) { 419f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com methodItems.add(new MethodItem(currentCodeAddress) { 420f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 421f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com @Override 422f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com public double getSortOrder() { 423f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com return -1000; 424f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com } 425f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 426f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com @Override 427f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com public boolean writeTo(IndentingWriter writer) throws IOException { 428f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com writer.write("#@"); 429754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.printUnsignedLongAsHex(codeAddress & 0xFFFFFFFFL); 430f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com return true; 431f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com } 432f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com }); 433f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com } 434c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com 435961c21be988e842cb552e8e55f59b69656bffc6cBen Gruver if (classDef.options.accessorComments && classDef.options.syntheticAccessorResolver != null && 436961c21be988e842cb552e8e55f59b69656bffc6cBen Gruver (instruction instanceof ReferenceInstruction)) { 437754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver Opcode opcode = instruction.getOpcode(); 4382f376953b4c96542f200724727e4dac74dd27425jesusfreke@jesusfreke.com 4392b8845bb247e3e5ee154966866b53fa9887e2609Ben Gruver if (opcode.referenceType == ReferenceType.METHOD) { 4404f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver MethodReference methodReference = null; 4414f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver try { 4424f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver methodReference = (MethodReference)((ReferenceInstruction)instruction).getReference(); 4434f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver } catch (InvalidItemIndex ex) { 4444f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver // just ignore it for now. We'll deal with it later, when processing the instructions 4454f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver // themselves 4464f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver } 4472b8845bb247e3e5ee154966866b53fa9887e2609Ben Gruver 4484f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver if (methodReference != null && 4494f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver SyntheticAccessorResolver.looksLikeSyntheticAccessor(methodReference.getName())) { 450bd6385f06205cdf98269eb4a2412000b35ac9d62Ben Gruver AccessedMember accessedMember = 45193aa50139c4641d931b05608f73af8879c0de1c2Ben Gruver classDef.options.syntheticAccessorResolver.getAccessedMember(methodReference); 4522f376953b4c96542f200724727e4dac74dd27425jesusfreke@jesusfreke.com if (accessedMember != null) { 4532f376953b4c96542f200724727e4dac74dd27425jesusfreke@jesusfreke.com methodItems.add(new SyntheticAccessCommentMethodItem(accessedMember, currentCodeAddress)); 4542f376953b4c96542f200724727e4dac74dd27425jesusfreke@jesusfreke.com } 4552f376953b4c96542f200724727e4dac74dd27425jesusfreke@jesusfreke.com } 4562f376953b4c96542f200724727e4dac74dd27425jesusfreke@jesusfreke.com } 4572b8845bb247e3e5ee154966866b53fa9887e2609Ben Gruver } 4582f376953b4c96542f200724727e4dac74dd27425jesusfreke@jesusfreke.com 459754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver currentCodeAddress += instruction.getCodeUnits(); 460f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com } 461f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com } 462f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 463c91b03ba45ccacfa7b0ad52592a42e8fd8c18da1Ben Gruver private void addAnalyzedInstructionMethodItems(List<MethodItem> methodItems) { 46493aa50139c4641d931b05608f73af8879c0de1c2Ben Gruver MethodAnalyzer methodAnalyzer = new MethodAnalyzer(classDef.options.classPath, method, 465827e2db34dc3b8b5504c148a09d594b5c0ddbd64Ben Gruver classDef.options.inlineResolver, classDef.options.normalizeVirtualMethods); 466f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 467c91b03ba45ccacfa7b0ad52592a42e8fd8c18da1Ben Gruver AnalysisException analysisException = methodAnalyzer.getAnalysisException(); 468c91b03ba45ccacfa7b0ad52592a42e8fd8c18da1Ben Gruver if (analysisException != null) { 469a55990c876eab2489e824711da23e5abc7bff1a5Ben Gruver // TODO: need to keep track of whether any errors occurred, so we can exit with a non-zero result 470f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com methodItems.add(new CommentMethodItem( 471a55990c876eab2489e824711da23e5abc7bff1a5Ben Gruver String.format("AnalysisException: %s", analysisException.getMessage()), 472c91b03ba45ccacfa7b0ad52592a42e8fd8c18da1Ben Gruver analysisException.codeAddress, Integer.MIN_VALUE)); 473a55990c876eab2489e824711da23e5abc7bff1a5Ben Gruver analysisException.printStackTrace(System.err); 4747e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com } 475f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 476c91b03ba45ccacfa7b0ad52592a42e8fd8c18da1Ben Gruver List<AnalyzedInstruction> instructions = methodAnalyzer.getAnalyzedInstructions(); 477ad1085e32a17b342c2418c117c59d9c8305d71fcJesusFreke@JesusFreke.com 478b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com int currentCodeAddress = 0; 479ef24b31c9872b24f60c88bdae9b2d8c93eb36feeJesusFreke@JesusFreke.com for (int i=0; i<instructions.size(); i++) { 480ef24b31c9872b24f60c88bdae9b2d8c93eb36feeJesusFreke@JesusFreke.com AnalyzedInstruction instruction = instructions.get(i); 481ad1085e32a17b342c2418c117c59d9c8305d71fcJesusFreke@JesusFreke.com 482c91b03ba45ccacfa7b0ad52592a42e8fd8c18da1Ben Gruver MethodItem methodItem = InstructionMethodItemFactory.makeInstructionFormatMethodItem( 483c91b03ba45ccacfa7b0ad52592a42e8fd8c18da1Ben Gruver this, currentCodeAddress, instruction.getInstruction()); 484650725bbd3c5e10b9f29d3bcbab473b20a89d57bJesusFreke@JesusFreke.com 485e01409c11f10de58a47df9bc02c6c715b75c6289JesusFreke@JesusFreke.com methodItems.add(methodItem); 4860c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com 487c91b03ba45ccacfa7b0ad52592a42e8fd8c18da1Ben Gruver if (instruction.getInstruction().getOpcode().format == Format.UnresolvedOdexInstruction) { 4886eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com methodItems.add(new CommentedOutMethodItem( 489c91b03ba45ccacfa7b0ad52592a42e8fd8c18da1Ben Gruver InstructionMethodItemFactory.makeInstructionFormatMethodItem( 490c91b03ba45ccacfa7b0ad52592a42e8fd8c18da1Ben Gruver this, currentCodeAddress, instruction.getOriginalInstruction()))); 4910c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com } 4927ab77bc90be62b0688c97d4476e3bd219eace0daJesusFreke@JesusFreke.com 493ef24b31c9872b24f60c88bdae9b2d8c93eb36feeJesusFreke@JesusFreke.com if (i != instructions.size() - 1) { 4946eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com methodItems.add(new BlankMethodItem(currentCodeAddress)); 495b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com } 496e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com 4975a5eafb818cc18baeef8bdae1940401da3735f25Ben Gruver if (classDef.options.codeOffsets) { 4986eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com methodItems.add(new MethodItem(currentCodeAddress) { 4992bdbf739bfd935877e463bc36df0e446b1dfb09fJesusFreke@JesusFreke.com 5006eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com @Override 5016eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com public double getSortOrder() { 5026eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com return -1000; 5031c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com } 5041c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com 5056eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com @Override 5060b2f7d6a57e90424b3ee455c041aab3996c05f2cJesusFreke@JesusFreke.com public boolean writeTo(IndentingWriter writer) throws IOException { 5076eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com writer.write("#@"); 508c91b03ba45ccacfa7b0ad52592a42e8fd8c18da1Ben Gruver writer.printUnsignedLongAsHex(codeAddress & 0xFFFFFFFFL); 5096eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com return true; 5101c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com } 5116eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com }); 5126eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com } 5131c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com 51493aa50139c4641d931b05608f73af8879c0de1c2Ben Gruver if (classDef.options.registerInfo != 0 && 51593aa50139c4641d931b05608f73af8879c0de1c2Ben Gruver !instruction.getInstruction().getOpcode().format.isPayloadFormat) { 5166eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com methodItems.add( 51793aa50139c4641d931b05608f73af8879c0de1c2Ben Gruver new PreInstructionRegisterInfoMethodItem(classDef.options.registerInfo, 518c91b03ba45ccacfa7b0ad52592a42e8fd8c18da1Ben Gruver methodAnalyzer, registerFormatter, instruction, currentCodeAddress)); 5191c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com 5206eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com methodItems.add( 521c91b03ba45ccacfa7b0ad52592a42e8fd8c18da1Ben Gruver new PostInstructionRegisterInfoMethodItem(registerFormatter, instruction, currentCodeAddress)); 5221c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com } 5237e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com 524c91b03ba45ccacfa7b0ad52592a42e8fd8c18da1Ben Gruver currentCodeAddress += instruction.getInstruction().getCodeUnits(); 525b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com } 526c91b03ba45ccacfa7b0ad52592a42e8fd8c18da1Ben Gruver } 527e24e70f9ad584d45d2a2af911c1d056163f1bc74JesusFreke@JesusFreke.com 528b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com private void addTries(List<MethodItem> methodItems) { 5291bf6f2324541df184689fdb2c0d8188af5221784Ben Gruver List<? extends TryBlock<? extends ExceptionHandler>> tryBlocks = methodImpl.getTryBlocks(); 530754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (tryBlocks.size() == 0) { 531b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com return; 532b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com } 533e24e70f9ad584d45d2a2af911c1d056163f1bc74JesusFreke@JesusFreke.com 534754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver int lastInstructionAddress = instructionOffsetMap.getInstructionCodeOffset(instructions.size() - 1); 535754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver int codeSize = lastInstructionAddress + instructions.get(instructions.size() - 1).getCodeUnits(); 536b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com 5371bf6f2324541df184689fdb2c0d8188af5221784Ben Gruver for (TryBlock<? extends ExceptionHandler> tryBlock: tryBlocks) { 538bea9627ed75546d7df9e79c927b9329c70a29808Ben Gruver int startAddress = tryBlock.getStartCodeAddress(); 539754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver int endAddress = startAddress + tryBlock.getCodeUnitCount(); 540b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com 5415934004fe3c1e9617793aa120e88f5df1b651c14Ben Gruver if (startAddress >= codeSize) { 5425934004fe3c1e9617793aa120e88f5df1b651c14Ben Gruver throw new RuntimeException(String.format("Try start offset %d is past the end of the code block.", 5435934004fe3c1e9617793aa120e88f5df1b651c14Ben Gruver startAddress)); 5445934004fe3c1e9617793aa120e88f5df1b651c14Ben Gruver } 5455934004fe3c1e9617793aa120e88f5df1b651c14Ben Gruver // Note: not >=. endAddress == codeSize is valid, when the try covers the last instruction 5465934004fe3c1e9617793aa120e88f5df1b651c14Ben Gruver if (endAddress > codeSize) { 5475934004fe3c1e9617793aa120e88f5df1b651c14Ben Gruver throw new RuntimeException(String.format("Try end offset %d is past the end of the code block.", 5485934004fe3c1e9617793aa120e88f5df1b651c14Ben Gruver endAddress)); 5495934004fe3c1e9617793aa120e88f5df1b651c14Ben Gruver } 5505934004fe3c1e9617793aa120e88f5df1b651c14Ben Gruver 551b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com /** 552b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com * The end address points to the address immediately after the end of the last 553b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com * instruction that the try block covers. We want the .catch directive and end_try 554b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com * label to be associated with the last covered instruction, so we need to get 555b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com * the address for that instruction 556b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com */ 557b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com 558754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver int lastCoveredIndex = instructionOffsetMap.getInstructionIndexAtCodeOffset(endAddress - 1, false); 559754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver int lastCoveredAddress = instructionOffsetMap.getInstructionCodeOffset(lastCoveredIndex); 560ad1085e32a17b342c2418c117c59d9c8305d71fcJesusFreke@JesusFreke.com 561754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver for (ExceptionHandler handler: tryBlock.getExceptionHandlers()) { 562bea9627ed75546d7df9e79c927b9329c70a29808Ben Gruver int handlerAddress = handler.getHandlerCodeAddress(); 563bea9627ed75546d7df9e79c927b9329c70a29808Ben Gruver if (handlerAddress >= codeSize) { 564754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver throw new ExceptionWithContext( 565bea9627ed75546d7df9e79c927b9329c70a29808Ben Gruver "Exception handler offset %d is past the end of the code block.", handlerAddress); 5665934004fe3c1e9617793aa120e88f5df1b651c14Ben Gruver } 5675934004fe3c1e9617793aa120e88f5df1b651c14Ben Gruver 568b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com //use the address from the last covered instruction 56993aa50139c4641d931b05608f73af8879c0de1c2Ben Gruver CatchMethodItem catchMethodItem = new CatchMethodItem(classDef.options, labelCache, lastCoveredAddress, 570bea9627ed75546d7df9e79c927b9329c70a29808Ben Gruver handler.getExceptionType(), startAddress, endAddress, handlerAddress); 571b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com methodItems.add(catchMethodItem); 572c65a8d8b5f2091a6bd835617262840a3f52c5c00JesusFreke@JesusFreke.com } 573c65a8d8b5f2091a6bd835617262840a3f52c5c00JesusFreke@JesusFreke.com } 574b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com } 575c65a8d8b5f2091a6bd835617262840a3f52c5c00JesusFreke@JesusFreke.com 576b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com private void addDebugInfo(final List<MethodItem> methodItems) { 577754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver for (DebugItem debugItem: methodImpl.getDebugItems()) { 578754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver methodItems.add(DebugMethodItem.build(registerFormatter, debugItem)); 579c65a8d8b5f2091a6bd835617262840a3f52c5c00JesusFreke@JesusFreke.com } 580b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com } 581e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com 582b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com private void setLabelSequentialNumbers() { 583b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com HashMap<String, Integer> nextLabelSequenceByType = new HashMap<String, Integer>(); 584b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com ArrayList<LabelMethodItem> sortedLabels = new ArrayList<LabelMethodItem>(labelCache.getLabels()); 585e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com 586b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com //sort the labels by their location in the method 587b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com Collections.sort(sortedLabels); 588e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com 589b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com for (LabelMethodItem labelMethodItem: sortedLabels) { 590b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com Integer labelSequence = nextLabelSequenceByType.get(labelMethodItem.getLabelPrefix()); 591b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com if (labelSequence == null) { 592b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com labelSequence = 0; 593e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com } 594b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com labelMethodItem.setLabelSequence(labelSequence); 595b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com nextLabelSequenceByType.put(labelMethodItem.getLabelPrefix(), labelSequence + 1); 596e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com } 597e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com } 598e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com 599d33fd6773cc3e527b4dbb79245796d556b7facdeBen Gruver @Nullable 600d33fd6773cc3e527b4dbb79245796d556b7facdeBen Gruver private String getContainingClassForImplicitReference() { 6015a5eafb818cc18baeef8bdae1940401da3735f25Ben Gruver if (classDef.options.implicitReferences) { 602d33fd6773cc3e527b4dbb79245796d556b7facdeBen Gruver return classDef.classDef.getType(); 603d33fd6773cc3e527b4dbb79245796d556b7facdeBen Gruver } 604d33fd6773cc3e527b4dbb79245796d556b7facdeBen Gruver return null; 605d33fd6773cc3e527b4dbb79245796d556b7facdeBen Gruver } 606d33fd6773cc3e527b4dbb79245796d556b7facdeBen Gruver 607e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com public static class LabelCache { 608e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com protected HashMap<LabelMethodItem, LabelMethodItem> labels = new HashMap<LabelMethodItem, LabelMethodItem>(); 609e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com 610e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com public LabelCache() { 611e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com } 612e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com 613e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com public LabelMethodItem internLabel(LabelMethodItem labelMethodItem) { 614e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com LabelMethodItem internedLabelMethodItem = labels.get(labelMethodItem); 615e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com if (internedLabelMethodItem != null) { 616e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com return internedLabelMethodItem; 617e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com } 618e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com labels.put(labelMethodItem, labelMethodItem); 619e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com return labelMethodItem; 620e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com } 621e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com 622e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com 623e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com public Collection<LabelMethodItem> getLabels() { 624e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com return labels.values(); 625e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com } 62636836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com } 6274f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver 6284f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver public static class InvalidSwitchPayload extends ExceptionWithContext { 6294f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver private final int payloadOffset; 6304f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver 6314f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver public InvalidSwitchPayload(int payloadOffset) { 6324f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver super("No switch payload at offset: %d", payloadOffset); 6334f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver this.payloadOffset = payloadOffset; 6344f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver } 6354f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver 6364f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver public int getPayloadOffset() { 6374f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver return payloadOffset; 6384f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver } 6394f2620415d505a35d2d14b866cde10a54b1b7c8cBen Gruver } 64036836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com} 641