Search in sources :

Example 21 with Reference

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

the class InstructionMethodItemTest method testInvalidReference.

@Test
public void testInvalidReference() throws IOException {
    Instruction21c instruction = new Instruction21c() {

        @Override
        public int getRegisterA() {
            return 0;
        }

        @Nonnull
        @Override
        public Reference getReference() {
            return new BaseStringReference() {

                @Override
                public void validateReference() throws InvalidReferenceException {
                    throw new InvalidReferenceException("blahblahblah");
                }

                @Nonnull
                @Override
                public String getString() {
                    throw new RuntimeException("invalid reference");
                }
            };
        }

        @Override
        public int getReferenceType() {
            return ReferenceType.STRING;
        }

        @Override
        public Opcode getOpcode() {
            return Opcode.CONST_STRING;
        }

        @Override
        public int getCodeUnits() {
            return Format.Format21c.size / 2;
        }
    };
    MethodImplementation methodImplementation = new MethodImplementation() {

        @Override
        public int getRegisterCount() {
            return 1;
        }

        @Nonnull
        @Override
        public Iterable<? extends Instruction> getInstructions() {
            return ImmutableList.of(instruction);
        }

        @Nonnull
        @Override
        public List<? extends TryBlock<? extends ExceptionHandler>> getTryBlocks() {
            return ImmutableList.of();
        }

        @Nonnull
        @Override
        public Iterable<? extends DebugItem> getDebugItems() {
            return ImmutableList.of();
        }
    };
    Method method = new TestMethod(methodImplementation);
    ClassDefinition classDefinition = new ClassDefinition(new BaksmaliOptions(), new TestClassDef());
    MethodDefinition methodDefinition = new MethodDefinition(classDefinition, method, methodImplementation);
    methodDefinition.registerFormatter = new RegisterFormatter(new BaksmaliOptions(), 1, 0);
    InstructionMethodItem methodItem = new InstructionMethodItem<Instruction21c>(methodDefinition, 0, instruction);
    StringWriter stringWriter = new StringWriter();
    BaksmaliWriter writer = new BaksmaliWriter(stringWriter);
    methodItem.writeTo(writer);
    Assert.assertEquals("#Invalid reference\n#const-string v0, blahblahblah\nnop", stringWriter.toString());
}
Also used : Instruction21c(org.jf.dexlib2.iface.instruction.formats.Instruction21c) ClassDefinition(org.jf.baksmali.Adaptors.ClassDefinition) RegisterFormatter(org.jf.baksmali.Adaptors.RegisterFormatter) BaseStringReference(org.jf.dexlib2.base.reference.BaseStringReference) InstructionMethodItem(org.jf.baksmali.Adaptors.Format.InstructionMethodItem) StringWriter(java.io.StringWriter) MethodDefinition(org.jf.baksmali.Adaptors.MethodDefinition) BaksmaliWriter(org.jf.baksmali.formatter.BaksmaliWriter) Test(org.junit.Test)

Example 22 with Reference

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

the class ListReferencesCommand method run.

@Override
public void run() {
    if (help || inputList == null || inputList.isEmpty()) {
        usage();
        return;
    }
    if (inputList.size() > 1) {
        System.err.println("Too many files specified");
        usage();
        return;
    }
    String input = inputList.get(0);
    loadDexFile(input);
    BaksmaliFormatter formatter = new BaksmaliFormatter();
    for (Reference reference : dexFile.getReferences(referenceType)) {
        System.out.println(formatter.getReference(reference));
    }
}
Also used : Reference(org.jf.dexlib2.iface.reference.Reference) BaksmaliFormatter(org.jf.baksmali.formatter.BaksmaliFormatter)

Example 23 with Reference

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

the class AnalyzedInstruction method setsRegister.

/**
 * Determines if this instruction sets the given register, or alters its type
 *
 * @param registerNumber The register to check
 * @return true if this instruction sets the given register or alters its type
 */
