Search in sources :

Example 1 with Instruction22c

use of org.jf.dexlib2.iface.instruction.formats.Instruction22c in project atlas by alibaba.

the class InsTructionsReIClassDef method reInstructions.

@Override
protected Iterable<? extends Instruction> reInstructions(Iterable<? extends Instruction> instructions) {
    final List<Instruction> reinstructions = new ArrayList<Instruction>();
    for (final Instruction instruction : instructions) {
        if (instruction instanceof ReferenceInstruction) {
            Opcode opcode = instruction.getOpcode();
            if (opcode.referenceType == ReferenceType.METHOD) {
                boolean isBasic = false;
                MethodReference methodReference = null;
                try {
                    methodReference = (MethodReference) ((ReferenceInstruction) instruction).getReference();
                    if (methodReference.getDefiningClass().contains("Ljava/lang") || methodReference.getDefiningClass().startsWith("Ljava/util/") || methodReference.getDefiningClass().startsWith("[Ljava/lang")) {
                        reinstructions.add(ImmutableInstruction.of(instruction));
                        continue;
                    }
                    String returnType = methodReference.getReturnType();
                    boolean isArray = false;
                    if (returnType.startsWith("[")) {
                        isArray = true;
                    }
                    String methodName = methodReference.getName();
                    if (methodName.equals("InitBundleInfoByVersionIfNeed")) {
                        System.out.println("InitBundleInfoByVersionIfNeed");
                    }
                    if (basicType.containsKey(returnType)) {
                        isBasic = true;
                    }
                    List<? extends CharSequence> paramTypes = methodReference.getParameterTypes();
                    List<CharSequence> dalvikParamTypes = new ArrayList<CharSequence>();
                    List<CharSequence> newParamTypes = new ArrayList<CharSequence>();
                    for (CharSequence charSequence : paramTypes) {
                        if (basicType.containsKey(charSequence.toString())) {
                            newParamTypes.add(charSequence);
                            dalvikParamTypes.add(basicType.get(charSequence.toString()));
                            continue;
                        }
                        boolean isArray1 = charSequence.toString().startsWith("[");
                        dalvikParamTypes.add(DefineUtils.getDalvikClassName(charSequence.toString()) + (isArray ? "[]" : ""));
                        newParamTypes.add(DefineUtils.getDefineClassName(classProcessor.classProcess(DefineUtils.getDalvikClassName(charSequence.toString())).className, isArray1));
                    }
                    final ImmutableMethodReference immutableReference = new ImmutableMethodReference(DefineUtils.getDefineClassName(classProcessor.classProcess(DefineUtils.getDalvikClassName(methodReference.getDefiningClass())).className, false), classProcessor.methodProcess(DefineUtils.getDalvikClassName(methodReference.getDefiningClass()), methodReference.getName(), isBasic ? basicType.get(methodReference.getReturnType()) : DefineUtils.getDalvikClassName(methodReference.getReturnType()) + (isArray ? "[]" : ""), StringUtils.join(dalvikParamTypes.toArray(), ",")).methodName, newParamTypes, isBasic ? returnType : DefineUtils.getDefineClassName(classProcessor.classProcess(DefineUtils.getDalvikClassName(methodReference.getReturnType())).className, methodReference.getReturnType().startsWith("[")));
                    if (instruction instanceof Instruction3rc) {
                        reinstructions.add(new ImmutableInstruction3rc(instruction.getOpcode(), ((Instruction3rc) instruction).getStartRegister(), ((Instruction3rc) instruction).getRegisterCount(), immutableReference));
                    } else if (instruction instanceof Instruction20bc) {
                        reinstructions.add(new ImmutableInstruction20bc(instruction.getOpcode(), ((Instruction20bc) instruction).getVerificationError(), immutableReference));
                    } else if (instruction instanceof Instruction21c) {
                        reinstructions.add(new ImmutableInstruction21c(instruction.getOpcode(), ((Instruction21c) instruction).getRegisterA(), immutableReference));
                    } else if (instruction instanceof Instruction22c) {
                        reinstructions.add(new ImmutableInstruction22c(instruction.getOpcode(), ((Instruction22c) instruction).getRegisterA(), ((Instruction22c) instruction).getRegisterB(), immutableReference));
                    } else if (instruction instanceof Instruction31c) {
                        reinstructions.add(new ImmutableInstruction31c(instruction.getOpcode(), ((Instruction31c) instruction).getRegisterA(), immutableReference));
                    } else if (instruction instanceof Instruction35c) {
                        reinstructions.add(new ImmutableInstruction35c(instruction.getOpcode(), ((Instruction35c) instruction).getRegisterCount(), ((Instruction35c) instruction).getRegisterC(), ((Instruction35c) instruction).getRegisterD(), ((Instruction35c) instruction).getRegisterE(), ((Instruction35c) instruction).getRegisterF(), ((Instruction35c) instruction).getRegisterG(), immutableReference));
                    }
                } catch (Exception e) {
                }
            } else if (opcode.referenceType == ReferenceType.FIELD) {
                FieldReference fieldReference = null;
                boolean isBasic = false;
                boolean isBasicArray = false;
                fieldReference = (FieldReference) ((ReferenceInstruction) instruction).getReference();
                if (fieldReference.getDefiningClass().startsWith("Ljava/lang/") || fieldReference.getDefiningClass().startsWith("Ljava/util/") || fieldReference.getDefiningClass().startsWith("[Ljava/lang/")) {
                    reinstructions.add(ImmutableInstruction.of(instruction));
                    continue;
                }
                if (basicType.containsKey(fieldReference.getType())) {
                    isBasic = true;
                }
                final ImmutableFieldReference immutableFieldReference = new ImmutableFieldReference(DefineUtils.getDefineClassName(classProcessor.classProcess(DefineUtils.getDalvikClassName(fieldReference.getDefiningClass())).className, false), classProcessor.filedProcess(DefineUtils.getDalvikClassName(fieldReference.getDefiningClass()), isBasic ? basicType.get(fieldReference.getType()) : DefineUtils.getDalvikClassName(fieldReference.getType()), fieldReference.getName()).fieldName, isBasic ? fieldReference.getType() : DefineUtils.getDefineClassName(classProcessor.classProcess(DefineUtils.getDalvikClassName(fieldReference.getType())).className, fieldReference.getType().startsWith("[")));
                if (instruction instanceof Instruction3rc) {
                    reinstructions.add(new ImmutableInstruction3rc(instruction.getOpcode(), ((Instruction3rc) instruction).getStartRegister(), ((Instruction3rc) instruction).getRegisterCount(), immutableFieldReference));
                } else if (instruction instanceof Instruction20bc) {
                    reinstructions.add(new ImmutableInstruction20bc(instruction.getOpcode(), ((Instruction20bc) instruction).getVerificationError(), immutableFieldReference));
                } else if (instruction instanceof Instruction21c) {
                    reinstructions.add(new ImmutableInstruction21c(instruction.getOpcode(), ((Instruction21c) instruction).getRegisterA(), immutableFieldReference));
                } else if (instruction instanceof Instruction22c) {
                    reinstructions.add(new ImmutableInstruction22c(instruction.getOpcode(), ((Instruction22c) instruction).getRegisterA(), ((Instruction22c) instruction).getRegisterB(), immutableFieldReference));
                } else if (instruction instanceof Instruction31c) {
                    reinstructions.add(new ImmutableInstruction31c(instruction.getOpcode(), ((Instruction31c) instruction).getRegisterA(), immutableFieldReference));
                } else if (instruction instanceof Instruction35c) {
                    reinstructions.add(new ImmutableInstruction35c(instruction.getOpcode(), ((Instruction35c) instruction).getRegisterCount(), ((Instruction35c) instruction).getRegisterC(), ((Instruction35c) instruction).getRegisterD(), ((Instruction35c) instruction).getRegisterE(), ((Instruction35c) instruction).getRegisterF(), ((Instruction35c) instruction).getRegisterG(), immutableFieldReference));
                }
            } else if (opcode.referenceType == ReferenceType.TYPE) {
                TypeReference typeReference = (TypeReference) ((ReferenceInstruction) instruction).getReference();
                String type = typeReference.getType();
                if (!basicType.containsKey(type) && !type.startsWith("Ljava/lang") && !type.startsWith("Ljava/util/") && !type.startsWith("[Ljava/lang")) {
                    type = DefineUtils.getDefineClassName(classProcessor.classProcess(DefineUtils.getDalvikClassName(type)).className, type.startsWith("["));
                }
                ImmutableTypeReference immutableTypeReference = new ImmutableTypeReference(type);
                if (instruction instanceof Instruction3rc) {
                    reinstructions.add(new ImmutableInstruction3rc(instruction.getOpcode(), ((Instruction3rc) instruction).getStartRegister(), ((Instruction3rc) instruction).getRegisterCount(), immutableTypeReference));
                } else if (instruction instanceof Instruction20bc) {
                    reinstructions.add(new ImmutableInstruction20bc(instruction.getOpcode(), ((Instruction20bc) instruction).getVerificationError(), immutableTypeReference));
                } else if (instruction instanceof Instruction21c) {
                    reinstructions.add(new ImmutableInstruction21c(instruction.getOpcode(), ((Instruction21c) instruction).getRegisterA(), immutableTypeReference));
                } else if (instruction instanceof Instruction22c) {
                    reinstructions.add(new ImmutableInstruction22c(instruction.getOpcode(), ((Instruction22c) instruction).getRegisterA(), ((Instruction22c) instruction).getRegisterB(), immutableTypeReference));
                } else if (instruction instanceof Instruction31c) {
                    reinstructions.add(new ImmutableInstruction31c(instruction.getOpcode(), ((Instruction31c) instruction).getRegisterA(), immutableTypeReference));
                } else if (instruction instanceof Instruction35c) {
                    reinstructions.add(new ImmutableInstruction35c(instruction.getOpcode(), ((Instruction35c) instruction).getRegisterCount(), ((Instruction35c) instruction).getRegisterC(), ((Instruction35c) instruction).getRegisterD(), ((Instruction35c) instruction).getRegisterE(), ((Instruction35c) instruction).getRegisterF(), ((Instruction35c) instruction).getRegisterG(), immutableTypeReference));
                }
            } else if (opcode.referenceType == ReferenceType.STRING) {
                StringReference stringReference = (StringReference) ((ReferenceInstruction) instruction).getReference();
                String type = stringReference.getString();
                //                    if (!basicType.contains(type) && !type.startsWith("[Ljava/lang")) {
                //                        type = DefineUtils.getDefineClassName(classProcessor.classProcess(DefineUtils.getDalvikClassName(type)).className);
                //                    }
                ImmutableStringReference immutableStringReference = new ImmutableStringReference(type);
                if (instruction instanceof Instruction3rc) {
                    reinstructions.add(new ImmutableInstruction3rc(instruction.getOpcode(), ((Instruction3rc) instruction).getStartRegister(), ((Instruction3rc) instruction).getRegisterCount(), immutableStringReference));
                } else if (instruction instanceof Instruction20bc) {
                    reinstructions.add(new ImmutableInstruction20bc(instruction.getOpcode(), ((Instruction20bc) instruction).getVerificationError(), immutableStringReference));
                } else if (instruction instanceof Instruction21c) {
                    reinstructions.add(new ImmutableInstruction21c(instruction.getOpcode(), ((Instruction21c) instruction).getRegisterA(), immutableStringReference));
                } else if (instruction instanceof Instruction22c) {
                    reinstructions.add(new ImmutableInstruction22c(instruction.getOpcode(), ((Instruction22c) instruction).getRegisterA(), ((Instruction22c) instruction).getRegisterB(), immutableStringReference));
                } else if (instruction instanceof Instruction31c) {
                    reinstructions.add(new ImmutableInstruction31c(instruction.getOpcode(), ((Instruction31c) instruction).getRegisterA(), immutableStringReference));
                } else if (instruction instanceof Instruction35c) {
                    reinstructions.add(new ImmutableInstruction35c(instruction.getOpcode(), ((Instruction35c) instruction).getRegisterCount(), ((Instruction35c) instruction).getRegisterC(), ((Instruction35c) instruction).getRegisterD(), ((Instruction35c) instruction).getRegisterE(), ((Instruction35c) instruction).getRegisterF(), ((Instruction35c) instruction).getRegisterG(), immutableStringReference));
                }
            } else {
                reinstructions.add(ImmutableInstruction.of(instruction));
            }
        } else {
            reinstructions.add(ImmutableInstruction.of(instruction));
        }
    }
    return new Iterable<Instruction>() {

        @Override
        public Iterator<Instruction> iterator() {
            return reinstructions.iterator();
        }
    };
}
Also used : ImmutableInstruction31c(org.jf.dexlib2.immutable.instruction.ImmutableInstruction31c) Instruction31c(org.jf.dexlib2.iface.instruction.formats.Instruction31c) ImmutableInstruction21c(org.jf.dexlib2.immutable.instruction.ImmutableInstruction21c) Instruction21c(org.jf.dexlib2.iface.instruction.formats.Instruction21c) Instruction35c(org.jf.dexlib2.iface.instruction.formats.Instruction35c) ImmutableInstruction35c(org.jf.dexlib2.immutable.instruction.ImmutableInstruction35c) ArrayList(java.util.ArrayList) ImmutableFieldReference(org.jf.dexlib2.immutable.reference.ImmutableFieldReference) ReferenceInstruction(org.jf.dexlib2.iface.instruction.ReferenceInstruction) Opcode(org.jf.dexlib2.Opcode) ImmutableInstruction(org.jf.dexlib2.immutable.instruction.ImmutableInstruction) Instruction(org.jf.dexlib2.iface.instruction.Instruction) ReferenceInstruction(org.jf.dexlib2.iface.instruction.ReferenceInstruction) ImmutableInstruction35c(org.jf.dexlib2.immutable.instruction.ImmutableInstruction35c) ImmutableInstruction21c(org.jf.dexlib2.immutable.instruction.ImmutableInstruction21c) ImmutableInstruction31c(org.jf.dexlib2.immutable.instruction.ImmutableInstruction31c) TypeReference(org.jf.dexlib2.iface.reference.TypeReference) ImmutableTypeReference(org.jf.dexlib2.immutable.reference.ImmutableTypeReference) ImmutableTypeReference(org.jf.dexlib2.immutable.reference.ImmutableTypeReference) Instruction3rc(org.jf.dexlib2.iface.instruction.formats.Instruction3rc) ImmutableInstruction3rc(org.jf.dexlib2.immutable.instruction.ImmutableInstruction3rc) Instruction22c(org.jf.dexlib2.iface.instruction.formats.Instruction22c) ImmutableInstruction22c(org.jf.dexlib2.immutable.instruction.ImmutableInstruction22c) FieldReference(org.jf.dexlib2.iface.reference.FieldReference) ImmutableFieldReference(org.jf.dexlib2.immutable.reference.ImmutableFieldReference) ImmutableMethodReference(org.jf.dexlib2.immutable.reference.ImmutableMethodReference) ImmutableStringReference(org.jf.dexlib2.immutable.reference.ImmutableStringReference) ImmutableStringReference(org.jf.dexlib2.immutable.reference.ImmutableStringReference) StringReference(org.jf.dexlib2.iface.reference.StringReference) ImmutableInstruction20bc(org.jf.dexlib2.immutable.instruction.ImmutableInstruction20bc) ImmutableInstruction20bc(org.jf.dexlib2.immutable.instruction.ImmutableInstruction20bc) Instruction20bc(org.jf.dexlib2.iface.instruction.formats.Instruction20bc) ImmutableInstruction22c(org.jf.dexlib2.immutable.instruction.ImmutableInstruction22c) ImmutableInstruction3rc(org.jf.dexlib2.immutable.instruction.ImmutableInstruction3rc) ImmutableMethodReference(org.jf.dexlib2.immutable.reference.ImmutableMethodReference) MethodReference(org.jf.dexlib2.iface.reference.MethodReference)

