use of org.jf.dexlib2.iface.MethodImplementation in project smali by JesusFreke.
the class ClassDefinition method writeVirtualMethods.
private void writeVirtualMethods(BaksmaliWriter writer, Set<String> directMethods) throws IOException {
boolean wroteHeader = false;
Set<String> writtenMethods = new HashSet<String>();
Iterable<? extends Method> virtualMethods;
if (classDef instanceof DexBackedClassDef) {
virtualMethods = ((DexBackedClassDef) classDef).getVirtualMethods(false);
} else {
virtualMethods = classDef.getVirtualMethods();
}
for (Method method : virtualMethods) {
if (!wroteHeader) {
writer.write("\n\n");
writer.write("# virtual methods");
wroteHeader = true;
}
writer.write('\n');
// TODO: check for method validation errors
String methodString = formatter.getShortMethodDescriptor(method);
BaksmaliWriter methodWriter = writer;
if (!writtenMethods.add(methodString)) {
writer.write("# duplicate method ignored\n");
methodWriter = getCommentingWriter(writer);
} else if (directMethods.contains(methodString)) {
writer.write("# There is both a direct and virtual method with this signature.\n" + "# You will need to rename one of these methods, including all references.\n");
System.err.println(String.format("Duplicate direct+virtual method found: %s->%s", classDef.getType(), methodString));
System.err.println("You will need to rename one of these methods, including all references.");
}
MethodImplementation methodImpl = method.getImplementation();
if (methodImpl == null) {
MethodDefinition.writeEmptyMethodTo(methodWriter, method, this);
} else {
MethodDefinition methodDefinition = new MethodDefinition(this, method, methodImpl);
methodDefinition.writeTo(methodWriter);
}
}
}
use of org.jf.dexlib2.iface.MethodImplementation in project smali by JesusFreke.
the class SyntheticAccessorResolver method getAccessedMember.
@Nullable
public AccessedMember getAccessedMember(@Nonnull MethodReference methodReference) {
AccessedMember accessedMember = resolvedAccessors.get(methodReference);
if (accessedMember != null) {
return accessedMember;
}
String type = methodReference.getDefiningClass();
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);
if (accessType >= 0) {
AccessedMember member = new AccessedMember(accessType, ((ReferenceInstruction) instructions.get(0)).getReference());
resolvedAccessors.put(methodReference, member);
return member;
}
return null;
}
use of org.jf.dexlib2.iface.MethodImplementation in project smali by JesusFreke.
the class FixOffsetsTest method testFixOffsets.
@Test
public void testFixOffsets() {
MethodImplementationBuilder builder = new MethodImplementationBuilder(1);
Label firstGotoTarget = builder.getLabel("firstGotoTarget");
builder.addInstruction(new BuilderInstruction10t(Opcode.GOTO, firstGotoTarget));
builder.addLineNumber(1);
for (int i = 0; i < 250; i++) {
builder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
}
builder.addLabel("tryStart");
builder.addLineNumber(2);
for (int i = 0; i < 250; i++) {
builder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
}
builder.addLineNumber(3);
Label secondGotoTarget = builder.getLabel("secondGotoTarget");
builder.addInstruction(new BuilderInstruction10t(Opcode.GOTO, secondGotoTarget));
builder.addLineNumber(4);
builder.addLabel("handler");
for (int i = 0; i < 500; i++) {
builder.addInstruction(new BuilderInstruction10x(Opcode.NOP));
}
builder.addLineNumber(5);
builder.addLabel("tryEnd");
builder.addLabel("firstGotoTarget");
builder.addLabel("secondGotoTarget");
builder.addInstruction(new BuilderInstruction10x(Opcode.RETURN_VOID));
Label tryStart = builder.getLabel("tryStart");
Label tryEnd = builder.getLabel("tryEnd");
Label handler = builder.getLabel("handler");
builder.addCatch(tryStart, tryEnd, handler);
MethodImplementation impl = builder.getMethodImplementation();
List<? extends Instruction> instructions = Lists.newArrayList(impl.getInstructions());
Assert.assertEquals(1003, instructions.size());
Assert.assertEquals(Opcode.GOTO_16, instructions.get(0).getOpcode());
Assert.assertEquals(1004, ((OffsetInstruction) instructions.get(0)).getCodeOffset());
Assert.assertEquals(Opcode.GOTO_16, instructions.get(501).getOpcode());
Assert.assertEquals(502, ((OffsetInstruction) instructions.get(501)).getCodeOffset());
List<? extends TryBlock<? extends ExceptionHandler>> exceptionHandlers = impl.getTryBlocks();
Assert.assertEquals(1, exceptionHandlers.size());
Assert.assertEquals(252, exceptionHandlers.get(0).getStartCodeAddress());
Assert.assertEquals(752, exceptionHandlers.get(0).getCodeUnitCount());
Assert.assertEquals(1, exceptionHandlers.get(0).getExceptionHandlers().size());
ExceptionHandler exceptionHandler = exceptionHandlers.get(0).getExceptionHandlers().get(0);
Assert.assertEquals(504, exceptionHandler.getHandlerCodeAddress());
List<DebugItem> debugItems = Lists.newArrayList(impl.getDebugItems());
Assert.assertEquals(5, debugItems.size());
Assert.assertEquals(1, ((LineNumber) debugItems.get(0)).getLineNumber());
Assert.assertEquals(2, debugItems.get(0).getCodeAddress());
Assert.assertEquals(2, ((LineNumber) debugItems.get(1)).getLineNumber());
Assert.assertEquals(252, debugItems.get(1).getCodeAddress());
Assert.assertEquals(3, ((LineNumber) debugItems.get(2)).getLineNumber());
Assert.assertEquals(502, debugItems.get(2).getCodeAddress());
Assert.assertEquals(4, ((LineNumber) debugItems.get(3)).getLineNumber());
Assert.assertEquals(504, debugItems.get(3).getCodeAddress());
Assert.assertEquals(5, ((LineNumber) debugItems.get(4)).getLineNumber());
Assert.assertEquals(1004, debugItems.get(4).getCodeAddress());
}
use of org.jf.dexlib2.iface.MethodImplementation in project smali by JesusFreke.
the class MethodAnalyzerTest method testInstanceOfNarrowingNez_dalvik.
@Test
public void testInstanceOfNarrowingNez_dalvik() throws IOException {
MethodImplementationBuilder builder = new MethodImplementationBuilder(2);
builder.addInstruction(new BuilderInstruction22c(Opcode.INSTANCE_OF, 0, 1, new ImmutableTypeReference("Lmain;")));
builder.addInstruction(new BuilderInstruction21t(Opcode.IF_NEZ, 0, builder.getLabel("instance_of")));
builder.addInstruction(new BuilderInstruction10x(Opcode.RETURN_VOID));
builder.addLabel("instance_of");
builder.addInstruction(new BuilderInstruction10x(Opcode.RETURN_VOID));
MethodImplementation methodImplementation = builder.getMethodImplementation();
Method method = new ImmutableMethod("Lmain;", "narrowing", Collections.singletonList(new ImmutableMethodParameter("Ljava/lang/Object;", null, null)), "V", AccessFlags.PUBLIC.getValue(), null, null, methodImplementation);
ClassDef classDef = new ImmutableClassDef("Lmain;", AccessFlags.PUBLIC.getValue(), "Ljava/lang/Object;", null, null, null, null, Collections.singletonList(method));
DexFile dexFile = new ImmutableDexFile(Opcodes.getDefault(), Collections.singletonList(classDef));
ClassPath classPath = new ClassPath(new DexClassProvider(dexFile));
MethodAnalyzer methodAnalyzer = new MethodAnalyzer(classPath, method, null, false);
List<AnalyzedInstruction> analyzedInstructions = methodAnalyzer.getAnalyzedInstructions();
Assert.assertEquals("Ljava/lang/Object;", analyzedInstructions.get(2).getPreInstructionRegisterType(1).type.getType());
Assert.assertEquals("Ljava/lang/Object;", analyzedInstructions.get(3).getPreInstructionRegisterType(1).type.getType());
}
use of org.jf.dexlib2.iface.MethodImplementation in project smali by JesusFreke.
the class MethodAnalyzerTest method testInstanceOfNarrowingEqz_art.
@Test
public void testInstanceOfNarrowingEqz_art() throws IOException {
MethodImplementationBuilder builder = new MethodImplementationBuilder(2);
builder.addInstruction(new BuilderInstruction22c(Opcode.INSTANCE_OF, 0, 1, new ImmutableTypeReference("Lmain;")));
builder.addInstruction(new BuilderInstruction21t(Opcode.IF_EQZ, 0, builder.getLabel("not_instance_of")));
builder.addInstruction(new BuilderInstruction10x(Opcode.RETURN_VOID));
builder.addLabel("not_instance_of");
builder.addInstruction(new BuilderInstruction10x(Opcode.RETURN_VOID));
MethodImplementation methodImplementation = builder.getMethodImplementation();
Method method = new ImmutableMethod("Lmain;", "narrowing", Collections.singletonList(new ImmutableMethodParameter("Ljava/lang/Object;", null, null)), "V", AccessFlags.PUBLIC.getValue(), null, null, methodImplementation);
ClassDef classDef = new ImmutableClassDef("Lmain;", AccessFlags.PUBLIC.getValue(), "Ljava/lang/Object;", null, null, null, null, Collections.singletonList(method));
DexFile dexFile = new ImmutableDexFile(forArtVersion(56), Collections.singletonList(classDef));
ClassPath classPath = new ClassPath(Lists.newArrayList(new DexClassProvider(dexFile)), true, 56);
MethodAnalyzer methodAnalyzer = new MethodAnalyzer(classPath, method, null, false);
List<AnalyzedInstruction> analyzedInstructions = methodAnalyzer.getAnalyzedInstructions();
Assert.assertEquals("Lmain;", analyzedInstructions.get(2).getPreInstructionRegisterType(1).type.getType());
Assert.assertEquals("Ljava/lang/Object;", analyzedInstructions.get(3).getPreInstructionRegisterType(1).type.getType());
}
Aggregations