Search in sources :

Example 31 with Method

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

the class AnalyzedInstruction method getSetRegisters.

public List<Integer> getSetRegisters() {
    List<Integer> setRegisters = Lists.newArrayList();
    if (instruction.getOpcode().setsRegister()) {
        setRegisters.add(getDestinationRegister());
    }
    if (instruction.getOpcode().setsWideRegister()) {
        setRegisters.add(getDestinationRegister() + 1);
    }
    if (isInvokeInit()) {
        //When constructing a new object, the register type will be an uninitialized reference after the new-instance
        //instruction, but becomes an initialized reference once the <init> method is called. So even though invoke
        //instructions don't normally change any registers, calling an <init> method will change the type of its
        //object register. If the uninitialized reference has been copied to other registers, they will be initialized
        //as well, so we need to check for that too
        int destinationRegister;
        if (instruction instanceof FiveRegisterInstruction) {
            destinationRegister = ((FiveRegisterInstruction) instruction).getRegisterC();
            assert ((FiveRegisterInstruction) instruction).getRegisterCount() > 0;
        } else {
            assert instruction instanceof RegisterRangeInstruction;
            RegisterRangeInstruction rangeInstruction = (RegisterRangeInstruction) instruction;
            assert rangeInstruction.getRegisterCount() > 0;
            destinationRegister = rangeInstruction.getStartRegister();
        }
        RegisterType preInstructionDestRegisterType = getPreInstructionRegisterType(destinationRegister);
        if (preInstructionDestRegisterType.category == RegisterType.UNINIT_REF || preInstructionDestRegisterType.category == RegisterType.UNINIT_THIS) {
            setRegisters.add(destinationRegister);
            RegisterType objectRegisterType = preRegisterMap[destinationRegister];
            for (int i = 0; i < preRegisterMap.length; i++) {
                if (i == destinationRegister) {
                    continue;
                }
                RegisterType preInstructionRegisterType = preRegisterMap[i];
                if (preInstructionRegisterType.equals(objectRegisterType)) {
                    setRegisters.add(i);
                } else if (preInstructionRegisterType.category == RegisterType.UNINIT_REF || preInstructionRegisterType.category == RegisterType.UNINIT_THIS) {
                    RegisterType postInstructionRegisterType = postRegisterMap[i];
                    if (postInstructionRegisterType.category == RegisterType.UNKNOWN) {
                        setRegisters.add(i);
                    }
                }
            }
        } else if (preInstructionDestRegisterType.category == RegisterType.UNKNOWN) {
            for (int i = 0; i < preRegisterMap.length; i++) {
                RegisterType registerType = preRegisterMap[i];
                if (registerType.category == RegisterType.UNINIT_REF || registerType.category == RegisterType.UNINIT_THIS) {
                    setRegisters.add(i);
                }
            }
        }
    }
    // branch of the following if-eqz/if-nez
    if (instructionIndex > 0 && methodAnalyzer.getClassPath().isArt() && getPredecessorCount() == 1 && (instruction.getOpcode() == Opcode.IF_EQZ || instruction.getOpcode() == Opcode.IF_NEZ)) {
        AnalyzedInstruction prevInstruction = predecessors.first();
        if (prevInstruction.instruction.getOpcode() == Opcode.INSTANCE_OF && MethodAnalyzer.canPropagateTypeAfterInstanceOf(prevInstruction, this, methodAnalyzer.getClassPath())) {
            Instruction22c instanceOfInstruction = (Instruction22c) prevInstruction.instruction;
            setRegisters.add(instanceOfInstruction.getRegisterB());
            // TODO: do we need to do some sort of additional check that these multiple move-object predecessors actually refer to the same value?
            if (instructionIndex > 1) {
                int originalSourceRegister = -1;
                RegisterType newType = null;
                for (AnalyzedInstruction prevPrevAnalyzedInstruction : prevInstruction.predecessors) {
                    Opcode opcode = prevPrevAnalyzedInstruction.instruction.getOpcode();
                    if (opcode == Opcode.MOVE_OBJECT || opcode == Opcode.MOVE_OBJECT_16 || opcode == Opcode.MOVE_OBJECT_FROM16) {
                        TwoRegisterInstruction moveInstruction = ((TwoRegisterInstruction) prevPrevAnalyzedInstruction.instruction);
                        RegisterType originalType = prevPrevAnalyzedInstruction.getPostInstructionRegisterType(moveInstruction.getRegisterB());
                        if (moveInstruction.getRegisterA() != instanceOfInstruction.getRegisterB()) {
                            originalSourceRegister = -1;
                            break;
                        }
                        if (originalType.type == null) {
                            originalSourceRegister = -1;
                            break;
                        }
                        if (newType == null) {
                            newType = RegisterType.getRegisterType(methodAnalyzer.getClassPath(), (TypeReference) instanceOfInstruction.getReference());
                        }
                        if (MethodAnalyzer.isNotWideningConversion(originalType, newType)) {
                            if (originalSourceRegister != -1) {
                                if (originalSourceRegister != moveInstruction.getRegisterB()) {
                                    originalSourceRegister = -1;
                                    break;
                                }
                            } else {
                                originalSourceRegister = moveInstruction.getRegisterB();
                            }
                        }
                    } else {
                        originalSourceRegister = -1;
                        break;
                    }
                }
                if (originalSourceRegister != -1) {
                    setRegisters.add(originalSourceRegister);
                }
            }
        }
    }
    return setRegisters;
}
Also used : Instruction22c(org.jf.dexlib2.iface.instruction.formats.Instruction22c) Opcode(org.jf.dexlib2.Opcode) TypeReference(org.jf.dexlib2.iface.reference.TypeReference)