Example 2 with Instruction22c

use of org.jf.dexlib2.iface.instruction.formats.Instruction22c 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 3 with Instruction22c

use of org.jf.dexlib2.iface.instruction.formats.Instruction22c in project smali by JesusFreke.

the class MethodAnalyzer method canPropagateTypeAfterInstanceOf.

static boolean canPropagateTypeAfterInstanceOf(AnalyzedInstruction analyzedInstanceOfInstruction, AnalyzedInstruction analyzedIfInstruction, ClassPath classPath) {
    if (!classPath.isArt()) {
        return false;
    }
    Instruction ifInstruction = analyzedIfInstruction.instruction;
    if (((Instruction21t) ifInstruction).getRegisterA() == analyzedInstanceOfInstruction.getDestinationRegister()) {
        Reference reference = ((Instruction22c) analyzedInstanceOfInstruction.getInstruction()).getReference();
        RegisterType registerType = RegisterType.getRegisterType(classPath, (TypeReference) reference);
        try {
            if (registerType.type != null && !registerType.type.isInterface()) {
                int objectRegister = ((TwoRegisterInstruction) analyzedInstanceOfInstruction.getInstruction()).getRegisterB();
                RegisterType originalType = analyzedIfInstruction.getPreInstructionRegisterType(objectRegister);
                return isNotWideningConversion(originalType, registerType);
            }
        } catch (UnresolvedClassException ex) {
            return false;
        }
    }
    return false;
}
Also used : BaseMethodReference(org.jf.dexlib2.base.reference.BaseMethodReference) TypeReference(org.jf.dexlib2.iface.reference.TypeReference) ImmutableMethodReference(org.jf.dexlib2.immutable.reference.ImmutableMethodReference) Reference(org.jf.dexlib2.iface.reference.Reference) FieldReference(org.jf.dexlib2.iface.reference.FieldReference) ImmutableFieldReference(org.jf.dexlib2.immutable.reference.ImmutableFieldReference) MethodReference(org.jf.dexlib2.iface.reference.MethodReference)

