Search in sources :

Example 91 with Method

use of org.jf.dexlib2.iface.Method in project smali by JesusFreke.

the class CustomMethodInlineTableTest method testCustomMethodInlineTable_Virtual.

@Test
public void testCustomMethodInlineTable_Virtual() throws IOException {
    List<ImmutableInstruction> instructions = Lists.newArrayList(new ImmutableInstruction35mi(Opcode.EXECUTE_INLINE, 1, 0, 0, 0, 0, 0, 0), new ImmutableInstruction10x(Opcode.RETURN_VOID));
    ImmutableMethodImplementation methodImpl = new ImmutableMethodImplementation(1, instructions, null, null);
    ImmutableMethod method = new ImmutableMethod("Lblah;", "blah", null, "V", AccessFlags.PUBLIC.getValue(), null, null, methodImpl);
    ClassDef classDef = new ImmutableClassDef("Lblah;", AccessFlags.PUBLIC.getValue(), "Ljava/lang/Object;", null, null, null, null, null, null, ImmutableList.of(method));
    ImmutableDexFile dexFile = new ImmutableDexFile(Opcodes.getDefault(), ImmutableList.of(classDef));
    ImmutableMultiDexContainer container = new ImmutableMultiDexContainer(ImmutableMap.of("classes.dex", dexFile));
    ClassPathResolver resolver = new ClassPathResolver(ImmutableList.<String>of(), ImmutableList.<String>of(), ImmutableList.<String>of(), container.getEntry("classes.dex"));
    ClassPath classPath = new ClassPath(resolver.getResolvedClassProviders(), false, ClassPath.NOT_ART);
    InlineMethodResolver inlineMethodResolver = new CustomInlineMethodResolver(classPath, "Lblah;->blah()V");
    MethodAnalyzer methodAnalyzer = new MethodAnalyzer(classPath, method, inlineMethodResolver, false);
    Instruction deodexedInstruction = methodAnalyzer.getInstructions().get(0);
    Assert.assertEquals(Opcode.INVOKE_VIRTUAL, deodexedInstruction.getOpcode());
    MethodReference methodReference = (MethodReference) ((Instruction35c) deodexedInstruction).getReference();
    Assert.assertEquals(method, methodReference);
}
Also used : Instruction(org.jf.dexlib2.iface.instruction.Instruction) ImmutableInstruction(org.jf.dexlib2.immutable.instruction.ImmutableInstruction) ImmutableInstruction10x(org.jf.dexlib2.immutable.instruction.ImmutableInstruction10x) ImmutableInstruction35mi(org.jf.dexlib2.immutable.instruction.ImmutableInstruction35mi) ClassDef(org.jf.dexlib2.iface.ClassDef) ImmutableInstruction(org.jf.dexlib2.immutable.instruction.ImmutableInstruction) MethodReference(org.jf.dexlib2.iface.reference.MethodReference) Test(org.junit.Test)

Example 92 with Method

use of org.jf.dexlib2.iface.Method in project smali by JesusFreke.

the class ImplicitReferenceTest method testImplicitMethodReference.

@Test
public void testImplicitMethodReference() throws RecognitionException, IOException {
    ClassDef classDef = SmaliTestUtils.compileSmali("" + ".class public LHelloWorld;\n" + ".super Ljava/lang/Object;\n" + ".method public static main([Ljava/lang/String;)V\n" + "    .registers 1\n" + "    invoke-static {p0}, toString()V\n" + "    invoke-static {p0}, V()V\n" + "    invoke-static {p0}, I()V\n" + "    return-void\n" + ".end method");
    Method mainMethod = null;
    for (Method method : classDef.getMethods()) {
        if (method.getName().equals("main")) {
            mainMethod = method;
        }
    }
    Assert.assertNotNull(mainMethod);
    MethodImplementation methodImpl = mainMethod.getImplementation();
    Assert.assertNotNull(methodImpl);
    List<Instruction> instructions = Lists.newArrayList(methodImpl.getInstructions());
    Instruction35c instruction = (Instruction35c) instructions.get(0);
    Assert.assertNotNull(instruction);
    Assert.assertEquals(Opcode.INVOKE_STATIC, instruction.getOpcode());
    MethodReference method = (MethodReference) instruction.getReference();
    Assert.assertEquals(classDef.getType(), method.getDefiningClass());
    Assert.assertEquals("toString", method.getName());
    instruction = (Instruction35c) instructions.get(1);
    Assert.assertNotNull(instruction);
    Assert.assertEquals(Opcode.INVOKE_STATIC, instruction.getOpcode());
    method = (MethodReference) instruction.getReference();
    Assert.assertEquals(classDef.getType(), method.getDefiningClass());
    Assert.assertEquals("V", method.getName());
    instruction = (Instruction35c) instructions.get(2);
    Assert.assertNotNull(instruction);
    Assert.assertEquals(Opcode.INVOKE_STATIC, instruction.getOpcode());
    method = (MethodReference) instruction.getReference();
    Assert.assertEquals(classDef.getType(), method.getDefiningClass());
    Assert.assertEquals("I", method.getName());
}
Also used : MethodImplementation(org.jf.dexlib2.iface.MethodImplementation) ClassDef(org.jf.dexlib2.iface.ClassDef) Instruction35c(org.jf.dexlib2.iface.instruction.formats.Instruction35c) MethodReference(org.jf.dexlib2.iface.reference.MethodReference) Method(org.jf.dexlib2.iface.Method) Instruction(org.jf.dexlib2.iface.instruction.Instruction) Test(org.junit.Test)

