mirror of
https://github.com/revanced/smali.git
synced 2025-05-28 20:00:13 +02:00
Re-implement SyntheticAccessorResolver
This commit is contained in:
parent
db389aa3a1
commit
2b8845bb24
1
.gitignore
vendored
1
.gitignore
vendored
@ -2,5 +2,6 @@
|
||||
/baksmali/build
|
||||
/dexlib/build
|
||||
/dexlib2/build
|
||||
/dexlib2/accessorTestGenerator/build
|
||||
/smali/build
|
||||
/util/build
|
||||
|
@ -33,12 +33,16 @@ import org.jf.baksmali.Adaptors.Debug.DebugMethodItem;
|
||||
import org.jf.baksmali.Adaptors.Format.InstructionMethodItemFactory;
|
||||
import org.jf.dexlib2.AccessFlags;
|
||||
import org.jf.dexlib2.Opcode;
|
||||
import org.jf.dexlib2.ReferenceType;
|
||||
import org.jf.dexlib2.iface.*;
|
||||
import org.jf.dexlib2.iface.debug.DebugItem;
|
||||
import org.jf.dexlib2.iface.instruction.Instruction;
|
||||
import org.jf.dexlib2.iface.instruction.OffsetInstruction;
|
||||
import org.jf.dexlib2.iface.instruction.ReferenceInstruction;
|
||||
import org.jf.dexlib2.iface.reference.MethodReference;
|
||||
import org.jf.dexlib2.util.InstructionOffsetMap;
|
||||
import org.jf.dexlib2.util.MethodUtil;
|
||||
import org.jf.dexlib2.util.SyntheticAccessorResolver;
|
||||
import org.jf.dexlib2.util.TypeUtils;
|
||||
import org.jf.util.IndentingWriter;
|
||||
import org.jf.baksmali.baksmali;
|
||||
@ -314,22 +318,21 @@ public class MethodDefinition {
|
||||
});
|
||||
}
|
||||
|
||||
//TODO: uncomment
|
||||
/*if (!baksmali.noAccessorComments && (instruction instanceof InstructionWithReference)) {
|
||||
if (!baksmali.noAccessorComments && (instruction instanceof ReferenceInstruction)) {
|
||||
Opcode opcode = instruction.getOpcode();
|
||||
if (opcode == Opcode.INVOKE_STATIC || opcode == Opcode.INVOKE_STATIC_RANGE) {
|
||||
MethodIdItem methodIdItem =
|
||||
(MethodIdItem)((InstructionWithReference) instruction).getReferencedItem();
|
||||
|
||||
if (SyntheticAccessorResolver.looksLikeSyntheticAccessor(methodIdItem)) {
|
||||
if (opcode.referenceType == ReferenceType.METHOD) {
|
||||
MethodReference methodReference = (MethodReference)((ReferenceInstruction)instruction).getReference();
|
||||
|
||||
if (SyntheticAccessorResolver.looksLikeSyntheticAccessor(methodReference.getName())) {
|
||||
SyntheticAccessorResolver.AccessedMember accessedMember =
|
||||
baksmali.syntheticAccessorResolver.getAccessedMember(methodIdItem);
|
||||
baksmali.syntheticAccessorResolver.getAccessedMember(methodReference);
|
||||
if (accessedMember != null) {
|
||||
methodItems.add(new SyntheticAccessCommentMethodItem(accessedMember, currentCodeAddress));
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
currentCodeAddress += instruction.getCodeUnits();
|
||||
}
|
||||
|
@ -28,17 +28,17 @@
|
||||
|
||||
package org.jf.baksmali.Adaptors;
|
||||
|
||||
import org.jf.dexlib.Code.Analysis.SyntheticAccessorResolver;
|
||||
import static org.jf.dexlib.Code.Analysis.SyntheticAccessorResolver.AccessedMember;
|
||||
import org.jf.dexlib2.ReferenceType;
|
||||
import org.jf.dexlib2.util.SyntheticAccessorResolver;
|
||||
import org.jf.util.ExceptionWithContext;
|
||||
import org.jf.util.IndentingWriter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
//TODO: uncomment
|
||||
/*public class SyntheticAccessCommentMethodItem extends MethodItem {
|
||||
private final AccessedMember accessedMember;
|
||||
public class SyntheticAccessCommentMethodItem extends MethodItem {
|
||||
private final SyntheticAccessorResolver.AccessedMember accessedMember;
|
||||
|
||||
public SyntheticAccessCommentMethodItem(AccessedMember accessedMember, int codeAddress) {
|
||||
public SyntheticAccessCommentMethodItem(SyntheticAccessorResolver.AccessedMember accessedMember, int codeAddress) {
|
||||
super(codeAddress);
|
||||
this.accessedMember = accessedMember;
|
||||
}
|
||||
@ -49,15 +49,73 @@ import java.io.IOException;
|
||||
}
|
||||
|
||||
public boolean writeTo(IndentingWriter writer) throws IOException {
|
||||
writer.write('#');
|
||||
if (accessedMember.accessedMemberType == SyntheticAccessorResolver.METHOD) {
|
||||
writer.write("calls: ");
|
||||
} else if (accessedMember.accessedMemberType == SyntheticAccessorResolver.GETTER) {
|
||||
writer.write("getter for: ");
|
||||
} else {
|
||||
writer.write("setter for: ");
|
||||
writer.write("# ");
|
||||
switch (accessedMember.accessedMemberType) {
|
||||
case SyntheticAccessorResolver.METHOD:
|
||||
writer.write("invokes: ");
|
||||
break;
|
||||
case SyntheticAccessorResolver.GETTER:
|
||||
writer.write("getter for: ");
|
||||
break;
|
||||
case SyntheticAccessorResolver.SETTER:
|
||||
writer.write("setter for: ");
|
||||
break;
|
||||
case SyntheticAccessorResolver.PREFIX_INCREMENT:
|
||||
writer.write("++operator for: ");
|
||||
break;
|
||||
case SyntheticAccessorResolver.POSTFIX_INCREMENT:
|
||||
writer.write("operator++ for: ");
|
||||
break;
|
||||
case SyntheticAccessorResolver.PREFIX_DECREMENT:
|
||||
writer.write("--operator for: ");
|
||||
break;
|
||||
case SyntheticAccessorResolver.POSTFIX_DECREMENT:
|
||||
writer.write("operator-- for: ");
|
||||
break;
|
||||
case SyntheticAccessorResolver.ADD_ASSIGNMENT:
|
||||
writer.write("+= operator for: ");
|
||||
break;
|
||||
case SyntheticAccessorResolver.SUB_ASSIGNMENT:
|
||||
writer.write("-= operator for: ");
|
||||
break;
|
||||
case SyntheticAccessorResolver.MUL_ASSIGNMENT:
|
||||
writer.write("*= operator for: ");
|
||||
break;
|
||||
case SyntheticAccessorResolver.DIV_ASSIGNMENT:
|
||||
writer.write("/= operator for: ");
|
||||
break;
|
||||
case SyntheticAccessorResolver.REM_ASSIGNMENT:
|
||||
writer.write("%= operator for: ");
|
||||
break;
|
||||
case SyntheticAccessorResolver.AND_ASSIGNMENT:
|
||||
writer.write("&= operator for: ");
|
||||
break;
|
||||
case SyntheticAccessorResolver.OR_ASSIGNMENT:
|
||||
writer.write("|= operator for: ");
|
||||
break;
|
||||
case SyntheticAccessorResolver.XOR_ASSIGNMENT:
|
||||
writer.write("^= operator for: ");
|
||||
break;
|
||||
case SyntheticAccessorResolver.SHL_ASSIGNMENT:
|
||||
writer.write("<<= operator for: ");
|
||||
break;
|
||||
case SyntheticAccessorResolver.SHR_ASSIGNMENT:
|
||||
writer.write(">>= operator for: ");
|
||||
break;
|
||||
case SyntheticAccessorResolver.USHR_ASSIGNMENT:
|
||||
writer.write(">>>= operator for: ");
|
||||
break;
|
||||
default:
|
||||
throw new ExceptionWithContext("Unknown access type: %d", accessedMember.accessedMemberType);
|
||||
}
|
||||
ReferenceFormatter.writeReference(writer, accessedMember.accessedMember);
|
||||
|
||||
int referenceType;
|
||||
if (accessedMember.accessedMemberType == SyntheticAccessorResolver.METHOD) {
|
||||
referenceType = ReferenceType.METHOD;
|
||||
} else {
|
||||
referenceType = ReferenceType.FIELD;
|
||||
}
|
||||
ReferenceFormatter.writeReference(writer, referenceType, accessedMember.accessedMember);
|
||||
return true;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
@ -29,9 +29,10 @@
|
||||
package org.jf.baksmali;
|
||||
|
||||
import org.jf.baksmali.Adaptors.ClassDefinition;
|
||||
import org.jf.dexlib.Code.Analysis.*;
|
||||
import org.jf.dexlib.Code.Analysis.InlineMethodResolver;
|
||||
import org.jf.dexlib2.iface.ClassDef;
|
||||
import org.jf.dexlib2.iface.DexFile;
|
||||
import org.jf.dexlib2.util.SyntheticAccessorResolver;
|
||||
import org.jf.util.ClassFileNameHandler;
|
||||
import org.jf.util.IndentingWriter;
|
||||
|
||||
@ -118,10 +119,9 @@ public class baksmali {
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: uncomment
|
||||
/*if (!noAccessorComments) {
|
||||
syntheticAccessorResolver = new SyntheticAccessorResolver(dexFile);
|
||||
}*/
|
||||
if (!noAccessorComments) {
|
||||
syntheticAccessorResolver = new SyntheticAccessorResolver(dexFile.getClasses());
|
||||
}
|
||||
|
||||
//sort the classes, so that if we're on a case-insensitive file system and need to handle classes with file
|
||||
//name collisions, then we'll use the same name for each class, if the dex file goes through multiple
|
||||
@ -146,7 +146,7 @@ public class baksmali {
|
||||
* package name are separated by '/'
|
||||
*/
|
||||
|
||||
String classDescriptor = classDef.getName();
|
||||
String classDescriptor = classDef.getType();
|
||||
|
||||
//validate that the descriptor is formatted like we expect
|
||||
if (classDescriptor.charAt(0) != 'L' ||
|
||||
|
39
dexlib2/accessorTestGenerator/build.gradle
Normal file
39
dexlib2/accessorTestGenerator/build.gradle
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2012, 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.
|
||||
*/
|
||||
|
||||
dependencies {
|
||||
compile project(':util')
|
||||
compile 'com.google.code.findbugs:jsr305:1.3.9'
|
||||
compile 'com.google.guava:guava:13.0.1'
|
||||
compile 'org.antlr:stringtemplate:4.0.2'
|
||||
|
||||
testCompile 'junit:junit:4.6'
|
||||
}
|
@ -0,0 +1,141 @@
|
||||
/*
|
||||
* Copyright 2012, 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.dexlib2;
|
||||
|
||||
import org.stringtemplate.v4.*;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.URL;
|
||||
|
||||
public class AccessorTestGenerator {
|
||||
private static class UnaryOperation {
|
||||
public final String name;
|
||||
public UnaryOperation(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
private static class BinaryOperation {
|
||||
public final String name;
|
||||
public final String[] inputTypes;
|
||||
public BinaryOperation(String name, String[] inputTypes) {
|
||||
this.name = name;
|
||||
this.inputTypes = inputTypes;
|
||||
}
|
||||
}
|
||||
|
||||
private static class TypeDef {
|
||||
public final String name;
|
||||
public final UnaryOperation[] unaryOperations;
|
||||
public final BinaryOperation[] binaryOperations;
|
||||
public TypeDef(String name, UnaryOperation[] unaryOperations, BinaryOperation[] binaryOperations) {
|
||||
this.name = name;
|
||||
this.unaryOperations = unaryOperations;
|
||||
this.binaryOperations = binaryOperations;
|
||||
}
|
||||
}
|
||||
|
||||
private static final UnaryOperation[] unaryOperations = new UnaryOperation[] {
|
||||
new UnaryOperation("preinc"),
|
||||
new UnaryOperation("postinc"),
|
||||
new UnaryOperation("predec"),
|
||||
new UnaryOperation("postdec")
|
||||
};
|
||||
|
||||
private static final String[] booleanInputs = new String[] {"boolean"};
|
||||
private static final String[] integralInputs = new String[] {"int", "long"};
|
||||
private static final String[] allInputs = new String[] {"int", "float", "long", "double"};
|
||||
|
||||
private static final BinaryOperation[] booleanOperations = new BinaryOperation[] {
|
||||
new BinaryOperation("and", booleanInputs),
|
||||
new BinaryOperation("or", booleanInputs),
|
||||
new BinaryOperation("xor", booleanInputs),
|
||||
};
|
||||
|
||||
private static final BinaryOperation[] floatOperations = new BinaryOperation[] {
|
||||
new BinaryOperation("add", allInputs),
|
||||
new BinaryOperation("sub", allInputs),
|
||||
new BinaryOperation("mul", allInputs),
|
||||
new BinaryOperation("div", allInputs),
|
||||
new BinaryOperation("rem", allInputs),
|
||||
};
|
||||
|
||||
private static final BinaryOperation[] integralOperations = new BinaryOperation[] {
|
||||
new BinaryOperation("add", allInputs),
|
||||
new BinaryOperation("sub", allInputs),
|
||||
new BinaryOperation("mul", allInputs),
|
||||
new BinaryOperation("div", allInputs),
|
||||
new BinaryOperation("rem", allInputs),
|
||||
new BinaryOperation("and", integralInputs),
|
||||
new BinaryOperation("or", integralInputs),
|
||||
new BinaryOperation("xor", integralInputs),
|
||||
new BinaryOperation("shl", integralInputs),
|
||||
new BinaryOperation("shr", integralInputs),
|
||||
new BinaryOperation("ushr", integralInputs),
|
||||
};
|
||||
|
||||
private static final TypeDef[] types = new TypeDef[] {
|
||||
new TypeDef("boolean", new UnaryOperation[0], booleanOperations),
|
||||
new TypeDef("byte", unaryOperations, integralOperations),
|
||||
new TypeDef("char", unaryOperations, integralOperations),
|
||||
new TypeDef("short", unaryOperations, integralOperations),
|
||||
new TypeDef("int", unaryOperations, integralOperations),
|
||||
new TypeDef("long", unaryOperations, integralOperations),
|
||||
new TypeDef("float", unaryOperations, floatOperations),
|
||||
new TypeDef("double", unaryOperations, floatOperations),
|
||||
};
|
||||
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
if (args.length != 1) {
|
||||
System.err.println("Usage: java org.jf.dexlib2.AccessorTestGenerator <output_file>");
|
||||
}
|
||||
|
||||
URL stgUrl = AccessorTestGenerator.class.getClassLoader().getResource("AccessorTest.stg");
|
||||
STGroupFile stg = new STGroupFile(stgUrl, "utf-8", '<', '>');
|
||||
ST fileSt = stg.getInstanceOf("file");
|
||||
fileSt.add("types", types);
|
||||
|
||||
PrintWriter w = null;
|
||||
try {
|
||||
w = new PrintWriter(new BufferedWriter(new FileWriter(args[0])));
|
||||
w.print(fileSt.render());
|
||||
} finally {
|
||||
if (w != null) {
|
||||
w.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -0,0 +1,86 @@
|
||||
decl(type, name, value) ::= "<type> <name><init(value)>;"
|
||||
init(v) ::= "<if(v)> = <v><endif>"
|
||||
|
||||
field_decl(type) ::= "private <type.name> <type.name>_val;"
|
||||
|
||||
preinc_template(type) ::= "++<type.name>_val;"
|
||||
postinc_template(type) ::= "<type.name>_val++;"
|
||||
predec_template(type) ::= "--<type.name>_val;"
|
||||
postdec_template(type) ::= "<type.name>_val--;"
|
||||
add_template(type) ::= "<type.name>_val += val;"
|
||||
sub_template(type) ::= "<type.name>_val -= val;"
|
||||
mul_template(type) ::= "<type.name>_val *= val;"
|
||||
div_template(type) ::= "<type.name>_val /= val;"
|
||||
rem_template(type) ::= "<type.name>_val %= val;"
|
||||
and_template(type) ::= "<type.name>_val &= val;"
|
||||
or_template(type) ::= "<type.name>_val |= val;"
|
||||
xor_template(type) ::= "<type.name>_val ^= val;"
|
||||
shl_template(type) ::= "<type.name>_val \<\<= val;"
|
||||
shr_template(type) ::= "<type.name>_val >>= val;"
|
||||
ushr_template(type) ::= "<type.name>_val >>>= val;"
|
||||
|
||||
operation_template_name(operation) ::= "<operation.name>_template"
|
||||
|
||||
binary_method(input, type, binary_operation) ::= <<
|
||||
public void <type.name>_<binary_operation.name>(<input> val) {
|
||||
<(operation_template_name(binary_operation))(type)>
|
||||
}
|
||||
>>
|
||||
|
||||
binary_methods(binary_operation, type) ::= <<
|
||||
<binary_operation.inputTypes:binary_method(type, binary_operation);separator="\n\n">
|
||||
>>
|
||||
|
||||
unary_method(unary_operation, type) ::= <<
|
||||
public void <type.name>_<unary_operation.name>() {
|
||||
<(operation_template_name(unary_operation))(type)>
|
||||
}
|
||||
>>
|
||||
|
||||
type_methods(type) ::= <<
|
||||
<[type.unaryOperations:unary_method(type), type.binaryOperations:binary_methods(type)];separator="\n\n">
|
||||
>>
|
||||
|
||||
|
||||
file(types) ::= <<
|
||||
/*
|
||||
* Copyright 2012, 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.dexlib2;
|
||||
|
||||
public class AccessorTypes {
|
||||
<types:field_decl();separator="\n">
|
||||
|
||||
private class Accessors {
|
||||
<types:type_methods();separator="\n\n">
|
||||
}
|
||||
}
|
||||
>>
|
@ -29,10 +29,91 @@
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
configurations {
|
||||
accessorTestGenerator
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile project(':util')
|
||||
compile 'com.google.code.findbugs:jsr305:1.3.9'
|
||||
compile 'com.google.guava:guava:13.0.1'
|
||||
|
||||
testCompile 'junit:junit:4.6'
|
||||
}
|
||||
|
||||
accessorTestGenerator project('accessorTestGenerator')
|
||||
}
|
||||
|
||||
ext.testAccessorOutputDir = file("${buildDir}/generated-accessor-test-sources")
|
||||
ext.testAccessorOutputFile = file("${buildDir}/generated-accessor-test-sources/org/jf/dexlib2/AccessorTypes.java")
|
||||
|
||||
sourceSets {
|
||||
// The sources for building the test dex file for the accessor test
|
||||
accessorTestDex {
|
||||
java {
|
||||
srcDir testAccessorOutputDir
|
||||
}
|
||||
}
|
||||
|
||||
// The sources for the accessor test itself
|
||||
accessorTest {
|
||||
java {
|
||||
compileClasspath += main.output
|
||||
runtimeClasspath += main.output
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
configurations {
|
||||
accessorTestDexCompile.extendsFrom compile
|
||||
accessorTestDexRuntime.extendsFrom runtime
|
||||
|
||||
accessorTestCompile.extendsFrom testCompile
|
||||
accessorTestRuntime.extendsFrom testRuntime
|
||||
}
|
||||
|
||||
idea {
|
||||
module {
|
||||
testSourceDirs += sourceSets.accessorTest.java.srcDirs
|
||||
}
|
||||
}
|
||||
|
||||
// You must manually execute this task to regenerate SyntheticAccessorFSM.java, after modifying the ragel file
|
||||
// e.g. ./gradlew ragel
|
||||
task ragel(type:Exec) {
|
||||
workingDir = 'src/main/ragel'
|
||||
|
||||
commandLine 'ragel', '-J', '-o', file('src/main/java/org/jf/dexlib2/util/SyntheticAccessorFSM.java'),
|
||||
'SyntheticAccessorFSM.rl'
|
||||
}
|
||||
|
||||
task generateAccessorTestSource(type: JavaExec) {
|
||||
outputs.dir file(testAccessorOutputDir)
|
||||
|
||||
mkdir(file(testAccessorOutputFile).parent)
|
||||
|
||||
classpath = configurations.accessorTestGenerator
|
||||
main = 'org.jf.dexlib2.AccessorTestGenerator'
|
||||
args testAccessorOutputFile
|
||||
}
|
||||
compileAccessorTestDexJava.dependsOn(generateAccessorTestSource)
|
||||
|
||||
task generateAccessorTestDex(type: Exec, dependsOn: compileAccessorTestDexJava) {
|
||||
def outputDex = file("${sourceSets.accessorTest.output.resourcesDir}/accessorTest.dex")
|
||||
mkdir(outputDex.parent)
|
||||
|
||||
inputs.dir project.sourceSets.accessorTestDex.output.classesDir
|
||||
outputs.file outputDex
|
||||
|
||||
sourceSets.accessorTest.resources
|
||||
|
||||
workingDir project.sourceSets.accessorTestDex.output.classesDir
|
||||
executable 'dx'
|
||||
args '--dex'
|
||||
args "--output=${outputDex}"
|
||||
args '.'
|
||||
}
|
||||
|
||||
task accessorTest(type: Test, dependsOn: generateAccessorTestDex) {
|
||||
testClassesDir = project.sourceSets.accessorTest.output.classesDir
|
||||
classpath = project.sourceSets.accessorTest.runtimeClasspath
|
||||
}
|
||||
|
133
dexlib2/src/accessorTest/java/org/jf/dexlib2/AccessorTest.java
Normal file
133
dexlib2/src/accessorTest/java/org/jf/dexlib2/AccessorTest.java
Normal file
@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright 2012, 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.dexlib2;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import junit.framework.Assert;
|
||||
import org.jf.dexlib2.iface.ClassDef;
|
||||
import org.jf.dexlib2.iface.DexFile;
|
||||
import org.jf.dexlib2.iface.Method;
|
||||
import org.jf.dexlib2.iface.MethodImplementation;
|
||||
import org.jf.dexlib2.iface.instruction.Instruction;
|
||||
import org.jf.dexlib2.iface.instruction.ReferenceInstruction;
|
||||
import org.jf.dexlib2.iface.reference.FieldReference;
|
||||
import org.jf.dexlib2.iface.reference.MethodReference;
|
||||
import org.jf.dexlib2.util.SyntheticAccessorResolver;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class AccessorTest {
|
||||
private Pattern accessorMethodPattern = Pattern.compile("([a-zA-Z]*)_([a-zA-Z]*)");
|
||||
|
||||
private static final Map<String, Integer> operationTypes;
|
||||
|
||||
static {
|
||||
ImmutableMap.Builder<String, Integer> builder = ImmutableMap.builder();
|
||||
builder.put("postinc", SyntheticAccessorResolver.POSTFIX_INCREMENT);
|
||||
builder.put("preinc", SyntheticAccessorResolver.PREFIX_INCREMENT);
|
||||
builder.put("postdec", SyntheticAccessorResolver.POSTFIX_DECREMENT);
|
||||
builder.put("predec", SyntheticAccessorResolver.PREFIX_DECREMENT);
|
||||
builder.put("add", SyntheticAccessorResolver.ADD_ASSIGNMENT);
|
||||
builder.put("sub", SyntheticAccessorResolver.SUB_ASSIGNMENT);
|
||||
builder.put("mul", SyntheticAccessorResolver.MUL_ASSIGNMENT);
|
||||
builder.put("div", SyntheticAccessorResolver.DIV_ASSIGNMENT);
|
||||
builder.put("rem", SyntheticAccessorResolver.REM_ASSIGNMENT);
|
||||
builder.put("and", SyntheticAccessorResolver.AND_ASSIGNMENT);
|
||||
builder.put("or", SyntheticAccessorResolver.OR_ASSIGNMENT);
|
||||
builder.put("xor", SyntheticAccessorResolver.XOR_ASSIGNMENT);
|
||||
builder.put("shl", SyntheticAccessorResolver.SHL_ASSIGNMENT);
|
||||
builder.put("shr", SyntheticAccessorResolver.SHR_ASSIGNMENT);
|
||||
builder.put("ushr", SyntheticAccessorResolver.USHR_ASSIGNMENT);
|
||||
operationTypes = builder.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAccessors() throws IOException {
|
||||
URL url = AccessorTest.class.getClassLoader().getResource("accessorTest.dex");
|
||||
Assert.assertNotNull(url);
|
||||
DexFile f = DexFileFactory.loadDexFile(url.getFile());
|
||||
|
||||
SyntheticAccessorResolver sar = new SyntheticAccessorResolver(f.getClasses());
|
||||
|
||||
ClassDef accessorTypesClass = null;
|
||||
ClassDef accessorsClass = null;
|
||||
|
||||
for (ClassDef classDef: f.getClasses()) {
|
||||
String className = classDef.getType();
|
||||
|
||||
if (className.equals("Lorg/jf/dexlib2/AccessorTypes;")) {
|
||||
accessorTypesClass = classDef;
|
||||
} else if (className.equals("Lorg/jf/dexlib2/AccessorTypes$Accessors;")) {
|
||||
accessorsClass = classDef;
|
||||
}
|
||||
}
|
||||
|
||||
Assert.assertNotNull(accessorTypesClass);
|
||||
Assert.assertNotNull(accessorsClass);
|
||||
|
||||
for (Method method: accessorsClass.getMethods()) {
|
||||
Matcher m = accessorMethodPattern.matcher(method.getName());
|
||||
if (!m.matches()) {
|
||||
continue;
|
||||
}
|
||||
String type = m.group(1);
|
||||
String operation = m.group(2);
|
||||
|
||||
MethodImplementation methodImpl = method.getImplementation();
|
||||
Assert.assertNotNull(methodImpl);
|
||||
|
||||
for (Instruction instruction: methodImpl.getInstructions()) {
|
||||
Opcode opcode = instruction.getOpcode();
|
||||
if (opcode == Opcode.INVOKE_STATIC || opcode == Opcode.INVOKE_STATIC_RANGE) {
|
||||
MethodReference accessorMethod =
|
||||
(MethodReference)((ReferenceInstruction) instruction).getReference();
|
||||
|
||||
SyntheticAccessorResolver.AccessedMember accessedMember = sar.getAccessedMember(accessorMethod);
|
||||
|
||||
Assert.assertNotNull(String.format("Could not resolve accessor for %s_%s", type, operation),
|
||||
accessedMember);
|
||||
|
||||
int operationType = operationTypes.get(operation);
|
||||
Assert.assertEquals(operationType, accessedMember.accessedMemberType);
|
||||
|
||||
Assert.assertEquals(String.format("%s_val", type),
|
||||
((FieldReference)accessedMember.accessedMember).getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,565 @@
|
||||
|
||||
// line 1 "SyntheticAccessorFSM.rl"
|
||||
/*
|
||||
* Copyright 2012, 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.dexlib2.util;
|
||||
|
||||
import org.jf.dexlib2.iface.instruction.Instruction;
|
||||
import org.jf.dexlib2.iface.instruction.formats.Instruction22b;
|
||||
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction;
|
||||
import org.jf.dexlib2.iface.instruction.WideLiteralInstruction;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SyntheticAccessorFSM {
|
||||
|
||||
// line 43 "SyntheticAccessorFSM.rl"
|
||||
|
||||
// line 48 "/home/jesusfreke/projects/smali/dexlib2/src/main/java/org/jf/dexlib2/util/SyntheticAccessorFSM.java"
|
||||
private static byte[] init__SyntheticAccessorFSM_actions_0()
|
||||
{
|
||||
return new byte [] {
|
||||
0, 1, 0, 1, 1, 1, 2, 1, 13, 1, 14, 1,
|
||||
15, 1, 16, 1, 17, 1, 18, 1, 19, 1, 20, 1,
|
||||
21, 1, 25, 2, 3, 7, 2, 4, 7, 2, 5, 7,
|
||||
2, 6, 7, 2, 8, 12, 2, 9, 12, 2, 10, 12,
|
||||
2, 11, 12, 2, 22, 23, 2, 22, 24, 2, 22, 25,
|
||||
2, 22, 26, 2, 22, 27, 2, 22, 28
|
||||
};
|
||||
}
|
||||
|
||||
private static final byte _SyntheticAccessorFSM_actions[] = init__SyntheticAccessorFSM_actions_0();
|
||||
|
||||
|
||||
private static short[] init__SyntheticAccessorFSM_key_offsets_0()
|
||||
{
|
||||
return new short [] {
|
||||
0, 0, 12, 82, 98, 102, 104, 166, 172, 174, 180, 184,
|
||||
190, 192, 196, 198, 201, 203
|
||||
};
|
||||
}
|
||||
|
||||
private static final short _SyntheticAccessorFSM_key_offsets[] = init__SyntheticAccessorFSM_key_offsets_0();
|
||||
|
||||
|
||||
private static short[] init__SyntheticAccessorFSM_trans_keys_0()
|
||||
{
|
||||
return new short [] {
|
||||
82, 88, 89, 95, 96, 102, 103, 109, 110, 114, 116, 120,
|
||||
145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156,
|
||||
157, 158, 159, 160, 161, 162, 163, 164, 165, 166, 167, 168,
|
||||
169, 170, 171, 172, 173, 174, 175, 177, 179, 180, 181, 182,
|
||||
183, 184, 185, 186, 187, 188, 190, 191, 192, 193, 194, 195,
|
||||
196, 197, 198, 199, 201, 202, 203, 204, 206, 207, 208, 216,
|
||||
15, 17, 18, 25, 129, 143, 144, 176, 178, 205, 144, 145,
|
||||
155, 156, 166, 167, 171, 172, 176, 177, 187, 188, 198, 199,
|
||||
203, 204, 89, 95, 103, 109, 15, 17, 145, 146, 147, 148,
|
||||
149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160,
|
||||
161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172,
|
||||
173, 174, 175, 177, 179, 180, 181, 182, 183, 184, 185, 186,
|
||||
187, 188, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199,
|
||||
201, 202, 203, 204, 206, 207, 144, 176, 178, 205, 89, 95,
|
||||
103, 109, 129, 143, 15, 17, 89, 95, 103, 109, 129, 143,
|
||||
89, 95, 103, 109, 89, 95, 103, 109, 129, 143, 15, 17,
|
||||
89, 95, 103, 109, 15, 17, 14, 10, 12, 15, 17, 0
|
||||
};
|
||||
}
|
||||
|
||||
private static final short _SyntheticAccessorFSM_trans_keys[] = init__SyntheticAccessorFSM_trans_keys_0();
|
||||
|
||||
|
||||
private static byte[] init__SyntheticAccessorFSM_single_lengths_0()
|
||||
{
|
||||
return new byte [] {
|
||||
0, 0, 60, 16, 0, 0, 58, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 1, 0, 0
|
||||
};
|
||||
}
|
||||
|
||||
private static final byte _SyntheticAccessorFSM_single_lengths[] = init__SyntheticAccessorFSM_single_lengths_0();
|
||||
|
||||
|
||||
private static byte[] init__SyntheticAccessorFSM_range_lengths_0()
|
||||
{
|
||||
return new byte [] {
|
||||
0, 6, 5, 0, 2, 1, 2, 3, 1, 3, 2, 3,
|
||||
1, 2, 1, 1, 1, 0
|
||||
};
|
||||
}
|
||||
|
||||
private static final byte _SyntheticAccessorFSM_range_lengths[] = init__SyntheticAccessorFSM_range_lengths_0();
|
||||
|
||||
|
||||
private static short[] init__SyntheticAccessorFSM_index_offsets_0()
|
||||
{
|
||||
return new short [] {
|
||||
0, 0, 7, 73, 90, 93, 95, 156, 160, 162, 166, 169,
|
||||
173, 175, 178, 180, 183, 185
|
||||
};
|
||||
}
|
||||
|
||||
private static final short _SyntheticAccessorFSM_index_offsets[] = init__SyntheticAccessorFSM_index_offsets_0();
|
||||
|
||||
|
||||
private static byte[] init__SyntheticAccessorFSM_indicies_0()
|
||||
{
|
||||
return new byte [] {
|
||||
0, 2, 0, 2, 3, 3, 1, 8, 9, 10, 11, 12,
|
||||
13, 14, 15, 16, 17, 18, 19, 9, 10, 11, 12, 13,
|
||||
14, 15, 16, 17, 20, 21, 9, 10, 11, 22, 23, 9,
|
||||
10, 11, 8, 10, 11, 12, 13, 14, 15, 16, 17, 18,
|
||||
19, 10, 11, 12, 13, 14, 15, 16, 17, 20, 21, 10,
|
||||
11, 22, 23, 10, 11, 24, 24, 4, 5, 6, 7, 9,
|
||||
1, 25, 26, 27, 28, 29, 30, 31, 32, 25, 26, 27,
|
||||
28, 29, 30, 31, 32, 1, 33, 33, 1, 34, 1, 8,
|
||||
9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 9,
|
||||
10, 11, 12, 13, 14, 15, 16, 17, 20, 21, 9, 10,
|
||||
11, 22, 23, 9, 10, 11, 8, 10, 11, 12, 13, 14,
|
||||
15, 16, 17, 18, 19, 10, 11, 12, 13, 14, 15, 16,
|
||||
17, 20, 21, 10, 11, 22, 23, 10, 11, 7, 9, 1,
|
||||
35, 35, 36, 1, 37, 1, 35, 35, 38, 1, 35, 35,
|
||||
1, 39, 39, 40, 1, 41, 1, 39, 39, 1, 42, 1,
|
||||
44, 43, 1, 45, 1, 1, 0
|
||||
};
|
||||
}
|
||||
|
||||
private static final byte _SyntheticAccessorFSM_indicies[] = init__SyntheticAccessorFSM_indicies_0();
|
||||
|
||||
|
||||
private static byte[] init__SyntheticAccessorFSM_trans_targs_0()
|
||||
{
|
||||
return new byte [] {
|
||||
2, 0, 14, 15, 17, 3, 6, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||
11, 4, 4, 4, 4, 4, 4, 4, 4, 5, 17, 8,
|
||||
9, 17, 10, 12, 13, 17, 17, 16, 17, 17
|
||||
};
|
||||
}
|
||||
|
||||
private static final byte _SyntheticAccessorFSM_trans_targs[] = init__SyntheticAccessorFSM_trans_targs_0();
|
||||
|
||||
|
||||
private static byte[] init__SyntheticAccessorFSM_trans_actions_0()
|
||||
{
|
||||
return new byte [] {
|
||||
0, 0, 1, 0, 51, 3, 0, 27, 39, 7, 9, 11,
|
||||
13, 15, 17, 19, 21, 23, 30, 42, 33, 45, 36, 48,
|
||||
5, 27, 39, 30, 42, 33, 45, 36, 48, 1, 63, 1,
|
||||
0, 66, 0, 1, 0, 60, 54, 0, 25, 57
|
||||
};
|
||||
}
|
||||
|
||||
private static final byte _SyntheticAccessorFSM_trans_actions[] = init__SyntheticAccessorFSM_trans_actions_0();
|
||||
|
||||
|
||||
static final int SyntheticAccessorFSM_start = 1;
|
||||
static final int SyntheticAccessorFSM_first_final = 17;
|
||||
static final int SyntheticAccessorFSM_error = 0;
|
||||
|
||||
static final int SyntheticAccessorFSM_en_main = 1;
|
||||
|
||||
|
||||
// line 44 "SyntheticAccessorFSM.rl"
|
||||
|
||||
// math type constants
|
||||
public static final int ADD = SyntheticAccessorResolver.ADD_ASSIGNMENT;
|
||||
public static final int SUB = SyntheticAccessorResolver.SUB_ASSIGNMENT;
|
||||
public static final int MUL = SyntheticAccessorResolver.MUL_ASSIGNMENT;
|
||||
public static final int DIV = SyntheticAccessorResolver.DIV_ASSIGNMENT;
|
||||
public static final int REM = SyntheticAccessorResolver.REM_ASSIGNMENT;
|
||||
public static final int AND = SyntheticAccessorResolver.AND_ASSIGNMENT;
|
||||
public static final int OR = SyntheticAccessorResolver.OR_ASSIGNMENT;
|
||||
public static final int XOR = SyntheticAccessorResolver.XOR_ASSIGNMENT;
|
||||
public static final int SHL = SyntheticAccessorResolver.SHL_ASSIGNMENT;
|
||||
public static final int SHR = SyntheticAccessorResolver.SHR_ASSIGNMENT;
|
||||
public static final int USHR = SyntheticAccessorResolver.USHR_ASSIGNMENT;
|
||||
|
||||
public static final int INT = 0;
|
||||
public static final int LONG = 1;
|
||||
public static final int FLOAT = 2;
|
||||
public static final int DOUBLE = 3;
|
||||
|
||||
public static final int POSITIVE_ONE = 1;
|
||||
public static final int NEGATIVE_ONE = -1;
|
||||
public static final int OTHER = 0;
|
||||
|
||||
public static int test(List<? extends Instruction> instructions) {
|
||||
int accessorType = -1;
|
||||
int cs, p = 0;
|
||||
int pe = instructions.size();
|
||||
|
||||
// one of the math type constants representing the type of math operation being performed
|
||||
int mathOp = -1;
|
||||
|
||||
// for increments an decrements, the type of value the math operation is on
|
||||
int mathType = -1;
|
||||
|
||||
// for increments and decrements, the value of the constant that is used
|
||||
long constantValue = 0;
|
||||
|
||||
// The source register for the put instruction
|
||||
int putRegister = -1;
|
||||
// The return register;
|
||||
int returnRegister = -1;
|
||||
|
||||
|
||||
// line 236 "/home/jesusfreke/projects/smali/dexlib2/src/main/java/org/jf/dexlib2/util/SyntheticAccessorFSM.java"
|
||||
{
|
||||
cs = SyntheticAccessorFSM_start;
|
||||
}
|
||||
|
||||
// line 241 "/home/jesusfreke/projects/smali/dexlib2/src/main/java/org/jf/dexlib2/util/SyntheticAccessorFSM.java"
|
||||
{
|
||||
int _klen;
|
||||
int _trans = 0;
|
||||
int _acts;
|
||||
int _nacts;
|
||||
int _keys;
|
||||
int _goto_targ = 0;
|
||||
|
||||
_goto: while (true) {
|
||||
switch ( _goto_targ ) {
|
||||
case 0:
|
||||
if ( p == pe ) {
|
||||
_goto_targ = 4;
|
||||
continue _goto;
|
||||
}
|
||||
if ( cs == 0 ) {
|
||||
_goto_targ = 5;
|
||||
continue _goto;
|
||||
}
|
||||
case 1:
|
||||
_match: do {
|
||||
_keys = _SyntheticAccessorFSM_key_offsets[cs];
|
||||
_trans = _SyntheticAccessorFSM_index_offsets[cs];
|
||||
_klen = _SyntheticAccessorFSM_single_lengths[cs];
|
||||
if ( _klen > 0 ) {
|
||||
int _lower = _keys;
|
||||
int _mid;
|
||||
int _upper = _keys + _klen - 1;
|
||||
while (true) {
|
||||
if ( _upper < _lower )
|
||||
break;
|
||||
|
||||
_mid = _lower + ((_upper-_lower) >> 1);
|
||||
if ( ( instructions.get(p).getOpcode().value) < _SyntheticAccessorFSM_trans_keys[_mid] )
|
||||
_upper = _mid - 1;
|
||||
else if ( ( instructions.get(p).getOpcode().value) > _SyntheticAccessorFSM_trans_keys[_mid] )
|
||||
_lower = _mid + 1;
|
||||
else {
|
||||
_trans += (_mid - _keys);
|
||||
break _match;
|
||||
}
|
||||
}
|
||||
_keys += _klen;
|
||||
_trans += _klen;
|
||||
}
|
||||
|
||||
_klen = _SyntheticAccessorFSM_range_lengths[cs];
|
||||
if ( _klen > 0 ) {
|
||||
int _lower = _keys;
|
||||
int _mid;
|
||||
int _upper = _keys + (_klen<<1) - 2;
|
||||
while (true) {
|
||||
if ( _upper < _lower )
|
||||
break;
|
||||
|
||||
_mid = _lower + (((_upper-_lower) >> 1) & ~1);
|
||||
if ( ( instructions.get(p).getOpcode().value) < _SyntheticAccessorFSM_trans_keys[_mid] )
|
||||
_upper = _mid - 2;
|
||||
else if ( ( instructions.get(p).getOpcode().value) > _SyntheticAccessorFSM_trans_keys[_mid+1] )
|
||||
_lower = _mid + 2;
|
||||
else {
|
||||
_trans += ((_mid - _keys)>>1);
|
||||
break _match;
|
||||
}
|
||||
}
|
||||
_trans += _klen;
|
||||
}
|
||||
} while (false);
|
||||
|
||||
_trans = _SyntheticAccessorFSM_indicies[_trans];
|
||||
cs = _SyntheticAccessorFSM_trans_targs[_trans];
|
||||
|
||||
if ( _SyntheticAccessorFSM_trans_actions[_trans] != 0 ) {
|
||||
_acts = _SyntheticAccessorFSM_trans_actions[_trans];
|
||||
_nacts = (int) _SyntheticAccessorFSM_actions[_acts++];
|
||||
while ( _nacts-- > 0 )
|
||||
{
|
||||
switch ( _SyntheticAccessorFSM_actions[_acts++] )
|
||||
{
|
||||
case 0:
|
||||
// line 94 "SyntheticAccessorFSM.rl"
|
||||
{
|
||||
putRegister = ((OneRegisterInstruction)instructions.get(p)).getRegisterA();
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
// line 101 "SyntheticAccessorFSM.rl"
|
||||
{
|
||||
constantValue = ((WideLiteralInstruction)instructions.get(p)).getWideLiteral();
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
// line 105 "SyntheticAccessorFSM.rl"
|
||||
{
|
||||
mathType = INT;
|
||||
mathOp = ADD;
|
||||
constantValue = ((WideLiteralInstruction)instructions.get(p)).getWideLiteral();
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
// line 111 "SyntheticAccessorFSM.rl"
|
||||
{ mathType = INT; }
|
||||
break;
|
||||
case 4:
|
||||
// line 112 "SyntheticAccessorFSM.rl"
|
||||
{ mathType = LONG; }
|
||||
break;
|
||||
case 5:
|
||||
// line 113 "SyntheticAccessorFSM.rl"
|
||||
{ mathType = FLOAT; }
|
||||
break;
|
||||
case 6:
|
||||
// line 114 "SyntheticAccessorFSM.rl"
|
||||
{mathType = DOUBLE; }
|
||||
break;
|
||||
case 7:
|
||||
// line 114 "SyntheticAccessorFSM.rl"
|
||||
{
|
||||
mathOp = ADD;
|
||||
}
|
||||
break;
|
||||
case 8:
|
||||
// line 117 "SyntheticAccessorFSM.rl"
|
||||
{ mathType = INT; }
|
||||
break;
|
||||
case 9:
|
||||
// line 118 "SyntheticAccessorFSM.rl"
|
||||
{ mathType = LONG; }
|
||||
break;
|
||||
case 10:
|
||||
// line 119 "SyntheticAccessorFSM.rl"
|
||||
{ mathType = FLOAT; }
|
||||
break;
|
||||
case 11:
|
||||
// line 120 "SyntheticAccessorFSM.rl"
|
||||
{mathType = DOUBLE; }
|
||||
break;
|
||||
case 12:
|
||||
// line 120 "SyntheticAccessorFSM.rl"
|
||||
{
|
||||
mathOp = SUB;
|
||||
}
|
||||
break;
|
||||
case 13:
|
||||
// line 124 "SyntheticAccessorFSM.rl"
|
||||
{
|
||||
mathOp = MUL;
|
||||
}
|
||||
break;
|
||||
case 14:
|
||||
// line 128 "SyntheticAccessorFSM.rl"
|
||||
{
|
||||
mathOp = DIV;
|
||||
}
|
||||
break;
|
||||
case 15:
|
||||
// line 132 "SyntheticAccessorFSM.rl"
|
||||
{
|
||||
mathOp = REM;
|
||||
}
|
||||
break;
|
||||
case 16:
|
||||
// line 135 "SyntheticAccessorFSM.rl"
|
||||
{
|
||||
mathOp = AND;
|
||||
}
|
||||
break;
|
||||
case 17:
|
||||
// line 138 "SyntheticAccessorFSM.rl"
|
||||
{
|
||||
mathOp = OR;
|
||||
}
|
||||
break;
|
||||
case 18:
|
||||
// line 141 "SyntheticAccessorFSM.rl"
|
||||
{
|
||||
mathOp = XOR;
|
||||
}
|
||||
break;
|
||||
case 19:
|
||||
// line 144 "SyntheticAccessorFSM.rl"
|
||||
{
|
||||
mathOp = SHL;
|
||||
}
|
||||
break;
|
||||
case 20:
|
||||
// line 147 "SyntheticAccessorFSM.rl"
|
||||
{
|
||||
mathOp = SHR;
|
||||
}
|
||||
break;
|
||||
case 21:
|
||||
// line 150 "SyntheticAccessorFSM.rl"
|
||||
{
|
||||
mathOp = USHR;
|
||||
}
|
||||
break;
|
||||
case 22:
|
||||
// line 156 "SyntheticAccessorFSM.rl"
|
||||
{
|
||||
returnRegister = ((OneRegisterInstruction)instructions.get(p)).getRegisterA();
|
||||
}
|
||||
break;
|
||||
case 23:
|
||||
// line 162 "SyntheticAccessorFSM.rl"
|
||||
{
|
||||
accessorType = SyntheticAccessorResolver.GETTER; { p += 1; _goto_targ = 5; if (true) continue _goto;}
|
||||
}
|
||||
break;
|
||||
case 24:
|
||||
// line 166 "SyntheticAccessorFSM.rl"
|
||||
{
|
||||
accessorType = SyntheticAccessorResolver.SETTER; { p += 1; _goto_targ = 5; if (true) continue _goto;}
|
||||
}
|
||||
break;
|
||||
case 25:
|
||||
// line 170 "SyntheticAccessorFSM.rl"
|
||||
{
|
||||
accessorType = SyntheticAccessorResolver.METHOD; { p += 1; _goto_targ = 5; if (true) continue _goto;}
|
||||
}
|
||||
break;
|
||||
case 26:
|
||||
// line 174 "SyntheticAccessorFSM.rl"
|
||||
{
|
||||
accessorType = getIncrementType(mathOp, mathType, constantValue, putRegister, returnRegister);
|
||||
}
|
||||
break;
|
||||
case 27:
|
||||
// line 178 "SyntheticAccessorFSM.rl"
|
||||
{
|
||||
accessorType = getIncrementType(mathOp, mathType, constantValue, putRegister, returnRegister);
|
||||
}
|
||||
break;
|
||||
case 28:
|
||||
// line 186 "SyntheticAccessorFSM.rl"
|
||||
{
|
||||
accessorType = mathOp; { p += 1; _goto_targ = 5; if (true) continue _goto;}
|
||||
}
|
||||
break;
|
||||
// line 481 "/home/jesusfreke/projects/smali/dexlib2/src/main/java/org/jf/dexlib2/util/SyntheticAccessorFSM.java"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
case 2:
|
||||
if ( cs == 0 ) {
|
||||
_goto_targ = 5;
|
||||
continue _goto;
|
||||
}
|
||||
if ( ++p != pe ) {
|
||||
_goto_targ = 1;
|
||||
continue _goto;
|
||||
}
|
||||
case 4:
|
||||
case 5:
|
||||
}
|
||||
break; }
|
||||
}
|
||||
|
||||
// line 199 "SyntheticAccessorFSM.rl"
|
||||
|
||||
|
||||
return accessorType;
|
||||
}
|
||||
|
||||
private static int getIncrementType(int mathOp, int mathType, long constantValue, int putRegister,
|
||||
int returnRegister) {
|
||||
boolean isPrefix = putRegister == returnRegister;
|
||||
|
||||
boolean negativeConstant = false;
|
||||
|
||||
switch (mathType) {
|
||||
case INT:
|
||||
case LONG: {
|
||||
if (constantValue == 1) {
|
||||
negativeConstant = false;
|
||||
} else if (constantValue == -1) {
|
||||
negativeConstant = true;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FLOAT: {
|
||||
float val = Float.intBitsToFloat((int)constantValue);
|
||||
if (val == 1) {
|
||||
negativeConstant = false;
|
||||
} else if (val == -1) {
|
||||
negativeConstant = true;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DOUBLE: {
|
||||
double val = Double.longBitsToDouble(constantValue);
|
||||
if (val == 1) {
|
||||
negativeConstant = false;
|
||||
} else if (val == -1) {
|
||||
negativeConstant = true;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
boolean isAdd = ((mathOp == ADD) && !negativeConstant) ||
|
||||
((mathOp == SUB) && negativeConstant);
|
||||
|
||||
if (isPrefix) {
|
||||
if (isAdd) {
|
||||
return SyntheticAccessorResolver.PREFIX_INCREMENT;
|
||||
} else {
|
||||
return SyntheticAccessorResolver.PREFIX_DECREMENT;
|
||||
}
|
||||
} else {
|
||||
if (isAdd) {
|
||||
return SyntheticAccessorResolver.POSTFIX_INCREMENT;
|
||||
} else {
|
||||
return SyntheticAccessorResolver.POSTFIX_DECREMENT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright 2012, 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.dexlib2.util;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import org.jf.dexlib2.AccessFlags;
|
||||
import org.jf.dexlib2.iface.ClassDef;
|
||||
import org.jf.dexlib2.iface.Method;
|
||||
import org.jf.dexlib2.iface.MethodImplementation;
|
||||
import org.jf.dexlib2.iface.instruction.Instruction;
|
||||
import org.jf.dexlib2.iface.instruction.ReferenceInstruction;
|
||||
import org.jf.dexlib2.iface.reference.*;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.*;
|
||||
|
||||
public class SyntheticAccessorResolver {
|
||||
public static final int METHOD = 0;
|
||||
public static final int GETTER = 1;
|
||||
public static final int SETTER = 2;
|
||||
public static final int POSTFIX_INCREMENT = 3;
|
||||
public static final int PREFIX_INCREMENT = 4;
|
||||
public static final int POSTFIX_DECREMENT = 5;
|
||||
public static final int PREFIX_DECREMENT = 6;
|
||||
public static final int ADD_ASSIGNMENT = 7;
|
||||
public static final int SUB_ASSIGNMENT = 8;
|
||||
public static final int MUL_ASSIGNMENT = 9;
|
||||
public static final int DIV_ASSIGNMENT = 10;
|
||||
public static final int REM_ASSIGNMENT = 11;
|
||||
public static final int AND_ASSIGNMENT = 12;
|
||||
public static final int OR_ASSIGNMENT = 13;
|
||||
public static final int XOR_ASSIGNMENT = 14;
|
||||
public static final int SHL_ASSIGNMENT = 15;
|
||||
public static final int SHR_ASSIGNMENT = 16;
|
||||
public static final int USHR_ASSIGNMENT = 17;
|
||||
|
||||
|
||||
//TODO: use a hashmap for the classes?
|
||||
private final Map<String, ClassDef> classDefMap;
|
||||
private final HashMap<String, AccessedMember> resolvedAccessors = new HashMap<String, AccessedMember>();
|
||||
|
||||
public SyntheticAccessorResolver(List<? extends ClassDef> classDefs) {
|
||||
ImmutableMap.Builder<String, ClassDef> builder = ImmutableMap.builder();
|
||||
|
||||
for (ClassDef classDef: classDefs) {
|
||||
builder.put(classDef.getType(), classDef);
|
||||
}
|
||||
|
||||
this.classDefMap = builder.build();
|
||||
}
|
||||
|
||||
public static boolean looksLikeSyntheticAccessor(String methodName) {
|
||||
return methodName.startsWith("access$");
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public AccessedMember getAccessedMember(@Nonnull MethodReference methodReference) {
|
||||
String methodDescriptor = ReferenceUtil.getMethodDescriptor(methodReference);
|
||||
|
||||
AccessedMember accessedMember = resolvedAccessors.get(methodDescriptor);
|
||||
if (accessedMember != null) {
|
||||
return accessedMember;
|
||||
}
|
||||
|
||||
String type = methodReference.getContainingClass();
|
||||
ClassDef classDef = classDefMap.get(type);
|
||||
if (classDef == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Method matchedMethod = null;
|
||||
MethodImplementation matchedMethodImpl = null;
|
||||
for (Method method: classDef.getMethods()) {
|
||||
MethodImplementation methodImpl = method.getImplementation();
|
||||
if (methodImpl != null) {
|
||||
if (methodReferenceEquals(method, methodReference)) {
|
||||
matchedMethod = method;
|
||||
matchedMethodImpl = methodImpl;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (matchedMethod == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
//A synthetic accessor will be marked synthetic
|
||||
if (!AccessFlags.SYNTHETIC.isSet(matchedMethod.getAccessFlags())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<Instruction> instructions = ImmutableList.copyOf(matchedMethodImpl.getInstructions());
|
||||
|
||||
int accessType = SyntheticAccessorFSM.test(instructions);
|
||||
|
||||
byte b = 0;
|
||||
double l = 12341234.567;
|
||||
b += l;
|
||||
|
||||
if (accessType >= 0) {
|
||||
return new AccessedMember(accessType, ((ReferenceInstruction)instructions.get(0)).getReference());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static class AccessedMember {
|
||||
public final int accessedMemberType;
|
||||
@Nonnull public final Reference accessedMember;
|
||||
|
||||
public AccessedMember(int accessedMemberType, @Nonnull Reference accessedMember) {
|
||||
this.accessedMemberType = accessedMemberType;
|
||||
this.accessedMember = accessedMember;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
switch (accessedMemberType) {
|
||||
case METHOD:
|
||||
|
||||
}
|
||||
return super.hashCode(); //To change body of overridden methods use File | Settings | File Templates.
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean methodReferenceEquals(@Nonnull MethodReference ref1, @Nonnull MethodReference ref2) {
|
||||
// we already know the containing class matches
|
||||
if ((!ref1.getName().equals(ref2.getName())) ||
|
||||
(!ref1.getReturnType().equals(ref2.getReturnType()))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Iterator<? extends BasicMethodParameter> params1 = ref1.getParameters().iterator();
|
||||
Iterator<? extends BasicMethodParameter> params2 = ref2.getParameters().iterator();
|
||||
while (params1.hasNext() && params2.hasNext()) {
|
||||
if (!params1.next().getType().equals(params2.next().getType())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return (!params1.hasNext()) && (!params2.hasNext());
|
||||
}
|
||||
}
|
246
dexlib2/src/main/ragel/Opcodes.rl
Normal file
246
dexlib2/src/main/ragel/Opcodes.rl
Normal file
@ -0,0 +1,246 @@
|
||||
define nop 0
|
||||
define move 1
|
||||
define move_from16 2
|
||||
define move_16 3
|
||||
define move_wide 4
|
||||
define move_wide_from16 5
|
||||
define move_wide_16 6
|
||||
define move_object 7
|
||||
define move_object_from16 8
|
||||
define move_object_16 9
|
||||
define move_result 10
|
||||
define move_result_wide 11
|
||||
define move_result_object 12
|
||||
define move_exception 13
|
||||
define return_void 14
|
||||
define return 15
|
||||
define return_wide 16
|
||||
define return_object 17
|
||||
define const_4 18
|
||||
define const_16 19
|
||||
define const 20
|
||||
define const_high16 21
|
||||
define const_wide_16 22
|
||||
define const_wide_32 23
|
||||
define const_wide 24
|
||||
define const_wide_high16 25
|
||||
define const_string 26
|
||||
define const_string_jumbo 27
|
||||
define const_class 28
|
||||
define monitor_enter 29
|
||||
define monitor_exit 30
|
||||
define check_cast 31
|
||||
define instance_of 32
|
||||
define array_length 33
|
||||
define new_instance 34
|
||||
define new_array 35
|
||||
define filled_new_array 36
|
||||
define filled_new_array_range 37
|
||||
define fill_array_data 38
|
||||
define throw 39
|
||||
define goto 40
|
||||
define goto_16 41
|
||||
define goto_32 42
|
||||
define packed_switch 43
|
||||
define sparse_switch 44
|
||||
define cmpl_float 45
|
||||
define cmpg_float 46
|
||||
define cmpl_double 47
|
||||
define cmpg_double 48
|
||||
define cmp_long 49
|
||||
define if_eq 50
|
||||
define if_ne 51
|
||||
define if_lt 52
|
||||
define if_ge 53
|
||||
define if_gt 54
|
||||
define if_le 55
|
||||
define if_eqz 56
|
||||
define if_nez 57
|
||||
define if_ltz 58
|
||||
define if_gez 59
|
||||
define if_gtz 60
|
||||
define if_lez 61
|
||||
define aget 68
|
||||
define aget_wide 69
|
||||
define aget_object 70
|
||||
define aget_boolean 71
|
||||
define aget_byte 72
|
||||
define aget_char 73
|
||||
define aget_short 74
|
||||
define aput 75
|
||||
define aput_wide 76
|
||||
define aput_object 77
|
||||
define aput_boolean 78
|
||||
define aput_byte 79
|
||||
define aput_char 80
|
||||
define aput_short 81
|
||||
define iget 82
|
||||
define iget_wide 83
|
||||
define iget_object 84
|
||||
define iget_boolean 85
|
||||
define iget_byte 86
|
||||
define iget_char 87
|
||||
define iget_short 88
|
||||
define iput 89
|
||||
define iput_wide 90
|
||||
define iput_object 91
|
||||
define iput_boolean 92
|
||||
define iput_byte 93
|
||||
define iput_char 94
|
||||
define iput_short 95
|
||||
define sget 96
|
||||
define sget_wide 97
|
||||
define sget_object 98
|
||||
define sget_boolean 99
|
||||
define sget_byte 100
|
||||
define sget_char 101
|
||||
define sget_short 102
|
||||
define sput 103
|
||||
define sput_wide 104
|
||||
define sput_object 105
|
||||
define sput_boolean 106
|
||||
define sput_byte 107
|
||||
define sput_char 108
|
||||
define sput_short 109
|
||||
define invoke_virtual 110
|
||||
define invoke_super 111
|
||||
define invoke_direct 112
|
||||
define invoke_static 113
|
||||
define invoke_interface 114
|
||||
define invoke_virtual_range 116
|
||||
define invoke_super_range 117
|
||||
define invoke_direct_range 118
|
||||
define invoke_static_range 119
|
||||
define invoke_interface_range 120
|
||||
define neg_int 123
|
||||
define not_int 124
|
||||
define neg_long 125
|
||||
define not_long 126
|
||||
define neg_float 127
|
||||
define neg_double 128
|
||||
define int_to_long 129
|
||||
define int_to_float 130
|
||||
define int_to_double 131
|
||||
define long_to_int 132
|
||||
define long_to_float 133
|
||||
define long_to_double 134
|
||||
define float_to_int 135
|
||||
define float_to_long 136
|
||||
define float_to_double 137
|
||||
define double_to_int 138
|
||||
define double_to_long 139
|
||||
define double_to_float 140
|
||||
define int_to_byte 141
|
||||
define int_to_char 142
|
||||
define int_to_short 143
|
||||
define add_int 144
|
||||
define sub_int 145
|
||||
define mul_int 146
|
||||
define div_int 147
|
||||
define rem_int 148
|
||||
define and_int 149
|
||||
define or_int 150
|
||||
define xor_int 151
|
||||
define shl_int 152
|
||||
define shr_int 153
|
||||
define ushr_int 154
|
||||
define add_long 155
|
||||
define sub_long 156
|
||||
define mul_long 157
|
||||
define div_long 158
|
||||
define rem_long 159
|
||||
define and_long 160
|
||||
define or_long 161
|
||||
define xor_long 162
|
||||
define shl_long 163
|
||||
define shr_long 164
|
||||
define ushr_long 165
|
||||
define add_float 166
|
||||
define sub_float 167
|
||||
define mul_float 168
|
||||
define div_float 169
|
||||
define rem_float 170
|
||||
define add_double 171
|
||||
define sub_double 172
|
||||
define mul_double 173
|
||||
define div_double 174
|
||||
define rem_double 175
|
||||
define add_int_2addr 176
|
||||
define sub_int_2addr 177
|
||||
define mul_int_2addr 178
|
||||
define div_int_2addr 179
|
||||
define rem_int_2addr 180
|
||||
define and_int_2addr 181
|
||||
define or_int_2addr 182
|
||||
define xor_int_2addr 183
|
||||
define shl_int_2addr 184
|
||||
define shr_int_2addr 185
|
||||
define ushr_int_2addr 186
|
||||
define add_long_2addr 187
|
||||
define sub_long_2addr 188
|
||||
define mul_long_2addr 189
|
||||
define div_long_2addr 190
|
||||
define rem_long_2addr 191
|
||||
define and_long_2addr 192
|
||||
define or_long_2addr 193
|
||||
define xor_long_2addr 194
|
||||
define shl_long_2addr 195
|
||||
define shr_long_2addr 196
|
||||
define ushr_long_2addr 197
|
||||
define add_float_2addr 198
|
||||
define sub_float_2addr 199
|
||||
define mul_float_2addr 200
|
||||
define div_float_2addr 201
|
||||
define rem_float_2addr 202
|
||||
define add_double_2addr 203
|
||||
define sub_double_2addr 204
|
||||
define mul_double_2addr 205
|
||||
define div_double_2addr 206
|
||||
define rem_double_2addr 207
|
||||
define add_int_lit16 208
|
||||
define rsub_int 209
|
||||
define mul_int_lit16 210
|
||||
define div_int_lit16 211
|
||||
define rem_int_lit16 212
|
||||
define and_int_lit16 213
|
||||
define or_int_lit16 214
|
||||
define xor_int_lit16 215
|
||||
define add_int_lit8 216
|
||||
define rsub_int_lit8 217
|
||||
define mul_int_lit8 218
|
||||
define div_int_lit8 219
|
||||
define rem_int_lit8 220
|
||||
define and_int_lit8 221
|
||||
define or_int_lit8 222
|
||||
define xor_int_lit8 223
|
||||
define shl_int_lit8 224
|
||||
define shr_int_lit8 225
|
||||
define ushr_int_lit8 226
|
||||
define iget_volatile 227
|
||||
define iput_volatile 228
|
||||
define sget_volatile 229
|
||||
define sput_volatile 230
|
||||
define iget_object_volatile 231
|
||||
define iget_wide_volatile 232
|
||||
define iput_wide_volatile 233
|
||||
define sget_wide_volatile 234
|
||||
define sput_wide_volatile 235
|
||||
define throw_verification_error 237
|
||||
define execute_inline 238
|
||||
define execute_inline_range 239
|
||||
define invoke_direct_empty 240
|
||||
define invoke_object_init_range 240
|
||||
define return_void_barrier 241
|
||||
define iget_quick 242
|
||||
define iget_wide_quick 243
|
||||
define iget_object_quick 244
|
||||
define iput_quick 245
|
||||
define iput_wide_quick 246
|
||||
define iput_object_quick 247
|
||||
define invoke_virtual_quick 248
|
||||
define invoke_virtual_quick_range 249
|
||||
define invoke_super_quick 250
|
||||
define invoke_super_quick_range 251
|
||||
define iput_object_volatile 252
|
||||
define sget_object_volatile 253
|
||||
define sput_object_volatile 254
|
263
dexlib2/src/main/ragel/SyntheticAccessorFSM.rl
Normal file
263
dexlib2/src/main/ragel/SyntheticAccessorFSM.rl
Normal file
@ -0,0 +1,263 @@
|
||||
/*
|
||||
* Copyright 2012, 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.dexlib2.util;
|
||||
|
||||
import org.jf.dexlib2.iface.instruction.Instruction;
|
||||
import org.jf.dexlib2.iface.instruction.formats.Instruction22b;
|
||||
import org.jf.dexlib2.iface.instruction.OneRegisterInstruction;
|
||||
import org.jf.dexlib2.iface.instruction.WideLiteralInstruction;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class SyntheticAccessorFSM {
|
||||
%% machine SyntheticAccessorFSM;
|
||||
%% write data;
|
||||
|
||||
// math type constants
|
||||
public static final int ADD = SyntheticAccessorResolver.ADD_ASSIGNMENT;
|
||||
public static final int SUB = SyntheticAccessorResolver.SUB_ASSIGNMENT;
|
||||
public static final int MUL = SyntheticAccessorResolver.MUL_ASSIGNMENT;
|
||||
public static final int DIV = SyntheticAccessorResolver.DIV_ASSIGNMENT;
|
||||
public static final int REM = SyntheticAccessorResolver.REM_ASSIGNMENT;
|
||||
public static final int AND = SyntheticAccessorResolver.AND_ASSIGNMENT;
|
||||
public static final int OR = SyntheticAccessorResolver.OR_ASSIGNMENT;
|
||||
public static final int XOR = SyntheticAccessorResolver.XOR_ASSIGNMENT;
|
||||
public static final int SHL = SyntheticAccessorResolver.SHL_ASSIGNMENT;
|
||||
public static final int SHR = SyntheticAccessorResolver.SHR_ASSIGNMENT;
|
||||
public static final int USHR = SyntheticAccessorResolver.USHR_ASSIGNMENT;
|
||||
|
||||
public static final int INT = 0;
|
||||
public static final int LONG = 1;
|
||||
public static final int FLOAT = 2;
|
||||
public static final int DOUBLE = 3;
|
||||
|
||||
public static final int POSITIVE_ONE = 1;
|
||||
public static final int NEGATIVE_ONE = -1;
|
||||
public static final int OTHER = 0;
|
||||
|
||||
public static int test(List<? extends Instruction> instructions) {
|
||||
int accessorType = -1;
|
||||
int cs, p = 0;
|
||||
int pe = instructions.size();
|
||||
|
||||
// one of the math type constants representing the type of math operation being performed
|
||||
int mathOp = -1;
|
||||
|
||||
// for increments an decrements, the type of value the math operation is on
|
||||
int mathType = -1;
|
||||
|
||||
// for increments and decrements, the value of the constant that is used
|
||||
long constantValue = 0;
|
||||
|
||||
// The source register for the put instruction
|
||||
int putRegister = -1;
|
||||
// The return register;
|
||||
int returnRegister = -1;
|
||||
|
||||
%%{
|
||||
import "Opcodes.rl";
|
||||
alphtype short;
|
||||
getkey instructions.get(p).getOpcode().value;
|
||||
|
||||
get = (0x52 .. 0x58) | (0x60 .. 0x66); # all igets/sgets
|
||||
|
||||
# all iputs/sputs
|
||||
put = ((0x59 .. 0x5f) | (0x67 .. 0x6d)) @ {
|
||||
putRegister = ((OneRegisterInstruction)instructions.get(p)).getRegisterA();
|
||||
};
|
||||
|
||||
invoke = (0x6e .. 0x72) | (0x74 .. 0x78); # all invokes
|
||||
|
||||
# all numeric const instructions
|
||||
const_literal = (0x12 .. 0x19) @ {
|
||||
constantValue = ((WideLiteralInstruction)instructions.get(p)).getWideLiteral();
|
||||
};
|
||||
|
||||
add_const = (add_int_lit8 | add_int_lit16) @ {
|
||||
mathType = INT;
|
||||
mathOp = ADD;
|
||||
constantValue = ((WideLiteralInstruction)instructions.get(p)).getWideLiteral();
|
||||
};
|
||||
|
||||
arbitrary_add = (((add_int | add_int_2addr) @ { mathType = INT; }) |
|
||||
((add_long | add_long_2addr) @ { mathType = LONG; }) |
|
||||
((add_float | add_float_2addr) @ { mathType = FLOAT; }) |
|
||||
((add_double | add_double_2addr) @ {mathType = DOUBLE; })) @ {
|
||||
mathOp = ADD;
|
||||
};
|
||||
arbitrary_sub = (((sub_int | sub_int_2addr) @ { mathType = INT; }) |
|
||||
((sub_long | sub_long_2addr) @ { mathType = LONG; }) |
|
||||
((sub_float | sub_float_2addr) @ { mathType = FLOAT; }) |
|
||||
((sub_double | sub_double_2addr) @ {mathType = DOUBLE; })) @ {
|
||||
mathOp = SUB;
|
||||
};
|
||||
arbitrary_mul = (mul_int | mul_int_2addr | mul_long | mul_long_2addr |
|
||||
mul_float | mul_float_2addr | mul_double | mul_double_2addr) @ {
|
||||
mathOp = MUL;
|
||||
};
|
||||
arbitrary_div = (div_int | div_int_2addr | div_long | div_long_2addr |
|
||||
div_float | div_float_2addr | div_double | div_double_2addr) @ {
|
||||
mathOp = DIV;
|
||||
};
|
||||
arbitrary_rem = (rem_int | rem_int_2addr | rem_long | rem_long_2addr |
|
||||
rem_float | rem_float_2addr | rem_double | rem_double_2addr) @ {
|
||||
mathOp = REM;
|
||||
};
|
||||
arbitrary_and = (and_int | and_int_2addr | and_long | and_long_2addr) @ {
|
||||
mathOp = AND;
|
||||
};
|
||||
arbitrary_or = (or_int | or_int_2addr | or_long | or_long_2addr) @ {
|
||||
mathOp = OR;
|
||||
};
|
||||
arbitrary_xor = (xor_int | xor_int_2addr | xor_long | xor_long_2addr) @ {
|
||||
mathOp = XOR;
|
||||
};
|
||||
arbitrary_shl = (shl_int | shl_int_2addr | shl_long | shl_long_2addr) @ {
|
||||
mathOp = SHL;
|
||||
};
|
||||
arbitrary_shr = (shr_int | shr_int_2addr | shr_long | shr_long_2addr) @ {
|
||||
mathOp = SHR;
|
||||
};
|
||||
arbitrary_ushr = (ushr_int | ushr_int_2addr | ushr_long | ushr_long_2addr) @ {
|
||||
mathOp = USHR;
|
||||
};
|
||||
|
||||
type_conversion = 0x81 .. 0x8f; # all type-conversion opcodes
|
||||
|
||||
return_something = (return | return_wide | return_object) @ {
|
||||
returnRegister = ((OneRegisterInstruction)instructions.get(p)).getRegisterA();
|
||||
};
|
||||
|
||||
any_move_result = move_result | move_result_wide | move_result_object;
|
||||
|
||||
get_accessor = get return_something @ {
|
||||
accessorType = SyntheticAccessorResolver.GETTER; fbreak;
|
||||
};
|
||||
|
||||
put_accessor = put return_something @ {
|
||||
accessorType = SyntheticAccessorResolver.SETTER; fbreak;
|
||||
};
|
||||
|
||||
invoke_accessor = invoke (return_void | (any_move_result return_something)) @ {
|
||||
accessorType = SyntheticAccessorResolver.METHOD; fbreak;
|
||||
};
|
||||
|
||||
increment_accessor = get add_const type_conversion? put return_something @ {
|
||||
accessorType = getIncrementType(mathOp, mathType, constantValue, putRegister, returnRegister);
|
||||
};
|
||||
|
||||
alt_increment_accessor = get const_literal (arbitrary_add | arbitrary_sub) put return_something @ {
|
||||
accessorType = getIncrementType(mathOp, mathType, constantValue, putRegister, returnRegister);
|
||||
};
|
||||
|
||||
math_assignment_accessor = get type_conversion?
|
||||
(arbitrary_add | arbitrary_sub | arbitrary_mul | arbitrary_div | arbitrary_rem |
|
||||
arbitrary_and | arbitrary_or | arbitrary_xor | arbitrary_shl | arbitrary_shr |
|
||||
arbitrary_ushr)
|
||||
type_conversion{0,2} put return_something @ {
|
||||
accessorType = mathOp; fbreak;
|
||||
};
|
||||
|
||||
main := get_accessor |
|
||||
put_accessor |
|
||||
invoke_accessor |
|
||||
increment_accessor |
|
||||
alt_increment_accessor |
|
||||
math_assignment_accessor;
|
||||
|
||||
write init;
|
||||
write exec;
|
||||
}%%
|
||||
|
||||
return accessorType;
|
||||
}
|
||||
|
||||
private static int getIncrementType(int mathOp, int mathType, long constantValue, int putRegister,
|
||||
int returnRegister) {
|
||||
boolean isPrefix = putRegister == returnRegister;
|
||||
|
||||
boolean negativeConstant = false;
|
||||
|
||||
switch (mathType) {
|
||||
case INT:
|
||||
case LONG: {
|
||||
if (constantValue == 1) {
|
||||
negativeConstant = false;
|
||||
} else if (constantValue == -1) {
|
||||
negativeConstant = true;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case FLOAT: {
|
||||
float val = Float.intBitsToFloat((int)constantValue);
|
||||
if (val == 1) {
|
||||
negativeConstant = false;
|
||||
} else if (val == -1) {
|
||||
negativeConstant = true;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DOUBLE: {
|
||||
double val = Double.longBitsToDouble(constantValue);
|
||||
if (val == 1) {
|
||||
negativeConstant = false;
|
||||
} else if (val == -1) {
|
||||
negativeConstant = true;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
boolean isAdd = ((mathOp == ADD) && !negativeConstant) ||
|
||||
((mathOp == SUB) && negativeConstant);
|
||||
|
||||
if (isPrefix) {
|
||||
if (isAdd) {
|
||||
return SyntheticAccessorResolver.PREFIX_INCREMENT;
|
||||
} else {
|
||||
return SyntheticAccessorResolver.PREFIX_DECREMENT;
|
||||
}
|
||||
} else {
|
||||
if (isAdd) {
|
||||
return SyntheticAccessorResolver.POSTFIX_INCREMENT;
|
||||
} else {
|
||||
return SyntheticAccessorResolver.POSTFIX_DECREMENT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1 +1 @@
|
||||
include 'util', 'dexlib', 'dexlib2', 'baksmali', 'smali'
|
||||
include 'util', 'dexlib', 'dexlib2', 'baksmali', 'smali', 'dexlib2:accessorTestGenerator'
|
Loading…
x
Reference in New Issue
Block a user