Example 4 with Instruction22c

use of org.jf.dexlib2.iface.instruction.formats.Instruction22c in project smali by JesusFreke.

the class MethodAnalyzer method analyzeIputIgetQuick.

private boolean analyzeIputIgetQuick(@Nonnull AnalyzedInstruction analyzedInstruction) {
    Instruction22cs instruction = (Instruction22cs) analyzedInstruction.instruction;
    int fieldOffset = instruction.getFieldOffset();
    RegisterType objectRegisterType = getAndCheckSourceRegister(analyzedInstruction, instruction.getRegisterB(), ReferenceOrUninitCategories);
    if (objectRegisterType.category == RegisterType.NULL) {
        return false;
    }
    TypeProto objectRegisterTypeProto = objectRegisterType.type;
    assert objectRegisterTypeProto != null;
    TypeProto classTypeProto = classPath.getClass(objectRegisterTypeProto.getType());
    FieldReference resolvedField = classTypeProto.getFieldByOffset(fieldOffset);
    if (resolvedField == null) {
        throw new AnalysisException("Could not resolve the field in class %s at offset %d", objectRegisterType.type.getType(), fieldOffset);
    }
    ClassDef thisClass = classPath.getClassDef(method.getDefiningClass());
    if (!TypeUtils.canAccessClass(thisClass.getType(), classPath.getClassDef(resolvedField.getDefiningClass()))) {
        // the class is not accessible. So we start looking at objectRegisterTypeProto (which may be different
        // than resolvedField.getDefiningClass()), and walk up the class hierarchy.
        ClassDef fieldClass = classPath.getClassDef(objectRegisterTypeProto.getType());
        while (!TypeUtils.canAccessClass(thisClass.getType(), fieldClass)) {
            String superclass = fieldClass.getSuperclass();
            if (superclass == null) {
                throw new ExceptionWithContext("Couldn't find accessible class while resolving field %s", ReferenceUtil.getShortFieldDescriptor(resolvedField));
            }
            fieldClass = classPath.getClassDef(superclass);
        }
        // fieldClass is now the first accessible class found. Now. we need to make sure that the field is
        // actually valid for this class
        FieldReference newResolvedField = classPath.getClass(fieldClass.getType()).getFieldByOffset(fieldOffset);
        if (newResolvedField == null) {
            throw new ExceptionWithContext("Couldn't find accessible class while resolving field %s", ReferenceUtil.getShortFieldDescriptor(resolvedField));
        }
        resolvedField = new ImmutableFieldReference(fieldClass.getType(), newResolvedField.getName(), newResolvedField.getType());
    }
    String fieldType = resolvedField.getType();
    Opcode opcode = classPath.getFieldInstructionMapper().getAndCheckDeodexedOpcode(fieldType, instruction.getOpcode());
    Instruction22c deodexedInstruction = new ImmutableInstruction22c(opcode, (byte) instruction.getRegisterA(), (byte) instruction.getRegisterB(), resolvedField);
    analyzedInstruction.setDeodexedInstruction(deodexedInstruction);
    analyzeInstruction(analyzedInstruction);
    return true;
}
Also used : FieldReference(org.jf.dexlib2.iface.reference.FieldReference) ImmutableFieldReference(org.jf.dexlib2.immutable.reference.ImmutableFieldReference) ImmutableFieldReference(org.jf.dexlib2.immutable.reference.ImmutableFieldReference) Opcode(org.jf.dexlib2.Opcode) ExceptionWithContext(org.jf.util.ExceptionWithContext)

