mirror of
https://github.com/revanced/smali.git
synced 2025-05-23 18:16:23 +02:00
Add support for specifying a custom inline method table to use while deodexing
This commit is contained in:
parent
e00d96c438
commit
5967598d01
@ -373,7 +373,7 @@ public class MethodDefinition {
|
||||
}
|
||||
|
||||
private void addAnalyzedInstructionMethodItems(List<MethodItem> methodItems) {
|
||||
methodAnalyzer = new MethodAnalyzer(encodedMethod, baksmali.deodex);
|
||||
methodAnalyzer = new MethodAnalyzer(encodedMethod, baksmali.deodex, baksmali.inlineResolver);
|
||||
|
||||
methodAnalyzer.analyze();
|
||||
|
||||
|
@ -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);
|
||||
|
@ -121,7 +121,7 @@ public class main {
|
||||
StringBuffer extraBootClassPathEntries = new StringBuffer();
|
||||
List<String> bootClassPathDirs = new ArrayList<String>();
|
||||
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);
|
||||
|
@ -593,7 +593,12 @@ public class ClassPath {
|
||||
private final int classDepth;
|
||||
|
||||
private final String[] vtable;
|
||||
private final HashMap<String, Integer> 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<String, Integer> methodLookup;
|
||||
|
||||
private final SparseArray<FieldDef> 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<String, Integer>((int)Math.ceil(vtable.length / .7f), .75f);
|
||||
|
||||
int directMethodCount = 0;
|
||||
if (classInfo.directMethods != null) {
|
||||
directMethodCount = classInfo.directMethods.length;
|
||||
}
|
||||
methodLookup = new HashMap<String, Integer>((int)Math.ceil(((vtable.length + directMethodCount)/ .7f)), .75f);
|
||||
for (int i=0; i<vtable.length; i++) {
|
||||
virtualMethodLookup.put(vtable[i], i);
|
||||
methodLookup.put(vtable[i], i);
|
||||
}
|
||||
if (directMethodCount > 0) {
|
||||
for (int i=0; i<classInfo.directMethods.length; i++) {
|
||||
if (classInfo.staticMethods[i]) {
|
||||
methodLookup.put(classInfo.directMethods[i], StaticMethod);
|
||||
} else {
|
||||
methodLookup.put(classInfo.directMethods[i], DirectMethod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
instanceFields = loadFields(classInfo);
|
||||
@ -745,7 +766,28 @@ public class ClassPath {
|
||||
}
|
||||
|
||||
public boolean hasVirtualMethod(String method) {
|
||||
return virtualMethodLookup.containsKey(method);
|
||||
Integer val = methodLookup.get(method);
|
||||
if (val == null || val < 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public int getMethodType(String method) {
|
||||
Integer val = methodLookup.get(method);
|
||||
if (val == null) {
|
||||
return -1;
|
||||
}
|
||||
if (val >= 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<encodedMethods.length; i++) {
|
||||
EncodedMethod encodedMethod = encodedMethods[i];
|
||||
|
||||
if ((encodedMethod.accessFlags & AccessFlags.STATIC.getValue()) != 0) {
|
||||
staticMethods[i] = true;
|
||||
}
|
||||
directMethods[i] = encodedMethods[i].method.getVirtualMethodString();
|
||||
}
|
||||
_staticMethods[0] = staticMethods;
|
||||
return directMethods;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String[] loadVirtualMethods(ClassDataItem classDataItem) {
|
||||
EncodedMethod[] encodedMethods = classDataItem.getVirtualMethods();
|
||||
if (encodedMethods != null && encodedMethods.length > 0) {
|
||||
|
@ -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<String> lines = new ArrayList<String>();
|
||||
|
||||
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; i++) {
|
||||
inlineMethods[i] = parseAndResolveInlineMethod(lines.get(i));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DeodexUtil.InlineMethod resolveExecuteInline(AnalyzedInstruction analyzedInstruction) {
|
||||
assert analyzedInstruction.instruction instanceof OdexedInvokeInline;
|
||||
|
||||
OdexedInvokeInline instruction = (OdexedInvokeInline)analyzedInstruction.instruction;
|
||||
int methodIndex = instruction.getInlineIndex();
|
||||
|
||||
if (methodIndex < 0 || methodIndex >= 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);
|
||||
}
|
||||
}
|
@ -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() {
|
||||
|
@ -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")
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -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()));
|
||||
|
Loading…
x
Reference in New Issue
Block a user