MethodDefinition.java revision db49fd7714893b35ba7de51fae8d8e386f3dc335
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); 90d3dd617d250771840c801009e4f71d971c4d4061Ben Gruver packedSwitchMap.append(targetOffset, codeOffset); 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); 95d3dd617d250771840c801009e4f71d971c4d4061Ben Gruver sparseSwitchMap.append(targetOffset, codeOffset); 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 163db49fd7714893b35ba7de51fae8d8e386f3dc335Ben Gruver List<MethodItem> methodItems = getMethodItems(); 164db49fd7714893b35ba7de51fae8d8e386f3dc335Ben Gruver int size = methodItems.size(); 165db49fd7714893b35ba7de51fae8d8e386f3dc335Ben Gruver for (int i=0; i<size; i++) { 166db49fd7714893b35ba7de51fae8d8e386f3dc335Ben Gruver MethodItem methodItem = methodItems.get(i); 167754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (methodItem.writeTo(writer)) { 168754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write('\n'); 1696eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com } 1706eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com } 171754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.deindent(4); 172754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write(".end method\n"); 1733c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com } 1743c9013f9c08fa8effc9f6d4dc58212c68eb21742JesusFreke@JesusFreke.com 175754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver private int findSwitchPayload(int targetOffset, Opcode type) { 176754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver int targetIndex = instructionOffsetMap.getInstructionIndexAtCodeOffset(targetOffset); 177754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver 178754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver //TODO: does dalvik let you pad with multiple nops? 179754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver //TODO: does dalvik let a switch instruction point to a non-payload instruction? 180754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver 181754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver List<? extends Instruction> instructions = methodImpl.getInstructions(); 182754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver Instruction instruction = instructions.get(targetIndex); 183754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (instruction.getOpcode() != type) { 184754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver // maybe it's pointing to a NOP padding instruction. Look at the next instruction 185754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (instruction.getOpcode() == Opcode.NOP) { 186754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver targetIndex += 1; 187754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (targetIndex < instructions.size()) { 188754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver instruction = instructions.get(targetIndex); 189754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (instruction.getOpcode() == type) { 190754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver return instructionOffsetMap.getInstructionCodeOffset(targetIndex); 191754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver } 192754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver } 193754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver } 194754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver throw new ExceptionWithContext("No switch payload at offset 0x%x", targetOffset); 195754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver } else { 196754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver return targetOffset; 197c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com } 198c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com } 199c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com 200754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver private static void writeAccessFlags(IndentingWriter writer, int accessFlags) 201754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver throws IOException { 202754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver for (AccessFlags accessFlag: AccessFlags.getAccessFlagsForMethod(accessFlags)) { 203754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write(accessFlag.toString()); 204754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write(' '); 205b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com } 206b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com } 207b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com 208c3a3ee3799e354b6718ce8eee2cf20cbac1ca9d9Ben Gruver private static void writeParameters(IndentingWriter writer, Method method) throws IOException { 209c3a3ee3799e354b6718ce8eee2cf20cbac1ca9d9Ben Gruver boolean isStatic = AccessFlags.STATIC.isSet(method.getAccessFlags()); 210c3a3ee3799e354b6718ce8eee2cf20cbac1ca9d9Ben Gruver int registerNumber = isStatic?0:1; 211c3a3ee3799e354b6718ce8eee2cf20cbac1ca9d9Ben Gruver for (MethodParameter parameter: method.getParameters()) { 212754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver String parameterType = parameter.getType(); 213754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver String parameterName = parameter.getName(); 214754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver List<? extends Annotation> annotations = parameter.getAnnotations(); 215754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (parameterName != null || annotations.size() != 0) { 21616f257ee8f12974c62e50643b2f87533513da455Ben Gruver writer.write(".param p"); 217754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.printSignedIntAsDec(registerNumber); 218754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (parameterName != null) { 21916f257ee8f12974c62e50643b2f87533513da455Ben Gruver writer.write(", "); 220db4316ef6ddeaaae94ca88673b6bac1c2b29eec5Ben Gruver // TODO: does dalvik allow non-identifier parameter and/or local names? 221754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write(parameterName); 222754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver } 223c3a3ee3799e354b6718ce8eee2cf20cbac1ca9d9Ben Gruver writer.write(" # "); 22416f257ee8f12974c62e50643b2f87533513da455Ben Gruver writer.write(parameterType); 225754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (annotations.size() > 0) { 226754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.indent(4); 227754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver AnnotationFormatter.writeTo(writer, annotations); 228754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.deindent(4); 22916f257ee8f12974c62e50643b2f87533513da455Ben Gruver writer.write(".end param\n"); 230754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver } else { 231754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.write("\n"); 232754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver } 233754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver } 234cb3e0ea38a669633b8daefd538750c8ded46f524Ben Gruver 235754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver registerNumber++; 236754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (TypeUtils.isWideType(parameterType)) { 237754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver registerNumber++; 238cb3e0ea38a669633b8daefd538750c8ded46f524Ben Gruver } 239b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com } 240b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com } 241b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com 242754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver @Nonnull public LabelCache getLabelCache() { 243754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver return labelCache; 244754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver } 245db26b663aa3b5bb721185b8798b6767710d3c243JesusFreke@JesusFreke.com 246754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver public int getPackedSwitchBaseAddress(int packedSwitchPayloadCodeOffset) { 247754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver return packedSwitchMap.get(packedSwitchPayloadCodeOffset, -1); 248db26b663aa3b5bb721185b8798b6767710d3c243JesusFreke@JesusFreke.com } 249db26b663aa3b5bb721185b8798b6767710d3c243JesusFreke@JesusFreke.com 250754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver public int getSparseSwitchBaseAddress(int sparseSwitchPayloadCodeOffset) { 251754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver return sparseSwitchMap.get(sparseSwitchPayloadCodeOffset, -1); 252343df2f456f38c305ee7d6742f6601d9bde09715Ben Gruver } 253343df2f456f38c305ee7d6742f6601d9bde09715Ben Gruver 254b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com private List<MethodItem> getMethodItems() { 255f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com ArrayList<MethodItem> methodItems = new ArrayList<MethodItem>(); 2569bc4978139ca38e422ae89065d3062146534132dJesusFreke@JesusFreke.com 257754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver //TODO: addAnalyzedInstructionMethodItems 258754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver addInstructionMethodItems(methodItems); 259f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 260f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com addTries(methodItems); 2618913c59363230bc1bf787b7e24941cb13209de0cJesusFreke@JesusFreke.com if (baksmali.outputDebugInfo) { 2628913c59363230bc1bf787b7e24941cb13209de0cJesusFreke@JesusFreke.com addDebugInfo(methodItems); 2638913c59363230bc1bf787b7e24941cb13209de0cJesusFreke@JesusFreke.com } 264f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 265f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com if (baksmali.useSequentialLabels) { 266f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com setLabelSequentialNumbers(); 267f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com } 268f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 269f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com for (LabelMethodItem labelMethodItem: labelCache.getLabels()) { 270e01409c11f10de58a47df9bc02c6c715b75c6289JesusFreke@JesusFreke.com methodItems.add(labelMethodItem); 271f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com } 272f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 273f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com Collections.sort(methodItems); 274f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 275f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com return methodItems; 276f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com } 277f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 278f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com private void addInstructionMethodItems(List<MethodItem> methodItems) { 279754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver List<? extends Instruction> instructions = methodImpl.getInstructions(); 280f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 281f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com int currentCodeAddress = 0; 282754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver for (int i=0; i<instructions.size(); i++) { 283754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver Instruction instruction = instructions.get(i); 284f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 285f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com MethodItem methodItem = InstructionMethodItemFactory.makeInstructionFormatMethodItem(this, 286754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver currentCodeAddress, instruction); 287f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 288f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com methodItems.add(methodItem); 289f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 290754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (i != instructions.size() - 1) { 291f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com methodItems.add(new BlankMethodItem(currentCodeAddress)); 292f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com } 293f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 294f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com if (baksmali.addCodeOffsets) { 295f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com methodItems.add(new MethodItem(currentCodeAddress) { 296f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 297f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com @Override 298f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com public double getSortOrder() { 299f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com return -1000; 300f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com } 301f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 302f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com @Override 303f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com public boolean writeTo(IndentingWriter writer) throws IOException { 304f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com writer.write("#@"); 305754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver writer.printUnsignedLongAsHex(codeAddress & 0xFFFFFFFFL); 306f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com return true; 307f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com } 308f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com }); 309f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com } 310c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com 311754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver //TODO: uncomment 312754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver /*if (!baksmali.noAccessorComments && (instruction instanceof InstructionWithReference)) { 313754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver Opcode opcode = instruction.getOpcode(); 314754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (opcode == Opcode.INVOKE_STATIC || opcode == Opcode.INVOKE_STATIC_RANGE) { 3152f376953b4c96542f200724727e4dac74dd27425jesusfreke@jesusfreke.com MethodIdItem methodIdItem = 3162f376953b4c96542f200724727e4dac74dd27425jesusfreke@jesusfreke.com (MethodIdItem)((InstructionWithReference) instruction).getReferencedItem(); 3172f376953b4c96542f200724727e4dac74dd27425jesusfreke@jesusfreke.com 3182f376953b4c96542f200724727e4dac74dd27425jesusfreke@jesusfreke.com if (SyntheticAccessorResolver.looksLikeSyntheticAccessor(methodIdItem)) { 3192f376953b4c96542f200724727e4dac74dd27425jesusfreke@jesusfreke.com SyntheticAccessorResolver.AccessedMember accessedMember = 3202f376953b4c96542f200724727e4dac74dd27425jesusfreke@jesusfreke.com baksmali.syntheticAccessorResolver.getAccessedMember(methodIdItem); 3212f376953b4c96542f200724727e4dac74dd27425jesusfreke@jesusfreke.com if (accessedMember != null) { 3222f376953b4c96542f200724727e4dac74dd27425jesusfreke@jesusfreke.com methodItems.add(new SyntheticAccessCommentMethodItem(accessedMember, currentCodeAddress)); 3232f376953b4c96542f200724727e4dac74dd27425jesusfreke@jesusfreke.com } 3242f376953b4c96542f200724727e4dac74dd27425jesusfreke@jesusfreke.com } 3252f376953b4c96542f200724727e4dac74dd27425jesusfreke@jesusfreke.com } 326754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver }*/ 3272f376953b4c96542f200724727e4dac74dd27425jesusfreke@jesusfreke.com 328754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver currentCodeAddress += instruction.getCodeUnits(); 329f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com } 330f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com } 331f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 332754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver //TODO: uncomment 333754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver /*private void addAnalyzedInstructionMethodItems(List<MethodItem> methodItems) { 3345967598d012839eb25d50d9fa63952ac802e05ddBen Gruver methodAnalyzer = new MethodAnalyzer(encodedMethod, baksmali.deodex, baksmali.inlineResolver); 335f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 336f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com methodAnalyzer.analyze(); 337f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 338f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com ValidationException validationException = methodAnalyzer.getValidationException(); 339f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com if (validationException != null) { 340f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com methodItems.add(new CommentMethodItem( 341f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com String.format("ValidationException: %s" ,validationException.getMessage()), 342f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com validationException.getCodeAddress(), Integer.MIN_VALUE)); 343f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com } else if (baksmali.verify) { 344f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com methodAnalyzer.verify(); 345f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 346f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com validationException = methodAnalyzer.getValidationException(); 347c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com if (validationException != null) { 3486eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com methodItems.add(new CommentMethodItem( 3491c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com String.format("ValidationException: %s" ,validationException.getMessage()), 350c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com validationException.getCodeAddress(), Integer.MIN_VALUE)); 351c9be5e13034da9827b5598a6257376164745b827JesusFreke@JesusFreke.com } 3527e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com } 353f7344d33d01953eee129f3cfa2b9655eb65bfe2fJesusFreke@JesusFreke.com 354ef24b31c9872b24f60c88bdae9b2d8c93eb36feeJesusFreke@JesusFreke.com List<AnalyzedInstruction> instructions = methodAnalyzer.getInstructions(); 355ad1085e32a17b342c2418c117c59d9c8305d71fcJesusFreke@JesusFreke.com 356b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com int currentCodeAddress = 0; 357ef24b31c9872b24f60c88bdae9b2d8c93eb36feeJesusFreke@JesusFreke.com for (int i=0; i<instructions.size(); i++) { 358ef24b31c9872b24f60c88bdae9b2d8c93eb36feeJesusFreke@JesusFreke.com AnalyzedInstruction instruction = instructions.get(i); 359ad1085e32a17b342c2418c117c59d9c8305d71fcJesusFreke@JesusFreke.com 360e01409c11f10de58a47df9bc02c6c715b75c6289JesusFreke@JesusFreke.com MethodItem methodItem = InstructionMethodItemFactory.makeInstructionFormatMethodItem(this, 361e01409c11f10de58a47df9bc02c6c715b75c6289JesusFreke@JesusFreke.com encodedMethod.codeItem, currentCodeAddress, instruction.getInstruction()); 362650725bbd3c5e10b9f29d3bcbab473b20a89d57bJesusFreke@JesusFreke.com 363e01409c11f10de58a47df9bc02c6c715b75c6289JesusFreke@JesusFreke.com methodItems.add(methodItem); 3640c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com 365e01409c11f10de58a47df9bc02c6c715b75c6289JesusFreke@JesusFreke.com if (instruction.getInstruction().getFormat() == Format.UnresolvedOdexInstruction) { 3666eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com methodItems.add(new CommentedOutMethodItem( 367e01409c11f10de58a47df9bc02c6c715b75c6289JesusFreke@JesusFreke.com InstructionMethodItemFactory.makeInstructionFormatMethodItem(this, 368e01409c11f10de58a47df9bc02c6c715b75c6289JesusFreke@JesusFreke.com encodedMethod.codeItem, currentCodeAddress, instruction.getOriginalInstruction()))); 3690c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com } 3707ab77bc90be62b0688c97d4476e3bd219eace0daJesusFreke@JesusFreke.com 371ef24b31c9872b24f60c88bdae9b2d8c93eb36feeJesusFreke@JesusFreke.com if (i != instructions.size() - 1) { 3726eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com methodItems.add(new BlankMethodItem(currentCodeAddress)); 373b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com } 374e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com 3752bdbf739bfd935877e463bc36df0e446b1dfb09fJesusFreke@JesusFreke.com if (baksmali.addCodeOffsets) { 3766eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com methodItems.add(new MethodItem(currentCodeAddress) { 3772bdbf739bfd935877e463bc36df0e446b1dfb09fJesusFreke@JesusFreke.com 3786eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com @Override 3796eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com public double getSortOrder() { 3806eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com return -1000; 3811c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com } 3821c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com 3836eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com @Override 3840b2f7d6a57e90424b3ee455c041aab3996c05f2cJesusFreke@JesusFreke.com public boolean writeTo(IndentingWriter writer) throws IOException { 3856eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com writer.write("#@"); 38674c14ffcca0ff4f8f3e66e66022894cd7b0b8540Ben Gruver writer.printUnsignedLongAsHex(codeAddress & 0xFFFFFFFF); 3876eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com return true; 3881c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com } 3896eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com }); 3906eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com } 3911c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com 3926eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com if (baksmali.registerInfo != 0 && !instruction.getInstruction().getFormat().variableSizeFormat) { 3936eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com methodItems.add( 3946eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com new PreInstructionRegisterInfoMethodItem(instruction, methodAnalyzer, currentCodeAddress)); 3951c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com 3966eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com methodItems.add( 3976eae34831fee1f116f3a453bdc5e143d68e05e03JesusFreke@JesusFreke.com new PostInstructionRegisterInfoMethodItem(instruction, methodAnalyzer, currentCodeAddress)); 3981c56c7e7507dc24ae1ed2f693c793d94df814c76JesusFreke@JesusFreke.com } 3997e24a9f010eeeff54f7ca0cb589a75cc251fabddJesusFreke@JesusFreke.com 4000c65e0f4f54ead8fd2832c954d516367b3556ae3JesusFreke@JesusFreke.com currentCodeAddress += instruction.getInstruction().getSize(currentCodeAddress); 401b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com } 402754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver }*/ 403e24e70f9ad584d45d2a2af911c1d056163f1bc74JesusFreke@JesusFreke.com 404b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com private void addTries(List<MethodItem> methodItems) { 405754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver List<? extends TryBlock> tryBlocks = methodImpl.getTryBlocks(); 406754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (tryBlocks.size() == 0) { 407b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com return; 408b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com } 409e24e70f9ad584d45d2a2af911c1d056163f1bc74JesusFreke@JesusFreke.com 410754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver List<? extends Instruction> instructions = methodImpl.getInstructions(); 411754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver int lastInstructionAddress = instructionOffsetMap.getInstructionCodeOffset(instructions.size() - 1); 412754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver int codeSize = lastInstructionAddress + instructions.get(instructions.size() - 1).getCodeUnits(); 413b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com 414754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver for (TryBlock tryBlock: tryBlocks) { 415754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver int startAddress = tryBlock.getStartCodeOffset(); 416754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver int endAddress = startAddress + tryBlock.getCodeUnitCount(); 417b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com 4185934004fe3c1e9617793aa120e88f5df1b651c14Ben Gruver if (startAddress >= codeSize) { 4195934004fe3c1e9617793aa120e88f5df1b651c14Ben Gruver throw new RuntimeException(String.format("Try start offset %d is past the end of the code block.", 4205934004fe3c1e9617793aa120e88f5df1b651c14Ben Gruver startAddress)); 4215934004fe3c1e9617793aa120e88f5df1b651c14Ben Gruver } 4225934004fe3c1e9617793aa120e88f5df1b651c14Ben Gruver // Note: not >=. endAddress == codeSize is valid, when the try covers the last instruction 4235934004fe3c1e9617793aa120e88f5df1b651c14Ben Gruver if (endAddress > codeSize) { 4245934004fe3c1e9617793aa120e88f5df1b651c14Ben Gruver throw new RuntimeException(String.format("Try end offset %d is past the end of the code block.", 4255934004fe3c1e9617793aa120e88f5df1b651c14Ben Gruver endAddress)); 4265934004fe3c1e9617793aa120e88f5df1b651c14Ben Gruver } 4275934004fe3c1e9617793aa120e88f5df1b651c14Ben Gruver 428b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com /** 429b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com * The end address points to the address immediately after the end of the last 430b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com * instruction that the try block covers. We want the .catch directive and end_try 431b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com * label to be associated with the last covered instruction, so we need to get 432b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com * the address for that instruction 433b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com */ 434b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com 435754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver int lastCoveredIndex = instructionOffsetMap.getInstructionIndexAtCodeOffset(endAddress - 1, false); 436754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver int lastCoveredAddress = instructionOffsetMap.getInstructionCodeOffset(lastCoveredIndex); 437ad1085e32a17b342c2418c117c59d9c8305d71fcJesusFreke@JesusFreke.com 438754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver for (ExceptionHandler handler: tryBlock.getExceptionHandlers()) { 439754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver int handlerOffset = handler.getHandlerCodeOffset(); 440754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver if (handlerOffset >= codeSize) { 441754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver throw new ExceptionWithContext( 442754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver "Exception handler offset %d is past the end of the code block.", handlerOffset); 4435934004fe3c1e9617793aa120e88f5df1b651c14Ben Gruver } 4445934004fe3c1e9617793aa120e88f5df1b651c14Ben Gruver 445b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com //use the address from the last covered instruction 4465934004fe3c1e9617793aa120e88f5df1b651c14Ben Gruver CatchMethodItem catchMethodItem = new CatchMethodItem(labelCache, lastCoveredAddress, 447754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver handler.getExceptionType(), startAddress, endAddress, handlerOffset); 448b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com methodItems.add(catchMethodItem); 449c65a8d8b5f2091a6bd835617262840a3f52c5c00JesusFreke@JesusFreke.com } 450c65a8d8b5f2091a6bd835617262840a3f52c5c00JesusFreke@JesusFreke.com } 451b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com } 452c65a8d8b5f2091a6bd835617262840a3f52c5c00JesusFreke@JesusFreke.com 453b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com private void addDebugInfo(final List<MethodItem> methodItems) { 454754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver for (DebugItem debugItem: methodImpl.getDebugItems()) { 455754b3c4dc009b7a02e39001560c3f0fd6a7cc2c0Ben Gruver methodItems.add(DebugMethodItem.build(registerFormatter, debugItem)); 456c65a8d8b5f2091a6bd835617262840a3f52c5c00JesusFreke@JesusFreke.com } 457b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com } 458e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com 459b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com private void setLabelSequentialNumbers() { 460b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com HashMap<String, Integer> nextLabelSequenceByType = new HashMap<String, Integer>(); 461b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com ArrayList<LabelMethodItem> sortedLabels = new ArrayList<LabelMethodItem>(labelCache.getLabels()); 462e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com 463b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com //sort the labels by their location in the method 464b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com Collections.sort(sortedLabels); 465e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com 466b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com for (LabelMethodItem labelMethodItem: sortedLabels) { 467b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com Integer labelSequence = nextLabelSequenceByType.get(labelMethodItem.getLabelPrefix()); 468b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com if (labelSequence == null) { 469b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com labelSequence = 0; 470e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com } 471b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com labelMethodItem.setLabelSequence(labelSequence); 472b2e1e2067d5179b0ec38c76a5191909f5a7dc1ccJesusFreke@JesusFreke.com nextLabelSequenceByType.put(labelMethodItem.getLabelPrefix(), labelSequence + 1); 473e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com } 474e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com } 475e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com 476e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com public static class LabelCache { 477e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com protected HashMap<LabelMethodItem, LabelMethodItem> labels = new HashMap<LabelMethodItem, LabelMethodItem>(); 478e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com 479e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com public LabelCache() { 480e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com } 481e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com 482e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com public LabelMethodItem internLabel(LabelMethodItem labelMethodItem) { 483e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com LabelMethodItem internedLabelMethodItem = labels.get(labelMethodItem); 484e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com if (internedLabelMethodItem != null) { 485e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com return internedLabelMethodItem; 486e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com } 487e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com labels.put(labelMethodItem, labelMethodItem); 488e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com return labelMethodItem; 489e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com } 490e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com 491e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com 492e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com public Collection<LabelMethodItem> getLabels() { 493e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com return labels.values(); 494e2684fa2191e04f27faba763f2bcc19593513b25JesusFreke@JesusFreke.com } 49536836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com } 49636836121d7ecf72050d3ef065b7ab5fa86548319JesusFreke@JesusFreke.com} 497