Example 5 with Instruction22c

use of org.jf.dexlib2.iface.instruction.formats.Instruction22c 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)

Aggregations

Opcode (org.jf.dexlib2.Opcode)4 TypeReference (org.jf.dexlib2.iface.reference.TypeReference)4 Instruction22c (org.jf.dexlib2.iface.instruction.formats.Instruction22c)3 FieldReference (org.jf.dexlib2.iface.reference.FieldReference)3 ImmutableFieldReference (org.jf.dexlib2.immutable.reference.ImmutableFieldReference)3 Instruction (org.jf.dexlib2.iface.instruction.Instruction)2 ReferenceInstruction (org.jf.dexlib2.iface.instruction.ReferenceInstruction)2 MethodReference (org.jf.dexlib2.iface.reference.MethodReference)2 StringReference (org.jf.dexlib2.iface.reference.StringReference)2 ImmutableMethodReference (org.jf.dexlib2.immutable.reference.ImmutableMethodReference)2 ExceptionWithContext (org.jf.util.ExceptionWithContext)2 ArrayList (java.util.ArrayList)1 BaseMethodReference (org.jf.dexlib2.base.reference.BaseMethodReference)1 ExceptionHandler (org.jf.dexlib2.iface.ExceptionHandler)1 MethodImplementation (org.jf.dexlib2.iface.MethodImplementation)1 OneRegisterInstruction (org.jf.dexlib2.iface.instruction.OneRegisterInstruction)1 Instruction20bc (org.jf.dexlib2.iface.instruction.formats.Instruction20bc)1 Instruction21c (org.jf.dexlib2.iface.instruction.formats.Instruction21c)1 Instruction31c (org.jf.dexlib2.iface.instruction.formats.Instruction31c)1 Instruction35c (org.jf.dexlib2.iface.instruction.formats.Instruction35c)1