Example 93 with Method

use of org.jf.dexlib2.iface.Method in project tinker by Tencent.

the class BuilderMutableMethodImplementation method fixInstructions.

private void fixInstructions() {
    HashSet<MethodLocation> payloadLocations = Sets.newHashSet();
    for (MethodLocation location : instructionList) {
        BuilderInstruction instruction = location.instruction;
        if (instruction != null) {
            switch(instruction.getOpcode()) {
                case SPARSE_SWITCH:
                case PACKED_SWITCH:
                    {
                        MethodLocation targetLocation = ((BuilderOffsetInstruction) instruction).getTarget().getLocation();
                        BuilderInstruction targetInstruction = targetLocation.instruction;
                        if (targetInstruction == null) {
                            throw new IllegalStateException(String.format("Switch instruction at address/index " + "0x%x/%d points to the end of the method.", location.codeAddress, location.index));
                        }
                        if (targetInstruction.getOpcode() == Opcode.NOP) {
                            targetInstruction = getFirstNonNop(targetLocation.index + 1);
                        }
                        if (targetInstruction == null || !(targetInstruction instanceof BuilderSwitchPayload)) {
                            throw new IllegalStateException(String.format("Switch instruction at address/index " + "0x%x/%d does not refer to a payload instruction.", location.codeAddress, location.index));
                        }
                        if ((instruction.opcode == Opcode.PACKED_SWITCH && targetInstruction.getOpcode() != Opcode.PACKED_SWITCH_PAYLOAD) || (instruction.opcode == Opcode.SPARSE_SWITCH && targetInstruction.getOpcode() != Opcode.SPARSE_SWITCH_PAYLOAD)) {
                            throw new IllegalStateException(String.format("Switch instruction at address/index " + "0x%x/%d refers to the wrong type of payload instruction.", location.codeAddress, location.index));
                        }
                        if (!payloadLocations.add(targetLocation)) {
                            throw new IllegalStateException("Multiple switch instructions refer to the same payload. " + "This is not currently supported. Please file a bug :)");
                        }
                        ((BuilderSwitchPayload) targetInstruction).referrer = location;
                        break;
                    }
                default:
                    {
                        break;
                    }
            }
        }
    }
    boolean madeChanges;
    do {
        madeChanges = false;
        for (int index = 0; index < instructionList.size(); index++) {
            MethodLocation location = instructionList.get(index);
            BuilderInstruction instruction = location.instruction;
            if (instruction != null) {
                switch(instruction.getOpcode()) {
                    case GOTO:
                        {
                            int offset = ((BuilderOffsetInstruction) instruction).internalGetCodeOffset();
                            if (offset < Byte.MIN_VALUE || offset > Byte.MAX_VALUE) {
                                BuilderOffsetInstruction replacement;
                                if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE) {
                                    replacement = new BuilderInstruction30t(Opcode.GOTO_32, ((BuilderOffsetInstruction) instruction).getTarget());
                                } else {
                                    replacement = new BuilderInstruction20t(Opcode.GOTO_16, ((BuilderOffsetInstruction) instruction).getTarget());
                                }
                                replaceInstruction(location.index, replacement);
                                madeChanges = true;
                            }
                            break;
                        }
                    case GOTO_16:
                        {
                            int offset = ((BuilderOffsetInstruction) instruction).internalGetCodeOffset();
                            if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE) {
                                BuilderOffsetInstruction replacement = new BuilderInstruction30t(Opcode.GOTO_32, ((BuilderOffsetInstruction) instruction).getTarget());
                                replaceInstruction(location.index, replacement);
                                madeChanges = true;
                            }
                            break;
                        }
                    case SPARSE_SWITCH_PAYLOAD:
                    case PACKED_SWITCH_PAYLOAD:
                        if (((BuilderSwitchPayload) instruction).referrer == null) {
                            // if the switch payload isn't referenced, just remove it
                            removeInstruction(index);
                            index--;
                            madeChanges = true;
                            break;
                        }
                    // intentional fall-through
                    case ARRAY_PAYLOAD:
                        {
                            if ((location.codeAddress & 0x01) != 0) {
                                int previousIndex = location.index - 1;
                                MethodLocation previousLocation = instructionList.get(previousIndex);
                                Instruction previousInstruction = previousLocation.instruction;
                                assert previousInstruction != null;
                                if (previousInstruction.getOpcode() == Opcode.NOP) {
                                    removeInstruction(previousIndex);
                                    index--;
                                } else {
                                    addInstruction(location.index, new BuilderInstruction10x(Opcode.NOP));
                                    index++;
                                }
                                madeChanges = true;
                            }
                            break;
                        }
                    default:
                        {
                            break;
                        }
                }
            }
        }
    } while (madeChanges);
    fixInstructions = false;
}
Also used : BuilderInstruction10x(org.jf.dexlib2.builder.instruction.BuilderInstruction10x) BuilderInstruction20t(org.jf.dexlib2.builder.instruction.BuilderInstruction20t) BuilderInstruction30t(org.jf.dexlib2.builder.instruction.BuilderInstruction30t) Instruction(org.jf.dexlib2.iface.instruction.Instruction)