public boolean setsRegister(int registerNumber) {
    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) {
            assert ((FiveRegisterInstruction) instruction).getRegisterCount() > 0;
            destinationRegister = ((FiveRegisterInstruction) instruction).getRegisterC();
        } else {
            assert instruction instanceof RegisterRangeInstruction;
            RegisterRangeInstruction rangeInstruction = (RegisterRangeInstruction) instruction;
            assert rangeInstruction.getRegisterCount() > 0;
            destinationRegister = rangeInstruction.getStartRegister();
        }
        RegisterType preInstructionDestRegisterType = getPreInstructionRegisterType(destinationRegister);
        if (preInstructionDestRegisterType.category == RegisterType.UNKNOWN) {
            // We never let an uninitialized reference propagate past an invoke-init if the object register type is
            // unknown This is because the uninitialized reference may be an alias to the reference being
            // initialized, but we can't know that until the object register's type is known
            RegisterType preInstructionRegisterType = getPreInstructionRegisterType(registerNumber);
            if (preInstructionRegisterType.category == RegisterType.UNINIT_REF || preInstructionRegisterType.category == RegisterType.UNINIT_THIS) {
                return true;
            }
        }
        if (preInstructionDestRegisterType.category != RegisterType.UNINIT_REF && preInstructionDestRegisterType.category != RegisterType.UNINIT_THIS) {
            return false;
        }
        if (registerNumber == destinationRegister) {
            return true;
        }
        // check if the uninit ref has been copied to another register
        return preInstructionDestRegisterType.equals(getPreInstructionRegisterType(registerNumber));
    }
    // 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;
            if (registerNumber == instanceOfInstruction.getRegisterB()) {
                return true;
            }
            // 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 && registerNumber == originalSourceRegister) {
                    return true;
                }
            }
        }
    }
    if (!instruction.getOpcode().setsRegister()) {
        return false;
    }
    int destinationRegister = getDestinationRegister();
    if (registerNumber == destinationRegister) {
        return true;
    }
    if (instruction.getOpcode().setsWideRegister() && registerNumber == (destinationRegister + 1)) {
        return true;
    }
    return false;
}
Also used : Instruction22c(org.jf.dexlib2.iface.instruction.formats.Instruction22c) Opcode(org.jf.dexlib2.Opcode) TypeReference(org.jf.dexlib2.iface.reference.TypeReference)

Example 24 with Reference

use of org.jf.dexlib2.iface.reference.Reference 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)

Example 25 with Reference

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

the class DexBackedField method getSize.

/**
 * Calculate and return the private size of a field definition.
 *
 * Calculated as: field_idx_diff + access_flags + annotations overhead +
 * initial value size + field reference size
 *
 * @return size in bytes
 */
public int getSize() {
    int size = 0;
    DexReader reader = dexFile.getBuffer().readerAt(startOffset);
    // field_idx_diff
    reader.readLargeUleb128();
    // access_flags
    reader.readSmallUleb128();
    size += reader.getOffset() - startOffset;
    Set<? extends DexBackedAnnotation> annotations = getAnnotations();
    if (!annotations.isEmpty()) {
        // 2 * uint overhead from field_annotation
        size += 2 * 4;
    }
    if (initialValueOffset > 0) {
        reader.setOffset(initialValueOffset);
        if (initialValue != null) {
            DexBackedEncodedValue.skipFrom(reader);
            size += reader.getOffset() - initialValueOffset;
        }
    }
    DexBackedFieldReference fieldRef = new DexBackedFieldReference(dexFile, fieldIndex);
    size += fieldRef.getSize();
    return size;
}
Also used : DexBackedFieldReference(org.jf.dexlib2.dexbacked.reference.DexBackedFieldReference)

Aggregations

Reference (org.jf.dexlib2.iface.reference.Reference)12 TypeReference (org.jf.dexlib2.iface.reference.TypeReference)11 MethodReference (org.jf.dexlib2.iface.reference.MethodReference)10 FieldReference (org.jf.dexlib2.iface.reference.FieldReference)9 Opcode (org.jf.dexlib2.Opcode)7 ExceptionWithContext (org.jf.util.ExceptionWithContext)5 DexBackedFieldReference (org.jf.dexlib2.dexbacked.reference.DexBackedFieldReference)3 DexBackedMethodReference (org.jf.dexlib2.dexbacked.reference.DexBackedMethodReference)3 Instruction (org.jf.dexlib2.iface.instruction.Instruction)3 ReferenceInstruction (org.jf.dexlib2.iface.instruction.ReferenceInstruction)3 Instruction20bc (org.jf.dexlib2.iface.instruction.formats.Instruction20bc)3 Instruction31t (org.jf.dexlib2.iface.instruction.formats.Instruction31t)3 UnknownInstruction (org.jf.dexlib2.iface.instruction.formats.UnknownInstruction)3 ImmutableMethodReference (org.jf.dexlib2.immutable.reference.ImmutableMethodReference)3 Nonnull (javax.annotation.Nonnull)2 Nullable (javax.annotation.Nullable)2 InvalidSwitchPayload (org.jf.baksmali.Adaptors.MethodDefinition.InvalidSwitchPayload)2 ReferenceType (org.jf.dexlib2.ReferenceType)2 BaseMethodReference (org.jf.dexlib2.base.reference.BaseMethodReference)2 InvalidItemIndex (org.jf.dexlib2.dexbacked.DexBackedDexFile.InvalidItemIndex)2