MethodDefinition.java revision c3a3ee3799e354b6718ce8eee2cf20cbac1ca9d9
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 31754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruverimport org.jf.baksmali.Adaptors.Debug.DebugMethodItem; 32fbea4e751fa6f1748ded4379a4b64601cb53ba7bJesusFreke@JesusFreke.comimport org.jf.baksmali.Adaptors.Format.InstructionMethodItemFactory; 33754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruverimport org.jf.dexlib2.AccessFlags; 34754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruverimport org.jf.dexlib2.Opcode; 35754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruverimport org.jf.dexlib2.iface.*; 36754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruverimport org.jf.dexlib2.iface.debug.DebugItem; 37754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruverimport org.jf.dexlib2.iface.instruction.Instruction; 38754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruverimport org.jf.dexlib2.iface.instruction.OffsetInstruction; 39754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruverimport org.jf.dexlib2.util.InstructionOffsetMap; 40754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruverimport org.jf.dexlib2.util.MethodUtil; 41754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruverimport org.jf.dexlib2.util.TypeUtils; 424b72225e9d81201838f387171a68a832486903f9JesusFreke@JesusFreke.comimport org.jf.util.IndentingWriter; 435b89857df3124851183c75a134f10b6ba41512a9JesusFreke@JesusFreke.comimport org.jf.baksmali.baksmali; 44bf95959ae43ddd003936a01dfaecc612a438d4b5Ben Gruverimport org.jf.util.ExceptionWithContext; 45b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.comimport org.jf.dexlib.Util.SparseIntArray; 4636836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com 47754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruverimport javax.annotation.Nonnull; 486eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.comimport java.io.IOException; 499bc4978139ca38e422ae89065d3062146534132dJesusFreke@JesusFreke.comimport java.util.*; 500b2f7d6a57e90424b3ee455c041aab3996c05f2cJesusFreke@JesusFreke.com 5136836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.compublic class MethodDefinition { 52754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver @Nonnull public final ClassDefinition classDef; 53754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver @Nonnull public final Method method; 54754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver @Nonnull public final MethodImplementation methodImpl; 55754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver public RegisterFormatter registerFormatter; 56b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com 57754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver @Nonnull private final String methodString; 58b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com 59754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver @Nonnull private final LabelCache labelCache = new LabelCache(); 60b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com 61754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver @Nonnull private final SparseIntArray packedSwitchMap; 62754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver @Nonnull private final SparseIntArray sparseSwitchMap; 63754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver @Nonnull private final InstructionOffsetMap instructionOffsetMap; 6410a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com 65754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver public MethodDefinition(@Nonnull ClassDefinition classDef, @Nonnull Method method, 66754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver @Nonnull MethodImplementation methodImpl) { 67754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver this.classDef = classDef; 68754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver this.method = method; 69754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver this.methodImpl = methodImpl; 7010a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com 71754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver this.methodString = MethodUtil.buildFullMethodString(classDef.classDef, method); 7210a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com 73754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver try { 7410a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com //TODO: what about try/catch blocks inside the dead code? those will need to be commented out too. ugh. 7510a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com 76754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver List<? extends Instruction> instructions = methodImpl.getInstructions(); 77754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver 78754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver packedSwitchMap = new SparseIntArray(0); 79754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver sparseSwitchMap = new SparseIntArray(0); 80754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver instructionOffsetMap = new InstructionOffsetMap(methodImpl); 81754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver 82754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver for (int i=0; i<instructions.size(); i++) { 83754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver Instruction instruction = instructions.get(i); 84754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver 85754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver Opcode opcode = instruction.getOpcode(); 86754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (opcode == Opcode.PACKED_SWITCH) { 87754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver int codeOffset = instructionOffsetMap.getInstructionCodeOffset(i); 88754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver int targetOffset = codeOffset + ((OffsetInstruction)instruction).getCodeOffset(); 89754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver targetOffset = findSwitchPayload(targetOffset, Opcode.PACKED_SWITCH_PAYLOAD); 90754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver packedSwitchMap.append(codeOffset, targetOffset); 91754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver } else if (opcode == Opcode.SPARSE_SWITCH) { 92754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver int codeOffset = instructionOffsetMap.getInstructionCodeOffset(i); 93754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver int targetOffset = codeOffset + ((OffsetInstruction)instruction).getCodeOffset(); 94754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver targetOffset = findSwitchPayload(targetOffset, Opcode.SPARSE_SWITCH_PAYLOAD); 95754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver sparseSwitchMap.append(codeOffset, targetOffset); 96b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com } 97b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com } 9810a95181115741071ae23911413a3f731047621cJesusFreke@JesusFreke.com }catch (Exception ex) { 99754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver throw ExceptionWithContext.withContext(ex, "Error while processing method %s", methodString); 100b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com } 101b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com } 102b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com 103754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver public static void writeEmptyMethodTo(IndentingWriter writer, Method method) throws IOException { 1046eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com writer.write(".method "); 105754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writeAccessFlags(writer, method.getAccessFlags()); 106754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write(method.getName()); 107754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write("("); 108754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver for (MethodParameter parameter: method.getParameters()) { 109754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write(parameter.getType()); 110754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver } 111754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write(")"); 112754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write(method.getReturnType()); 1130b2f7d6a57e90424b3ee455c041aab3996c05f2cJesusFreke@JesusFreke.com writer.write('\n'); 11436836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com 1156eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com writer.indent(4); 116c3a3ee3799e354b6718ce8eee2cf20cbac1ca9d9Ben Gruver writeParameters(writer, method); 117754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver AnnotationFormatter.writeTo(writer, method.getAnnotations()); 1186eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com writer.deindent(4); 1190b2f7d6a57e90424b3ee455c041aab3996c05f2cJesusFreke@JesusFreke.com writer.write(".end method\n"); 12036836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com } 12136836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com 122754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver public void writeTo(IndentingWriter writer) throws IOException { 123754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver int parameterRegisterCount = 0; 124754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (!AccessFlags.STATIC.isSet(method.getAccessFlags())) { 125754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver parameterRegisterCount++; 12636836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com } 127fa07a1972e3cff56d5615c18a8797ff58fc9f739JesusFreke@JesusFreke.com 128754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write(".method "); 129754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writeAccessFlags(writer, method.getAccessFlags()); 130754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write(method.getName()); 131754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write("("); 132754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver for (MethodParameter parameter: method.getParameters()) { 133754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver String type = parameter.getType(); 134754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write(type); 135754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver parameterRegisterCount++; 136754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (TypeUtils.isWideType(type)) { 137754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver parameterRegisterCount++; 138754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver } 1393c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com } 140754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write(")"); 141754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write(method.getReturnType()); 142754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write('\n'); 1433c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com 144754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.indent(4); 145754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (baksmali.useLocalsDirective) { 146754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write(".locals "); 147754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.printSignedIntAsDec(methodImpl.getRegisterCount() - parameterRegisterCount); 1486eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com } else { 149754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write(".registers "); 150754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.printSignedIntAsDec(methodImpl.getRegisterCount()); 1516eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com } 152754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write('\n'); 153c3a3ee3799e354b6718ce8eee2cf20cbac1ca9d9Ben Gruver writeParameters(writer, method); 1543c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com 155754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (registerFormatter == null) { 156754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver registerFormatter = new RegisterFormatter(methodImpl.getRegisterCount(), parameterRegisterCount); 1573c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com } 1583c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com 159754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver AnnotationFormatter.writeTo(writer, method.getAnnotations()); 1603c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com 161754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write('\n'); 1626eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com 163754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver for (MethodItem methodItem: getMethodItems()) { 164754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (methodItem.writeTo(writer)) { 165754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write('\n'); 1666eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com } 1676eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com } 168754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.deindent(4); 169754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write(".end method\n"); 1703c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com } 1713c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com 172754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver private int findSwitchPayload(int targetOffset, Opcode type) { 173754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver int targetIndex = instructionOffsetMap.getInstructionIndexAtCodeOffset(targetOffset); 174754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver 175754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver //TODO: does dalvik let you pad with multiple nops? 176754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver //TODO: does dalvik let a switch instruction point to a non-payload instruction? 177754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver 178754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver List<? extends Instruction> instructions = methodImpl.getInstructions(); 179754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver Instruction instruction = instructions.get(targetIndex); 180754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (instruction.getOpcode() != type) { 181754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver // maybe it's pointing to a NOP padding instruction. Look at the next instruction 182754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (instruction.getOpcode() == Opcode.NOP) { 183754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver targetIndex += 1; 184754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (targetIndex < instructions.size()) { 185754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver instruction = instructions.get(targetIndex); 186754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (instruction.getOpcode() == type) { 187754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver return instructionOffsetMap.getInstructionCodeOffset(targetIndex); 188754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver } 189754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver } 190754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver } 191754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver throw new ExceptionWithContext("No switch payload at offset 0x%x", targetOffset); 192754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver } else { 193754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver return targetOffset; 194c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com } 195c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com } 196c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com 197754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver private static void writeAccessFlags(IndentingWriter writer, int accessFlags) 198754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver throws IOException { 199754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver for (AccessFlags accessFlag: AccessFlags.getAccessFlagsForMethod(accessFlags)) { 200754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write(accessFlag.toString()); 201754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write(' '); 202b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com } 203b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com } 204b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com 205c3a3ee3799e354b6718ce8eee2cf20cbac1ca9d9Ben Gruver private static void writeParameters(IndentingWriter writer, Method method) throws IOException { 206c3a3ee3799e354b6718ce8eee2cf20cbac1ca9d9Ben Gruver boolean isStatic = AccessFlags.STATIC.isSet(method.getAccessFlags()); 207c3a3ee3799e354b6718ce8eee2cf20cbac1ca9d9Ben Gruver int registerNumber = isStatic?0:1; 208c3a3ee3799e354b6718ce8eee2cf20cbac1ca9d9Ben Gruver for (MethodParameter parameter: method.getParameters()) { 209754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver String parameterType = parameter.getType(); 210754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver String parameterName = parameter.getName(); 211754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver List<? extends Annotation> annotations = parameter.getAnnotations(); 212754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (parameterName != null || annotations.size() != 0) { 21316f257ee8f12974c62e50643b2f87533513da455Ben Gruver writer.write(".param p"); 214754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.printSignedIntAsDec(registerNumber); 215754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (parameterName != null) { 21616f257ee8f12974c62e50643b2f87533513da455Ben Gruver writer.write(", "); 217db4316ef6ddeaaae94ca88673b6bac1c2b29eec5Ben Gruver // TODO: does dalvik allow non-identifier parameter and/or local names? 218754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write(parameterName); 219754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver } 220c3a3ee3799e354b6718ce8eee2cf20cbac1ca9d9Ben Gruver writer.write(" # "); 22116f257ee8f12974c62e50643b2f87533513da455Ben Gruver writer.write(parameterType); 222754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (annotations.size() > 0) { 223754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.indent(4); 224754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver AnnotationFormatter.writeTo(writer, annotations); 225754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.deindent(4); 22616f257ee8f12974c62e50643b2f87533513da455Ben Gruver writer.write(".end param\n"); 227754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver } else { 228754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write("\n"); 229754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver } 230754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver } 231cb3e0ea38a669633b8daefd538750c8ded46f524Ben Gruver 232754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver registerNumber++; 233754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (TypeUtils.isWideType(parameterType)) { 234754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver registerNumber++; 235cb3e0ea38a669633b8daefd538750c8ded46f524Ben Gruver } 236b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com } 237b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com } 238b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com 239754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver @Nonnull public LabelCache getLabelCache() { 240754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver return labelCache; 241754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver } 242db26b663aa3b5bb721185b8798b6767710d3c243JesusFreke@JesusFreke.com 243754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver public int getPackedSwitchBaseAddress(int packedSwitchPayloadCodeOffset) { 244754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver return packedSwitchMap.get(packedSwitchPayloadCodeOffset, -1); 245db26b663aa3b5bb721185b8798b6767710d3c243JesusFreke@JesusFreke.com } 246db26b663aa3b5bb721185b8798b6767710d3c243JesusFreke@JesusFreke.com 247754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver public int getSparseSwitchBaseAddress(int sparseSwitchPayloadCodeOffset) { 248754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver return sparseSwitchMap.get(sparseSwitchPayloadCodeOffset, -1); 249343df2f456f38c305ee7d6742f6601d9bde09715Ben Gruver } 250343df2f456f38c305ee7d6742f6601d9bde09715Ben Gruver 251b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com private List<MethodItem> getMethodItems() { 252f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com ArrayList<MethodItem> methodItems = new ArrayList<MethodItem>(); 2539bc4978139ca38e422ae89065d3062146534132dJesusFreke@JesusFreke.com 254754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver //TODO: addAnalyzedInstructionMethodItems 255754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver addInstructionMethodItems(methodItems); 256f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 257f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com addTries(methodItems); 2588913c59363230bc1bf787b7e24941cb13209de0cJesusFreke@JesusFreke.com if (baksmali.outputDebugInfo) { 2598913c59363230bc1bf787b7e24941cb13209de0cJesusFreke@JesusFreke.com addDebugInfo(methodItems); 2608913c59363230bc1bf787b7e24941cb13209de0cJesusFreke@JesusFreke.com } 261f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 262f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com if (baksmali.useSequentialLabels) { 263f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com setLabelSequentialNumbers(); 264f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com } 265f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 266f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com for (LabelMethodItem labelMethodItem: labelCache.getLabels()) { 267e01409c11f10de58a47df9bc02c6c715b75c6289JesusFreke@JesusFreke.com methodItems.add(labelMethodItem); 268f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com } 269f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 270f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com Collections.sort(methodItems); 271f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 272f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com return methodItems; 273f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com } 274f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 275f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com private void addInstructionMethodItems(List<MethodItem> methodItems) { 276754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver List<? extends Instruction> instructions = methodImpl.getInstructions(); 277f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 278f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com int currentCodeAddress = 0; 279754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver for (int i=0; i<instructions.size(); i++) { 280754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver Instruction instruction = instructions.get(i); 281f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 282f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com MethodItem methodItem = InstructionMethodItemFactory.makeInstructionFormatMethodItem(this, 283754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver currentCodeAddress, instruction); 284f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 285f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com methodItems.add(methodItem); 286f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 287754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (i != instructions.size() - 1) { 288f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com methodItems.add(new BlankMethodItem(currentCodeAddress)); 289f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com } 290f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 291f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com if (baksmali.addCodeOffsets) { 292f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com methodItems.add(new MethodItem(currentCodeAddress) { 293f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 294f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com @Override 295f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com public double getSortOrder() { 296f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com return -1000; 297f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com } 298f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 299f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com @Override 300f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com public boolean writeTo(IndentingWriter writer) throws IOException { 301f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com writer.write("#@"); 302754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.printUnsignedLongAsHex(codeAddress & 0xFFFFFFFFL); 303f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com return true; 304f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com } 305f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com }); 306f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com } 307c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com 308754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver //TODO: uncomment 309754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver /*if (!baksmali.noAccessorComments && (instruction instanceof InstructionWithReference)) { 310754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver Opcode opcode = instruction.getOpcode(); 311754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (opcode == Opcode.INVOKE_STATIC || opcode == Opcode.INVOKE_STATIC_RANGE) { 3122f376953b4c96542f200724727e4dac74dd27425jesusfreke@jesusfreke.com MethodIdItem methodIdItem = 3132f376953b4c96542f200724727e4dac74dd27425jesusfreke@jesusfreke.com (MethodIdItem)((InstructionWithReference) instruction).getReferencedItem(); 3142f376953b4c96542f200724727e4dac74dd27425jesusfreke@jesusfreke.com 3152f376953b4c96542f200724727e4dac74dd27425jesusfreke@jesusfreke.com if (SyntheticAccessorResolver.looksLikeSyntheticAccessor(methodIdItem)) { 3162f376953b4c96542f200724727e4dac74dd27425jesusfreke@jesusfreke.com SyntheticAccessorResolver.AccessedMember accessedMember = 3172f376953b4c96542f200724727e4dac74dd27425jesusfreke@jesusfreke.com baksmali.syntheticAccessorResolver.getAccessedMember(methodIdItem); 3182f376953b4c96542f200724727e4dac74dd27425jesusfreke@jesusfreke.com if (accessedMember != null) { 3192f376953b4c96542f200724727e4dac74dd27425jesusfreke@jesusfreke.com methodItems.add(new SyntheticAccessCommentMethodItem(accessedMember, currentCodeAddress)); 3202f376953b4c96542f200724727e4dac74dd27425jesusfreke@jesusfreke.com } 3212f376953b4c96542f200724727e4dac74dd27425jesusfreke@jesusfreke.com } 3222f376953b4c96542f200724727e4dac74dd27425jesusfreke@jesusfreke.com } 323754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver }*/ 3242f376953b4c96542f200724727e4dac74dd27425jesusfreke@jesusfreke.com 325754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver currentCodeAddress += instruction.getCodeUnits(); 326f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com } 327f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com } 328f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 329754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver //TODO: uncomment 330754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver /*private void addAnalyzedInstructionMethodItems(List<MethodItem> methodItems) { 3315967598d012839eb25d50d9fa63952ac802e05ddBen Gruver methodAnalyzer = new MethodAnalyzer(encodedMethod, baksmali.deodex, baksmali.inlineResolver); 332f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 333f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com methodAnalyzer.analyze(); 334f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 335f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com ValidationException validationException = methodAnalyzer.getValidationException(); 336f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com if (validationException != null) { 337f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com methodItems.add(new CommentMethodItem( 338f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com String.format("ValidationException: %s" ,validationException.getMessage()), 339f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com validationException.getCodeAddress(), Integer.MIN_VALUE)); 340f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com } else if (baksmali.verify) { 341f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com methodAnalyzer.verify(); 342f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 343f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com validationException = methodAnalyzer.getValidationException(); 344c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com if (validationException != null) { 3456eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com methodItems.add(new CommentMethodItem( 3461c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com String.format("ValidationException: %s" ,validationException.getMessage()), 347c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com validationException.getCodeAddress(), Integer.MIN_VALUE)); 348c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com } 3497e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com } 350f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 351ef24b31c9872b24f60c88bdae9b2d8c93eb36feeJesusFreke@JesusFreke.com List<AnalyzedInstruction> instructions = methodAnalyzer.getInstructions(); 352ad1085e32a17b342c2418c117c59d9c8305d71fcJesusFreke@JesusFreke.com 353b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com int currentCodeAddress = 0; 354ef24b31c9872b24f60c88bdae9b2d8c93eb36feeJesusFreke@JesusFreke.com for (int i=0; i<instructions.size(); i++) { 355ef24b31c9872b24f60c88bdae9b2d8c93eb36feeJesusFreke@JesusFreke.com AnalyzedInstruction instruction = instructions.get(i); 356ad1085e32a17b342c2418c117c59d9c8305d71fcJesusFreke@JesusFreke.com 357e01409c11f10de58a47df9bc02c6c715b75c6289JesusFreke@JesusFreke.com MethodItem methodItem = InstructionMethodItemFactory.makeInstructionFormatMethodItem(this, 358e01409c11f10de58a47df9bc02c6c715b75c6289JesusFreke@JesusFreke.com encodedMethod.codeItem, currentCodeAddress, instruction.getInstruction()); 359650725bbd3c5e10b9f29d3bcbab473b20a89d57bJesusFreke@JesusFreke.com 360e01409c11f10de58a47df9bc02c6c715b75c6289JesusFreke@JesusFreke.com methodItems.add(methodItem); 3610c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com 362e01409c11f10de58a47df9bc02c6c715b75c6289JesusFreke@JesusFreke.com if (instruction.getInstruction().getFormat() == Format.UnresolvedOdexInstruction) { 3636eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com methodItems.add(new CommentedOutMethodItem( 364e01409c11f10de58a47df9bc02c6c715b75c6289JesusFreke@JesusFreke.com InstructionMethodItemFactory.makeInstructionFormatMethodItem(this, 365e01409c11f10de58a47df9bc02c6c715b75c6289JesusFreke@JesusFreke.com encodedMethod.codeItem, currentCodeAddress, instruction.getOriginalInstruction()))); 3660c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com } 3677ab77bc90be62b0688c97d4476e3bd219eace0daJesusFreke@JesusFreke.com 368ef24b31c9872b24f60c88bdae9b2d8c93eb36feeJesusFreke@JesusFreke.com if (i != instructions.size() - 1) { 3696eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com methodItems.add(new BlankMethodItem(currentCodeAddress)); 370b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com } 371e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com 3722bdbf739bfd935877e463bc36df0e446b1dfb09fJesusFreke@JesusFreke.com if (baksmali.addCodeOffsets) { 3736eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com methodItems.add(new MethodItem(currentCodeAddress) { 3742bdbf739bfd935877e463bc36df0e446b1dfb09fJesusFreke@JesusFreke.com 3756eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com @Override 3766eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com public double getSortOrder() { 3776eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com return -1000; 3781c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com } 3791c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com 3806eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com @Override 3810b2f7d6a57e90424b3ee455c041aab3996c05f2cJesusFreke@JesusFreke.com public boolean writeTo(IndentingWriter writer) throws IOException { 3826eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com writer.write("#@"); 38374c14ffcca0ff4f8f3e66e66022894cd7b0b8540Ben Gruver writer.printUnsignedLongAsHex(codeAddress & 0xFFFFFFFF); 3846eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com return true; 3851c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com } 3866eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com }); 3876eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com } 3881c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com 3896eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com if (baksmali.registerInfo != 0 && !instruction.getInstruction().getFormat().variableSizeFormat) { 3906eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com methodItems.add( 3916eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com new PreInstructionRegisterInfoMethodItem(instruction, methodAnalyzer, currentCodeAddress)); 3921c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com 3936eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com methodItems.add( 3946eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com new PostInstructionRegisterInfoMethodItem(instruction, methodAnalyzer, currentCodeAddress)); 3951c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com } 3967e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com 3970c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com currentCodeAddress += instruction.getInstruction().getSize(currentCodeAddress); 398b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com } 399754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver }*/ 400e24e70f9ad584d45d2a2af911c1d056163f1bc74JesusFreke@JesusFreke.com 401b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com private void addTries(List<MethodItem> methodItems) { 402754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver List<? extends TryBlock> tryBlocks = methodImpl.getTryBlocks(); 403754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (tryBlocks.size() == 0) { 404b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com return; 405b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com } 406e24e70f9ad584d45d2a2af911c1d056163f1bc74JesusFreke@JesusFreke.com 407754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver List<? extends Instruction> instructions = methodImpl.getInstructions(); 408754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver int lastInstructionAddress = instructionOffsetMap.getInstructionCodeOffset(instructions.size() - 1); 409754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver int codeSize = lastInstructionAddress + instructions.get(instructions.size() - 1).getCodeUnits(); 410b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com 411754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver for (TryBlock tryBlock: tryBlocks) { 412754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver int startAddress = tryBlock.getStartCodeOffset(); 413754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver int endAddress = startAddress + tryBlock.getCodeUnitCount(); 414b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com 4155934004fe3c1e9617793aa120e88f5df1b651c14Ben Gruver if (startAddress >= codeSize) { 4165934004fe3c1e9617793aa120e88f5df1b651c14Ben Gruver throw new RuntimeException(String.format("Try start offset %d is past the end of the code block.", 4175934004fe3c1e9617793aa120e88f5df1b651c14Ben Gruver startAddress)); 4185934004fe3c1e9617793aa120e88f5df1b651c14Ben Gruver } 4195934004fe3c1e9617793aa120e88f5df1b651c14Ben Gruver // Note: not >=. endAddress == codeSize is valid, when the try covers the last instruction 4205934004fe3c1e9617793aa120e88f5df1b651c14Ben Gruver if (endAddress > codeSize) { 4215934004fe3c1e9617793aa120e88f5df1b651c14Ben Gruver throw new RuntimeException(String.format("Try end offset %d is past the end of the code block.", 4225934004fe3c1e9617793aa120e88f5df1b651c14Ben Gruver endAddress)); 4235934004fe3c1e9617793aa120e88f5df1b651c14Ben Gruver } 4245934004fe3c1e9617793aa120e88f5df1b651c14Ben Gruver 425b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com /** 426b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com * The end address points to the address immediately after the end of the last 427b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com * instruction that the try block covers. We want the .catch directive and end_try 428b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com * label to be associated with the last covered instruction, so we need to get 429b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com * the address for that instruction 430b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com */ 431b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com 432754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver int lastCoveredIndex = instructionOffsetMap.getInstructionIndexAtCodeOffset(endAddress - 1, false); 433754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver int lastCoveredAddress = instructionOffsetMap.getInstructionCodeOffset(lastCoveredIndex); 434ad1085e32a17b342c2418c117c59d9c8305d71fcJesusFreke@JesusFreke.com 435754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver for (ExceptionHandler handler: tryBlock.getExceptionHandlers()) { 436754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver int handlerOffset = handler.getHandlerCodeOffset(); 437754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (handlerOffset >= codeSize) { 438754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver throw new ExceptionWithContext( 439754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver "Exception handler offset %d is past the end of the code block.", handlerOffset); 4405934004fe3c1e9617793aa120e88f5df1b651c14Ben Gruver } 4415934004fe3c1e9617793aa120e88f5df1b651c14Ben Gruver 442b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com //use the address from the last covered instruction 4435934004fe3c1e9617793aa120e88f5df1b651c14Ben Gruver CatchMethodItem catchMethodItem = new CatchMethodItem(labelCache, lastCoveredAddress, 444754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver handler.getExceptionType(), startAddress, endAddress, handlerOffset); 445b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com methodItems.add(catchMethodItem); 446c65a8d8b5f2091a6bd835617262840a3f52c5c00JesusFreke@JesusFreke.com } 447c65a8d8b5f2091a6bd835617262840a3f52c5c00JesusFreke@JesusFreke.com } 448b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com } 449c65a8d8b5f2091a6bd835617262840a3f52c5c00JesusFreke@JesusFreke.com 450b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com private void addDebugInfo(final List<MethodItem> methodItems) { 451754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver for (DebugItem debugItem: methodImpl.getDebugItems()) { 452754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver methodItems.add(DebugMethodItem.build(registerFormatter, debugItem)); 453c65a8d8b5f2091a6bd835617262840a3f52c5c00JesusFreke@JesusFreke.com } 454b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com } 455e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com 456b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com private void setLabelSequentialNumbers() { 457b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com HashMap<String, Integer> nextLabelSequenceByType = new HashMap<String, Integer>(); 458b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com ArrayList<LabelMethodItem> sortedLabels = new ArrayList<LabelMethodItem>(labelCache.getLabels()); 459e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com 460b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com //sort the labels by their location in the method 461b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com Collections.sort(sortedLabels); 462e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com 463b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com for (LabelMethodItem labelMethodItem: sortedLabels) { 464b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com Integer labelSequence = nextLabelSequenceByType.get(labelMethodItem.getLabelPrefix()); 465b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com if (labelSequence == null) { 466b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com labelSequence = 0; 467e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com } 468b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com labelMethodItem.setLabelSequence(labelSequence); 469b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com nextLabelSequenceByType.put(labelMethodItem.getLabelPrefix(), labelSequence + 1); 470e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com } 471e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com } 472e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com 473e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com public static class LabelCache { 474e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com protected HashMap<LabelMethodItem, LabelMethodItem> labels = new HashMap<LabelMethodItem, LabelMethodItem>(); 475e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com 476e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com public LabelCache() { 477e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com } 478e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com 479e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com public LabelMethodItem internLabel(LabelMethodItem labelMethodItem) { 480e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com LabelMethodItem internedLabelMethodItem = labels.get(labelMethodItem); 481e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com if (internedLabelMethodItem != null) { 482e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com return internedLabelMethodItem; 483e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com } 484e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com labels.put(labelMethodItem, labelMethodItem); 485e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com return labelMethodItem; 486e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com } 487e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com 488e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com 489e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com public Collection<LabelMethodItem> getLabels() { 490e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com return labels.values(); 491e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com } 49236836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com } 49336836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com} 494