Search in sources :

Example 6 with AnalyzedInstruction

use of org.jf.dexlib2.analysis.AnalyzedInstruction in project smali by JesusFreke.

the class PreInstructionRegisterInfoMethodItem method writeFullMerge.

private void writeFullMerge(IndentingWriter writer, int registerNum) throws IOException {
    registerFormatter.writeTo(writer, registerNum);
    writer.write('=');
    analyzedInstruction.getPreInstructionRegisterType(registerNum).writeTo(writer);
    writer.write(":merge{");
    boolean first = true;
    for (AnalyzedInstruction predecessor : analyzedInstruction.getPredecessors()) {
        RegisterType predecessorRegisterType = analyzedInstruction.getPredecessorRegisterType(predecessor, registerNum);
        if (!first) {
            writer.write(',');
        }
        if (predecessor.getInstructionIndex() == -1) {
            //the fake "StartOfMethod" instruction
            writer.write("Start:");
        } else {
            writer.write("0x");
            writer.printUnsignedLongAsHex(methodAnalyzer.getInstructionAddress(predecessor));
            writer.write(':');
        }
        predecessorRegisterType.writeTo(writer);
        first = false;
    }
    writer.write('}');
}
Also used : RegisterType(org.jf.dexlib2.analysis.RegisterType) AnalyzedInstruction(org.jf.dexlib2.analysis.AnalyzedInstruction)

Example 7 with AnalyzedInstruction

use of org.jf.dexlib2.analysis.AnalyzedInstruction in project smali by JesusFreke.

the class MethodDefinition method addAnalyzedInstructionMethodItems.

private void addAnalyzedInstructionMethodItems(List<MethodItem> methodItems) {
    MethodAnalyzer methodAnalyzer = new MethodAnalyzer(classDef.options.classPath, method, classDef.options.inlineResolver, classDef.options.normalizeVirtualMethods);
    AnalysisException analysisException = methodAnalyzer.getAnalysisException();
    if (analysisException != null) {
        // TODO: need to keep track of whether any errors occurred, so we can exit with a non-zero result
        methodItems.add(new CommentMethodItem(String.format("AnalysisException: %s", analysisException.getMessage()), analysisException.codeAddress, Integer.MIN_VALUE));
        analysisException.printStackTrace(System.err);
    }
    List<AnalyzedInstruction> instructions = methodAnalyzer.getAnalyzedInstructions();
    int currentCodeAddress = 0;
    for (int i = 0; i < instructions.size(); i++) {
        AnalyzedInstruction instruction = instructions.get(i);
        MethodItem methodItem = InstructionMethodItemFactory.makeInstructionFormatMethodItem(this, currentCodeAddress, instruction.getInstruction());
        methodItems.add(methodItem);
        if (instruction.getInstruction().getOpcode().format == Format.UnresolvedOdexInstruction) {
            methodItems.add(new CommentedOutMethodItem(InstructionMethodItemFactory.makeInstructionFormatMethodItem(this, currentCodeAddress, instruction.getOriginalInstruction())));
        }
        if (i != instructions.size() - 1) {
            methodItems.add(new BlankMethodItem(currentCodeAddress));
        }
        if (classDef.options.codeOffsets) {
            methodItems.add(new MethodItem(currentCodeAddress) {

                @Override
                public double getSortOrder() {
                    return -1000;
                }

                @Override
                public boolean writeTo(IndentingWriter writer) throws IOException {
                    writer.write("#@");
                    writer.printUnsignedLongAsHex(codeAddress & 0xFFFFFFFFL);
                    return true;
                }
            });
        }
        if (classDef.options.registerInfo != 0 && !instruction.getInstruction().getOpcode().format.isPayloadFormat) {
            methodItems.add(new PreInstructionRegisterInfoMethodItem(classDef.options.registerInfo, methodAnalyzer, registerFormatter, instruction, currentCodeAddress));
            methodItems.add(new PostInstructionRegisterInfoMethodItem(registerFormatter, instruction, currentCodeAddress));
        }
        currentCodeAddress += instruction.getInstruction().getCodeUnits();
    }
}
Also used : DebugMethodItem(org.jf.baksmali.Adaptors.Debug.DebugMethodItem) MethodAnalyzer(org.jf.dexlib2.analysis.MethodAnalyzer) IOException(java.io.IOException) AnalyzedInstruction(org.jf.dexlib2.analysis.AnalyzedInstruction) AnalysisException(org.jf.dexlib2.analysis.AnalysisException) IndentingWriter(org.jf.util.IndentingWriter)

Example 8 with AnalyzedInstruction

use of org.jf.dexlib2.analysis.AnalyzedInstruction 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 9 with AnalyzedInstruction

use of org.jf.dexlib2.analysis.AnalyzedInstruction 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 10 with AnalyzedInstruction

use of org.jf.dexlib2.analysis.AnalyzedInstruction in project smali by JesusFreke.

the class MethodAnalyzer method analyzeNewInstance.

private void analyzeNewInstance(@Nonnull AnalyzedInstruction analyzedInstruction) {
    ReferenceInstruction instruction = (ReferenceInstruction) analyzedInstruction.instruction;
    int register = ((OneRegisterInstruction) analyzedInstruction.instruction).getRegisterA();
    RegisterType destRegisterType = analyzedInstruction.getPostInstructionRegisterType(register);
    if (destRegisterType.category != RegisterType.UNKNOWN) {
        //successors and nothing else needs to be done.
        assert destRegisterType.category == RegisterType.UNINIT_REF;
        return;
    }
    TypeReference typeReference = (TypeReference) instruction.getReference();
    RegisterType classType = RegisterType.getRegisterType(classPath, typeReference);
    setDestinationRegisterTypeAndPropagateChanges(analyzedInstruction, RegisterType.getRegisterType(RegisterType.UNINIT_REF, classType.type));
}
Also used : TypeReference(org.jf.dexlib2.iface.reference.TypeReference)

Aggregations

Opcode (org.jf.dexlib2.Opcode)8 TypeReference (org.jf.dexlib2.iface.reference.TypeReference)7 AnalyzedInstruction (org.jf.dexlib2.analysis.AnalyzedInstruction)6 MethodImplementationBuilder (org.jf.dexlib2.builder.MethodImplementationBuilder)6 BuilderInstruction10x (org.jf.dexlib2.builder.instruction.BuilderInstruction10x)6 BuilderInstruction21t (org.jf.dexlib2.builder.instruction.BuilderInstruction21t)6 BuilderInstruction22c (org.jf.dexlib2.builder.instruction.BuilderInstruction22c)6 ClassDef (org.jf.dexlib2.iface.ClassDef)6 DexFile (org.jf.dexlib2.iface.DexFile)6 Method (org.jf.dexlib2.iface.Method)6 MethodImplementation (org.jf.dexlib2.iface.MethodImplementation)6 ImmutableClassDef (org.jf.dexlib2.immutable.ImmutableClassDef)6 ImmutableDexFile (org.jf.dexlib2.immutable.ImmutableDexFile)6 ImmutableMethod (org.jf.dexlib2.immutable.ImmutableMethod)6 ImmutableMethodParameter (org.jf.dexlib2.immutable.ImmutableMethodParameter)6 ImmutableTypeReference (org.jf.dexlib2.immutable.reference.ImmutableTypeReference)6 Test (org.junit.Test)6 FieldReference (org.jf.dexlib2.iface.reference.FieldReference)5 ImmutableFieldReference (org.jf.dexlib2.immutable.reference.ImmutableFieldReference)5 BaseMethodReference (org.jf.dexlib2.base.reference.BaseMethodReference)4