diff --git a/baksmali/src/main/java/org/jf/baksmali/Adaptors/MethodDefinition.java b/baksmali/src/main/java/org/jf/baksmali/Adaptors/MethodDefinition.java index 70071b65..88c98bf7 100644 --- a/baksmali/src/main/java/org/jf/baksmali/Adaptors/MethodDefinition.java +++ b/baksmali/src/main/java/org/jf/baksmali/Adaptors/MethodDefinition.java @@ -373,7 +373,7 @@ public class MethodDefinition { } private void addAnalyzedInstructionMethodItems(List methodItems) { - methodAnalyzer = new MethodAnalyzer(encodedMethod, baksmali.deodex); + methodAnalyzer = new MethodAnalyzer(encodedMethod, baksmali.deodex, baksmali.inlineResolver); methodAnalyzer.analyze(); diff --git a/baksmali/src/main/java/org/jf/baksmali/baksmali.java b/baksmali/src/main/java/org/jf/baksmali/baksmali.java index f746ed90..9db30317 100644 --- a/baksmali/src/main/java/org/jf/baksmali/baksmali.java +++ b/baksmali/src/main/java/org/jf/baksmali/baksmali.java @@ -30,8 +30,7 @@ package org.jf.baksmali; import org.jf.baksmali.Adaptors.ClassDefinition; import org.jf.dexlib.ClassDefItem; -import org.jf.dexlib.Code.Analysis.ClassPath; -import org.jf.dexlib.Code.Analysis.SyntheticAccessorResolver; +import org.jf.dexlib.Code.Analysis.*; import org.jf.dexlib.DexFile; import org.jf.util.ClassFileNameHandler; import org.jf.util.IndentingWriter; @@ -52,6 +51,7 @@ public class baksmali { public static boolean noAccessorComments = false; public static boolean deodex = false; public static boolean verify = false; + public static InlineMethodResolver inlineResolver = null; public static int registerInfo = 0; public static String bootClassPath; @@ -62,7 +62,7 @@ public class baksmali { boolean noParameterRegisters, boolean useLocalsDirective, boolean useSequentialLabels, boolean outputDebugInfo, boolean addCodeOffsets, boolean noAccessorComments, int registerInfo, boolean verify, - boolean ignoreErrors) + boolean ignoreErrors, String inlineTable) { baksmali.noParameterRegisters = noParameterRegisters; baksmali.useLocalsDirective = useLocalsDirective; @@ -111,6 +111,10 @@ public class baksmali { ClassPath.InitializeClassPath(classPathDirs, bootClassPathArray, extraBootClassPathArray, dexFilePath, dexFile, classPathErrorHandler); } + + if (inlineTable != null) { + inlineResolver = new CustomInlineMethodResolver(inlineTable); + } } catch (Exception ex) { System.err.println("\n\nError occured while loading boot class path files. Aborting."); ex.printStackTrace(System.err); diff --git a/baksmali/src/main/java/org/jf/baksmali/main.java b/baksmali/src/main/java/org/jf/baksmali/main.java index 510e6505..43350a34 100644 --- a/baksmali/src/main/java/org/jf/baksmali/main.java +++ b/baksmali/src/main/java/org/jf/baksmali/main.java @@ -121,7 +121,7 @@ public class main { StringBuffer extraBootClassPathEntries = new StringBuffer(); List bootClassPathDirs = new ArrayList(); bootClassPathDirs.add("."); - + String inlineTable = null; String[] remainingArgs = commandLine.getArgs(); @@ -237,6 +237,9 @@ public class main { case 'V': verify = true; break; + case 'T': + inlineTable = commandLine.getOptionValue("T"); + break; default: assert false; } @@ -290,7 +293,7 @@ public class main { baksmali.disassembleDexFile(dexFileFile.getPath(), dexFile, deodex, outputDirectory, bootClassPathDirsArray, bootClassPath, extraBootClassPathEntries.toString(), noParameterRegisters, useLocalsDirective, useSequentialLabels, outputDebugInfo, addCodeOffsets, - noAccessorComments, registerInfo, verify, ignoreErrors); + noAccessorComments, registerInfo, verify, ignoreErrors, inlineTable); } if ((doDump || write) && !dexFile.isOdex()) { @@ -443,6 +446,7 @@ public class main { " behavior is to stop disassembling and exit once an error is encountered") .create("I"); + Option noDisassemblyOption = OptionBuilder.withLongOpt("no-disassembly") .withDescription("suppresses the output of the disassembly") .create("N"); @@ -466,6 +470,12 @@ public class main { .withDescription("perform bytecode verification") .create("V"); + Option inlineTableOption = OptionBuilder.withLongOpt("inline-table") + .withDescription("specify a file containing a custom inline method table to use for deodexing") + .hasArg() + .withArgName("FILE") + .create("T"); + basicOptions.addOption(versionOption); basicOptions.addOption(helpOption); basicOptions.addOption(outputDirOption); @@ -488,7 +498,7 @@ public class main { debugOptions.addOption(sortOption); debugOptions.addOption(fixSignedRegisterOption); debugOptions.addOption(verifyDexOption); - + debugOptions.addOption(inlineTableOption); for (Object option: basicOptions.getOptions()) { options.addOption((Option)option); diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/ClassPath.java b/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/ClassPath.java index f3204624..d32be0f3 100644 --- a/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/ClassPath.java +++ b/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/ClassPath.java @@ -593,7 +593,12 @@ public class ClassPath { private final int classDepth; private final String[] vtable; - private final HashMap virtualMethodLookup; + + //this maps a method name of the form method(III)Ljava/lang/String; to an integer + //If the value is non-negative, it is a vtable index + //If it is -1, it is a non-static direct method, + //If it is -2, it is a static method + private final HashMap methodLookup; private final SparseArray instanceFields; @@ -601,6 +606,8 @@ public class ClassPath { public final static int PrimitiveClassDef = 1; public final static int UnresolvedClassDef = 2; + private final static int DirectMethod = -1; + private final static int StaticMethod = -2; /** * The following fields are used only during the initial loading of classes, and are set to null afterwards @@ -629,7 +636,7 @@ public class ClassPath { isInterface = false; vtable = superclass.vtable; - virtualMethodLookup = superclass.virtualMethodLookup; + methodLookup = superclass.methodLookup; instanceFields = superclass.instanceFields; classDepth = 1; //1 off from java.lang.Object @@ -645,7 +652,7 @@ public class ClassPath { implementedInterfaces = null; isInterface = false; vtable = null; - virtualMethodLookup = null; + methodLookup = null; instanceFields = null; classDepth = 0; //TODO: maybe use -1 to indicate not applicable? @@ -659,7 +666,7 @@ public class ClassPath { isInterface = false; vtable = superclass.vtable; - virtualMethodLookup = superclass.virtualMethodLookup; + methodLookup = superclass.methodLookup; instanceFields = superclass.instanceFields; classDepth = 1; //1 off from java.lang.Object @@ -686,9 +693,23 @@ public class ClassPath { interfaceTable = loadInterfaceTable(classInfo); virtualMethods = classInfo.virtualMethods; vtable = loadVtable(classInfo); - virtualMethodLookup = new HashMap((int)Math.ceil(vtable.length / .7f), .75f); + + int directMethodCount = 0; + if (classInfo.directMethods != null) { + directMethodCount = classInfo.directMethods.length; + } + methodLookup = new HashMap((int)Math.ceil(((vtable.length + directMethodCount)/ .7f)), .75f); for (int i=0; i 0) { + for (int i=0; i= 0) { + return DeodexUtil.Virtual; + } + if (val == DirectMethod) { + return DeodexUtil.Direct; + } + if (val == StaticMethod) { + return DeodexUtil.Static; + } + throw new RuntimeException("Unexpected method type"); } public FieldDef getInstanceField(int fieldOffset) { @@ -1141,6 +1183,8 @@ public class ClassPath { public final boolean isInterface; public final String superclassType; public final String[] interfaces; + public final boolean[] staticMethods; + public final String[] directMethods; public final String[] virtualMethods; public final String[][] instanceFields; @@ -1162,9 +1206,14 @@ public class ClassPath { ClassDataItem classDataItem = classDefItem.getClassData(); if (classDataItem != null) { + boolean[][] _staticMethods = new boolean[1][]; + directMethods = loadDirectMethods(classDataItem, _staticMethods); + staticMethods = _staticMethods[0]; virtualMethods = loadVirtualMethods(classDataItem); instanceFields = loadInstanceFields(classDataItem); } else { + staticMethods = null; + directMethods = null; virtualMethods = null; instanceFields = null; } @@ -1185,6 +1234,26 @@ public class ClassPath { return null; } + private String[] loadDirectMethods(ClassDataItem classDataItem, boolean[][] _staticMethods) { + EncodedMethod[] encodedMethods = classDataItem.getDirectMethods(); + + if (encodedMethods != null && encodedMethods.length > 0) { + boolean[] staticMethods = new boolean[encodedMethods.length]; + String[] directMethods = new String[encodedMethods.length]; + for (int i=0; i 0) { diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/CustomInlineMethodResolver.java b/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/CustomInlineMethodResolver.java new file mode 100644 index 00000000..9c1653d2 --- /dev/null +++ b/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/CustomInlineMethodResolver.java @@ -0,0 +1,115 @@ +/* + * Copyright 2011, Google Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.jf.dexlib.Code.Analysis; + +import org.jf.dexlib.Code.OdexedInvokeInline; +import org.jf.dexlib.Code.OdexedInvokeVirtual; + +import java.io.*; +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class CustomInlineMethodResolver extends InlineMethodResolver { + private DeodexUtil.InlineMethod[] inlineMethods; + + public CustomInlineMethodResolver(String inlineTable) { + FileReader fr = null; + try { + fr = new FileReader(inlineTable); + } catch (FileNotFoundException ex) { + throw new RuntimeException("Could not find inline table file: " + inlineTable); + } + + List lines = new ArrayList(); + + BufferedReader br = new BufferedReader(fr); + + try { + String line = br.readLine(); + + while (line != null) { + if (line.length() > 0) { + lines.add(line); + } + + line = br.readLine(); + } + } catch (IOException ex) { + throw new RuntimeException("Error while reading file: " + inlineTable, ex); + } + + inlineMethods = new DeodexUtil.InlineMethod[lines.size()]; + + for (int i=0; i= inlineMethods.length) { + throw new RuntimeException("Invalid method index: " + methodIndex); + } + return inlineMethods[methodIndex]; + } + + private static final Pattern longMethodPattern = Pattern.compile("(L[^;]+;)->([^(]+)\\(([^)]*)\\)(.+)"); + + private DeodexUtil.InlineMethod parseAndResolveInlineMethod(String inlineMethod) { + Matcher m = longMethodPattern.matcher(inlineMethod); + if (!m.matches()) { + assert false; + throw new RuntimeException("Invalid method descriptor: " + inlineMethod); + } + + String className = m.group(1); + String methodName = m.group(2); + String methodParams = m.group(3); + String methodRet = m.group(4); + + ClassPath.ClassDef classDef = ClassPath.getClassDef(className, false); + int methodType = classDef.getMethodType(String.format("%s(%s)%s", methodName, methodParams, methodRet)); + + if (methodType == -1) { + throw new RuntimeException("Cannot resolve inline method: " + inlineMethod); + } + + return new DeodexUtil.InlineMethod(methodType, className, methodName, methodParams, methodRet); + } +} diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/DeodexUtil.java b/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/DeodexUtil.java index 8d41434d..4d351835 100644 --- a/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/DeodexUtil.java +++ b/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/DeodexUtil.java @@ -55,6 +55,11 @@ public class DeodexUtil { inlineMethodResolver = InlineMethodResolver.createInlineMethodResolver(this, odexHeader.version); } + public DeodexUtil(DexFile dexFile, InlineMethodResolver inlineMethodResolver) { + this.dexFile = dexFile; + this.inlineMethodResolver = inlineMethodResolver; + } + public InlineMethod lookupInlineMethod(AnalyzedInstruction instruction) { return inlineMethodResolver.resolveExecuteInline(instruction); } @@ -246,7 +251,7 @@ public class DeodexUtil { return null; } - public class InlineMethod { + public static class InlineMethod { public final int methodType; public final String classType; public final String methodName; @@ -264,17 +269,17 @@ public class DeodexUtil { this.returnType = returnType; } - public MethodIdItem getMethodIdItem() { + public MethodIdItem getMethodIdItem(DeodexUtil deodexUtil) { if (methodIdItem == null) { - loadMethod(); + loadMethod(deodexUtil); } return methodIdItem; } - private void loadMethod() { + private void loadMethod(DeodexUtil deodexUtil) { ClassPath.ClassDef classDef = ClassPath.getClassDef(classType); - this.methodIdItem = parseAndResolveMethod(classDef, methodName, parameters, returnType); + this.methodIdItem = deodexUtil.parseAndResolveMethod(classDef, methodName, parameters, returnType); } public String getMethodString() { diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/InlineMethodResolver.java b/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/InlineMethodResolver.java index cd0f75c3..73fdde67 100644 --- a/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/InlineMethodResolver.java +++ b/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/InlineMethodResolver.java @@ -35,7 +35,7 @@ import static org.jf.dexlib.Code.Analysis.DeodexUtil.Static; import static org.jf.dexlib.Code.Analysis.DeodexUtil.Virtual; import static org.jf.dexlib.Code.Analysis.DeodexUtil.Direct; -abstract class InlineMethodResolver { +public abstract class InlineMethodResolver { public static InlineMethodResolver createInlineMethodResolver(DeodexUtil deodexUtil, int odexVersion) { if (odexVersion == 35) { return new InlineMethodResolver_version35(deodexUtil); @@ -46,7 +46,7 @@ abstract class InlineMethodResolver { } } - private InlineMethodResolver() { + protected InlineMethodResolver() { } public abstract DeodexUtil.InlineMethod resolveExecuteInline(AnalyzedInstruction instruction); @@ -57,20 +57,20 @@ abstract class InlineMethodResolver { public InlineMethodResolver_version35(DeodexUtil deodexUtil) { inlineMethods = new DeodexUtil.InlineMethod[] { - deodexUtil.new InlineMethod(Static, "Lorg/apache/harmony/dalvik/NativeTestTarget;", "emptyInlineMethod", "", "V"), - deodexUtil.new InlineMethod(Virtual, "Ljava/lang/String;", "charAt", "I", "C"), - deodexUtil.new InlineMethod(Virtual, "Ljava/lang/String;", "compareTo", "Ljava/lang/String;", "I"), - deodexUtil.new InlineMethod(Virtual, "Ljava/lang/String;", "equals", "Ljava/lang/Object;", "Z"), - deodexUtil.new InlineMethod(Virtual, "Ljava/lang/String;", "length", "", "I"), - deodexUtil.new InlineMethod(Static, "Ljava/lang/Math;", "abs", "I", "I"), - deodexUtil.new InlineMethod(Static, "Ljava/lang/Math;", "abs", "J", "J"), - deodexUtil.new InlineMethod(Static, "Ljava/lang/Math;", "abs", "F", "F"), - deodexUtil.new InlineMethod(Static, "Ljava/lang/Math;", "abs", "D", "D"), - deodexUtil.new InlineMethod(Static, "Ljava/lang/Math;", "min", "II", "I"), - deodexUtil.new InlineMethod(Static, "Ljava/lang/Math;", "max", "II", "I"), - deodexUtil.new InlineMethod(Static, "Ljava/lang/Math;", "sqrt", "D", "D"), - deodexUtil.new InlineMethod(Static, "Ljava/lang/Math;", "cos", "D", "D"), - deodexUtil.new InlineMethod(Static, "Ljava/lang/Math;", "sin", "D", "D") + new DeodexUtil.InlineMethod(Static, "Lorg/apache/harmony/dalvik/NativeTestTarget;", "emptyInlineMethod", "", "V"), + new DeodexUtil.InlineMethod(Virtual, "Ljava/lang/String;", "charAt", "I", "C"), + new DeodexUtil.InlineMethod(Virtual, "Ljava/lang/String;", "compareTo", "Ljava/lang/String;", "I"), + new DeodexUtil.InlineMethod(Virtual, "Ljava/lang/String;", "equals", "Ljava/lang/Object;", "Z"), + new DeodexUtil.InlineMethod(Virtual, "Ljava/lang/String;", "length", "", "I"), + new DeodexUtil.InlineMethod(Static, "Ljava/lang/Math;", "abs", "I", "I"), + new DeodexUtil.InlineMethod(Static, "Ljava/lang/Math;", "abs", "J", "J"), + new DeodexUtil.InlineMethod(Static, "Ljava/lang/Math;", "abs", "F", "F"), + new DeodexUtil.InlineMethod(Static, "Ljava/lang/Math;", "abs", "D", "D"), + new DeodexUtil.InlineMethod(Static, "Ljava/lang/Math;", "min", "II", "I"), + new DeodexUtil.InlineMethod(Static, "Ljava/lang/Math;", "max", "II", "I"), + new DeodexUtil.InlineMethod(Static, "Ljava/lang/Math;", "sqrt", "D", "D"), + new DeodexUtil.InlineMethod(Static, "Ljava/lang/Math;", "cos", "D", "D"), + new DeodexUtil.InlineMethod(Static, "Ljava/lang/Math;", "sin", "D", "D") }; } @@ -102,40 +102,40 @@ abstract class InlineMethodResolver { //passed to distinguish between them. //froyo - indexOfIMethod = deodexUtil.new InlineMethod(Virtual, "Ljava/lang/String;", "indexOf", "I", "I"); - indexOfIIMethod = deodexUtil.new InlineMethod(Virtual, "Ljava/lang/String;", "indexOf", "II", "I"); + indexOfIMethod = new DeodexUtil.InlineMethod(Virtual, "Ljava/lang/String;", "indexOf", "I", "I"); + indexOfIIMethod = new DeodexUtil.InlineMethod(Virtual, "Ljava/lang/String;", "indexOf", "II", "I"); //gingerbread - fastIndexOfMethod = deodexUtil.new InlineMethod(Direct, "Ljava/lang/String;", "fastIndexOf", "II", "I"); - isEmptyMethod = deodexUtil.new InlineMethod(Virtual, "Ljava/lang/String;", "isEmpty", "", "Z"); + fastIndexOfMethod = new DeodexUtil.InlineMethod(Direct, "Ljava/lang/String;", "fastIndexOf", "II", "I"); + isEmptyMethod = new DeodexUtil.InlineMethod(Virtual, "Ljava/lang/String;", "isEmpty", "", "Z"); inlineMethods = new DeodexUtil.InlineMethod[] { - deodexUtil.new InlineMethod(Static, "Lorg/apache/harmony/dalvik/NativeTestTarget;", "emptyInlineMethod", "", "V"), - deodexUtil.new InlineMethod(Virtual, "Ljava/lang/String;", "charAt", "I", "C"), - deodexUtil.new InlineMethod(Virtual, "Ljava/lang/String;", "compareTo", "Ljava/lang/String;", "I"), - deodexUtil.new InlineMethod(Virtual, "Ljava/lang/String;", "equals", "Ljava/lang/Object;", "Z"), + new DeodexUtil.InlineMethod(Static, "Lorg/apache/harmony/dalvik/NativeTestTarget;", "emptyInlineMethod", "", "V"), + new DeodexUtil.InlineMethod(Virtual, "Ljava/lang/String;", "charAt", "I", "C"), + new DeodexUtil.InlineMethod(Virtual, "Ljava/lang/String;", "compareTo", "Ljava/lang/String;", "I"), + new DeodexUtil.InlineMethod(Virtual, "Ljava/lang/String;", "equals", "Ljava/lang/Object;", "Z"), //froyo: deodexUtil.new InlineMethod(Virtual, "Ljava/lang/String;", "indexOf", "I", "I"), //gingerbread: deodexUtil.new InlineMethod(Virtual, "Ljava/lang/String;", "fastIndexOf", "II", "I"), null, //froyo: deodexUtil.new InlineMethod(Virtual, "Ljava/lang/String;", "indexOf", "II", "I"), //gingerbread: deodexUtil.new InlineMethod(Virtual, "Ljava/lang/String;", "isEmpty", "", "Z"), null, - deodexUtil.new InlineMethod(Virtual, "Ljava/lang/String;", "length", "", "I"), - deodexUtil.new InlineMethod(Static, "Ljava/lang/Math;", "abs", "I", "I"), - deodexUtil.new InlineMethod(Static, "Ljava/lang/Math;", "abs", "J", "J"), - deodexUtil.new InlineMethod(Static, "Ljava/lang/Math;", "abs", "F", "F"), - deodexUtil.new InlineMethod(Static, "Ljava/lang/Math;", "abs", "D", "D"), - deodexUtil.new InlineMethod(Static, "Ljava/lang/Math;", "min", "II", "I"), - deodexUtil.new InlineMethod(Static, "Ljava/lang/Math;", "max", "II", "I"), - deodexUtil.new InlineMethod(Static, "Ljava/lang/Math;", "sqrt", "D", "D"), - deodexUtil.new InlineMethod(Static, "Ljava/lang/Math;", "cos", "D", "D"), - deodexUtil.new InlineMethod(Static, "Ljava/lang/Math;", "sin", "D", "D"), - deodexUtil.new InlineMethod(Static, "Ljava/lang/Float;", "floatToIntBits", "F", "I"), - deodexUtil.new InlineMethod(Static, "Ljava/lang/Float;", "floatToRawIntBits", "F", "I"), - deodexUtil.new InlineMethod(Static, "Ljava/lang/Float;", "intBitsToFloat", "I", "F"), - deodexUtil.new InlineMethod(Static, "Ljava/lang/Double;", "doubleToLongBits", "D", "J"), - deodexUtil.new InlineMethod(Static, "Ljava/lang/Double;", "doubleToRawLongBits", "D", "J"), - deodexUtil.new InlineMethod(Static, "Ljava/lang/Double;", "longBitsToDouble", "J", "D") + new DeodexUtil.InlineMethod(Virtual, "Ljava/lang/String;", "length", "", "I"), + new DeodexUtil.InlineMethod(Static, "Ljava/lang/Math;", "abs", "I", "I"), + new DeodexUtil.InlineMethod(Static, "Ljava/lang/Math;", "abs", "J", "J"), + new DeodexUtil.InlineMethod(Static, "Ljava/lang/Math;", "abs", "F", "F"), + new DeodexUtil.InlineMethod(Static, "Ljava/lang/Math;", "abs", "D", "D"), + new DeodexUtil.InlineMethod(Static, "Ljava/lang/Math;", "min", "II", "I"), + new DeodexUtil.InlineMethod(Static, "Ljava/lang/Math;", "max", "II", "I"), + new DeodexUtil.InlineMethod(Static, "Ljava/lang/Math;", "sqrt", "D", "D"), + new DeodexUtil.InlineMethod(Static, "Ljava/lang/Math;", "cos", "D", "D"), + new DeodexUtil.InlineMethod(Static, "Ljava/lang/Math;", "sin", "D", "D"), + new DeodexUtil.InlineMethod(Static, "Ljava/lang/Float;", "floatToIntBits", "F", "I"), + new DeodexUtil.InlineMethod(Static, "Ljava/lang/Float;", "floatToRawIntBits", "F", "I"), + new DeodexUtil.InlineMethod(Static, "Ljava/lang/Float;", "intBitsToFloat", "I", "F"), + new DeodexUtil.InlineMethod(Static, "Ljava/lang/Double;", "doubleToLongBits", "D", "J"), + new DeodexUtil.InlineMethod(Static, "Ljava/lang/Double;", "doubleToRawLongBits", "D", "J"), + new DeodexUtil.InlineMethod(Static, "Ljava/lang/Double;", "longBitsToDouble", "J", "D") }; } diff --git a/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/MethodAnalyzer.java b/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/MethodAnalyzer.java index 0e0f1942..d9ebe139 100644 --- a/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/MethodAnalyzer.java +++ b/dexlib/src/main/java/org/jf/dexlib/Code/Analysis/MethodAnalyzer.java @@ -71,7 +71,8 @@ public class MethodAnalyzer { //instruction, etc. private AnalyzedInstruction startOfMethod; - public MethodAnalyzer(ClassDataItem.EncodedMethod encodedMethod, boolean deodex) { + public MethodAnalyzer(ClassDataItem.EncodedMethod encodedMethod, boolean deodex, + InlineMethodResolver inlineResolver) { if (encodedMethod == null) { throw new IllegalArgumentException("encodedMethod cannot be null"); } @@ -81,7 +82,11 @@ public class MethodAnalyzer { this.encodedMethod = encodedMethod; if (deodex) { - this.deodexUtil = new DeodexUtil(encodedMethod.method.getDexFile()); + if (inlineResolver != null) { + this.deodexUtil = new DeodexUtil(encodedMethod.method.getDexFile(), inlineResolver); + } else { + this.deodexUtil = new DeodexUtil(encodedMethod.method.getDexFile()); + } } else { this.deodexUtil = null; } @@ -3386,7 +3391,7 @@ public class MethodAnalyzer { Instruction35mi instruction = (Instruction35mi)analyzedInstruction.instruction; DeodexUtil.InlineMethod inlineMethod = deodexUtil.lookupInlineMethod(analyzedInstruction); - MethodIdItem inlineMethodIdItem = inlineMethod.getMethodIdItem(); + MethodIdItem inlineMethodIdItem = inlineMethod.getMethodIdItem(deodexUtil); if (inlineMethodIdItem == null) { throw new ValidationException(String.format("Cannot load inline method with index %d", instruction.getInlineIndex())); @@ -3424,7 +3429,7 @@ public class MethodAnalyzer { Instruction3rmi instruction = (Instruction3rmi)analyzedInstruction.instruction; DeodexUtil.InlineMethod inlineMethod = deodexUtil.lookupInlineMethod(analyzedInstruction); - MethodIdItem inlineMethodIdItem = inlineMethod.getMethodIdItem(); + MethodIdItem inlineMethodIdItem = inlineMethod.getMethodIdItem(deodexUtil); if (inlineMethodIdItem == null) { throw new ValidationException(String.format("Cannot load inline method with index %d", instruction.getInlineIndex()));