Example 32 with Method

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

the class AnalyzedMethodUtil method canAccess.

public static boolean canAccess(@Nonnull TypeProto type, @Nonnull Method virtualMethod, boolean checkPackagePrivate, boolean checkProtected, boolean checkClass) {
    if (checkPackagePrivate && MethodUtil.isPackagePrivate(virtualMethod)) {
        String otherPackage = TypeUtils.getPackage(virtualMethod.getDefiningClass());
        String thisPackage = TypeUtils.getPackage(type.getType());
        if (!otherPackage.equals(thisPackage)) {
            return false;
        }
    }
    if (checkProtected && (virtualMethod.getAccessFlags() & AccessFlags.PROTECTED.getValue()) != 0) {
        if (!TypeProtoUtils.extendsFrom(type, virtualMethod.getDefiningClass())) {
            return false;
        }
    }
    if (checkClass) {
        ClassPath classPath = type.getClassPath();
        ClassDef methodClassDef = classPath.getClassDef(virtualMethod.getDefiningClass());
        if (!TypeUtils.canAccessClass(type.getType(), methodClassDef)) {
            return false;
        }
    }
    return true;
}
Also used : ClassDef(org.jf.dexlib2.iface.ClassDef)

Example 33 with Method

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

the class CustomInlineMethodResolver method resolveExecuteInline.

@Override
@Nonnull
public Method resolveExecuteInline(@Nonnull AnalyzedInstruction analyzedInstruction) {
    InlineIndexInstruction instruction = (InlineIndexInstruction) analyzedInstruction.instruction;
    int methodIndex = instruction.getInlineIndex();
    if (methodIndex < 0 || methodIndex >= inlineMethods.length) {
        throw new RuntimeException("Invalid method index: " + methodIndex);
    }
    return inlineMethods[methodIndex];
}
Also used : InlineIndexInstruction(org.jf.dexlib2.iface.instruction.InlineIndexInstruction) Nonnull(javax.annotation.Nonnull)

Example 34 with Method

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

the class ListVtablesCommand method listClassVtable.

private void listClassVtable(ClassProto classProto) throws IOException {
    List<Method> methods = classProto.getVtable();
    String className = "Class " + classProto.getType() + " extends " + classProto.getSuperclass() + " : " + methods.size() + " methods\n";
    System.out.write(className.getBytes());
    for (int i = 0; i < methods.size(); i++) {
        Method method = methods.get(i);
        String methodString = i + ":" + method.getDefiningClass() + "->" + method.getName() + "(";
        for (CharSequence parameter : method.getParameterTypes()) {
            methodString += parameter;
        }
        methodString += ")" + method.getReturnType() + "\n";
        System.out.write(methodString.getBytes());
    }
    System.out.write("\n".getBytes());
}
Also used : Method(org.jf.dexlib2.iface.Method)

Example 35 with Method

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

the class ClassDefinition method writeDirectMethods.

private Set<String> writeDirectMethods(IndentingWriter 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 = ReferenceUtil.getMethodDescriptor(method, true);
        IndentingWriter methodWriter = writer;
        if (!writtenMethods.add(methodString)) {
            writer.write("# duplicate method ignored\n");
            methodWriter = new CommentingIndentingWriter(writer);
        }
        MethodImplementation methodImpl = method.getImplementation();
        if (methodImpl == null) {
            MethodDefinition.writeEmptyMethodTo(methodWriter, method, options);
        } else {
            MethodDefinition methodDefinition = new MethodDefinition(this, method, methodImpl);
            methodDefinition.writeTo(methodWriter);
        }
    }
    return writtenMethods;
}
Also used : IndentingWriter(org.jf.util.IndentingWriter) DexBackedClassDef(org.jf.dexlib2.dexbacked.DexBackedClassDef)

Aggregations

ClassDef (org.jf.dexlib2.iface.ClassDef)21 Method (org.jf.dexlib2.iface.Method)21 MethodImplementation (org.jf.dexlib2.iface.MethodImplementation)19 Test (org.junit.Test)16 Instruction (org.jf.dexlib2.iface.instruction.Instruction)15 DexFile (org.jf.dexlib2.iface.DexFile)13 ImmutableMethod (org.jf.dexlib2.immutable.ImmutableMethod)13 ImmutableClassDef (org.jf.dexlib2.immutable.ImmutableClassDef)11 ImmutableDexFile (org.jf.dexlib2.immutable.ImmutableDexFile)10 MethodImplementationBuilder (org.jf.dexlib2.builder.MethodImplementationBuilder)7 MutableMethodImplementation (org.jf.dexlib2.builder.MutableMethodImplementation)7 BuilderInstruction10x (org.jf.dexlib2.builder.instruction.BuilderInstruction10x)7 DexBackedClassDef (org.jf.dexlib2.dexbacked.DexBackedClassDef)7 ImmutableMethodParameter (org.jf.dexlib2.immutable.ImmutableMethodParameter)7 Nonnull (javax.annotation.Nonnull)6 Opcode (org.jf.dexlib2.Opcode)6 BuilderInstruction21t (org.jf.dexlib2.builder.instruction.BuilderInstruction21t)6 BuilderInstruction22c (org.jf.dexlib2.builder.instruction.BuilderInstruction22c)6 ReferenceInstruction (org.jf.dexlib2.iface.instruction.ReferenceInstruction)6 MethodReference (org.jf.dexlib2.iface.reference.MethodReference)6