Example 94 with Method

use of org.jf.dexlib2.iface.Method in project smali by JesusFreke.

the class ClassDefinition method writeDirectMethods.

private Set<String> writeDirectMethods(BaksmaliWriter writer) throws IOException {
    boolean wroteHeader = false;
    Set<String> writtenMethods = new HashSet<String>();
    Iterable<? extends Method> directMethods;
    if (classDef instanceof DexBackedClassDef) {
        directMethods = ((DexBackedClassDef) classDef).getDirectMethods(false);
    } else {
        directMethods = classDef.getDirectMethods();
    }
    for (Method method : directMethods) {
        if (!wroteHeader) {
            writer.write("\n\n");
            writer.write("# direct 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);
        }
        MethodImplementation methodImpl = method.getImplementation();
        if (methodImpl == null) {
            MethodDefinition.writeEmptyMethodTo(methodWriter, method, this);
        } else {
            MethodDefinition methodDefinition = new MethodDefinition(this, method, methodImpl);
            methodDefinition.writeTo(methodWriter);
        }
    }
    return writtenMethods;
}
Also used : BaksmaliWriter(org.jf.baksmali.formatter.BaksmaliWriter) DexBackedClassDef(org.jf.dexlib2.dexbacked.DexBackedClassDef) HashSet(java.util.HashSet)

Example 95 with Method

use of org.jf.dexlib2.iface.Method in project smali by JesusFreke.

the class DexBackedMethod method getSize.

/**
 * Calculate and return the private size of a method definition.
 *
 * Calculated as: method_idx_diff + access_flags + code_off +
 * implementation size + reference size
 *
 * @return size in bytes
 */
public int getSize() {
    int size = 0;
    DexReader reader = dexFile.getDataBuffer().readerAt(startOffset);
    // method_idx_diff
    reader.readLargeUleb128();
    // access_flags
    reader.readSmallUleb128();
    // code_off
    reader.readSmallUleb128();
    size += reader.getOffset() - startOffset;
    DexBackedMethodImplementation impl = getImplementation();
    if (impl != null) {
        size += impl.getSize();
    }
    DexBackedMethodReference methodRef = new DexBackedMethodReference(dexFile, methodIndex);
    size += methodRef.getSize();
    return size;
}
Also used : DexBackedMethodReference(org.jf.dexlib2.dexbacked.reference.DexBackedMethodReference)

Aggregations

Method (org.jf.dexlib2.iface.Method)30 ClassDef (org.jf.dexlib2.iface.ClassDef)27 MethodImplementation (org.jf.dexlib2.iface.MethodImplementation)23 Test (org.junit.Test)21 Instruction (org.jf.dexlib2.iface.instruction.Instruction)19 MethodReference (org.jf.dexlib2.iface.reference.MethodReference)18 DexFile (org.jf.dexlib2.iface.DexFile)16 ImmutableMethod (org.jf.dexlib2.immutable.ImmutableMethod)15 DexBackedClassDef (org.jf.dexlib2.dexbacked.DexBackedClassDef)13 ArrayList (java.util.ArrayList)12 ImmutableClassDef (org.jf.dexlib2.immutable.ImmutableClassDef)12 MutableMethodImplementation (org.jf.dexlib2.builder.MutableMethodImplementation)10 ImmutableDexFile (org.jf.dexlib2.immutable.ImmutableDexFile)10 HashSet (java.util.HashSet)9 Nonnull (javax.annotation.Nonnull)9 BuilderInstruction10x (org.jf.dexlib2.builder.instruction.BuilderInstruction10x)8 ReferenceInstruction (org.jf.dexlib2.iface.instruction.ReferenceInstruction)8 ImmutableMethodParameter (org.jf.dexlib2.immutable.ImmutableMethodParameter)8 ImmutableMethodReference (org.jf.dexlib2.immutable.reference.ImmutableMethodReference)8 File (java.io.File)7