Search in sources :

Example 1 with TypeProto

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

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

the class CustomInlineMethodResolver method parseAndResolveInlineMethod.

@Nonnull
private Method parseAndResolveInlineMethod(@Nonnull String inlineMethod) {
    Matcher m = longMethodPattern.matcher(inlineMethod);
    if (!m.matches()) {
        assert false;
        throw new RuntimeException("Invalid method descriptor: " + inlineMethod);
    }
    String className = m.group(1);
    String methodName = m.group(2);
    Iterable<ImmutableMethodParameter> methodParams = ParamUtil.parseParamString(m.group(3));
    String methodRet = m.group(4);
    ImmutableMethodReference methodRef = new ImmutableMethodReference(className, methodName, methodParams, methodRet);
    int accessFlags = 0;
    boolean resolved = false;
    TypeProto typeProto = classPath.getClass(className);
    if (typeProto instanceof ClassProto) {
        ClassDef classDef = ((ClassProto) typeProto).getClassDef();
        for (Method method : classDef.getMethods()) {
            if (method.equals(methodRef)) {
                resolved = true;
                accessFlags = method.getAccessFlags();
                break;
            }
        }
    }
    if (!resolved) {
        throw new RuntimeException("Cannot resolve inline method: " + inlineMethod);
    }
    return new ImmutableMethod(className, methodName, methodParams, methodRet, accessFlags, null, null);
}
Also used : ImmutableMethod(org.jf.dexlib2.immutable.ImmutableMethod) ImmutableMethodReference(org.jf.dexlib2.immutable.reference.ImmutableMethodReference) Matcher(java.util.regex.Matcher) ImmutableMethodParameter(org.jf.dexlib2.immutable.ImmutableMethodParameter) ImmutableMethod(org.jf.dexlib2.immutable.ImmutableMethod) Method(org.jf.dexlib2.iface.Method) ClassDef(org.jf.dexlib2.iface.ClassDef) Nonnull(javax.annotation.Nonnull)

Example 3 with TypeProto

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

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

the class MethodAnalyzer method analyzeInvokeVirtualQuick.

private boolean analyzeInvokeVirtualQuick(@Nonnull AnalyzedInstruction analyzedInstruction, boolean isSuper, boolean isRange) {
    int methodIndex;
    int objectRegister;
    if (isRange) {
        Instruction3rms instruction = (Instruction3rms) analyzedInstruction.instruction;
        methodIndex = instruction.getVtableIndex();
        objectRegister = instruction.getStartRegister();
    } else {
        Instruction35ms instruction = (Instruction35ms) analyzedInstruction.instruction;
        methodIndex = instruction.getVtableIndex();
        objectRegister = instruction.getRegisterC();
    }
    RegisterType objectRegisterType = getAndCheckSourceRegister(analyzedInstruction, objectRegister, ReferenceOrUninitCategories);
    TypeProto objectRegisterTypeProto = objectRegisterType.type;
    if (objectRegisterType.category == RegisterType.NULL) {
        return false;
    }
    assert objectRegisterTypeProto != null;
    MethodReference resolvedMethod;
    if (isSuper) {
        // invoke-super is only used for the same class that we're currently in
        TypeProto typeProto = classPath.getClass(method.getDefiningClass());
        TypeProto superType;
        String superclassType = typeProto.getSuperclass();
        if (superclassType != null) {
            superType = classPath.getClass(superclassType);
        } else {
            // This is either java.lang.Object, or an UnknownClassProto
            superType = typeProto;
        }
        resolvedMethod = superType.getMethodByVtableIndex(methodIndex);
    } else {
        resolvedMethod = objectRegisterTypeProto.getMethodByVtableIndex(methodIndex);
    }
    if (resolvedMethod == null) {
        throw new AnalysisException("Could not resolve the method in class %s at index %d", objectRegisterType.type.getType(), methodIndex);
    }
    // no need to check class access for invoke-super. A class can obviously access its superclass.
    ClassDef thisClass = classPath.getClassDef(method.getDefiningClass());
    if (classPath.getClass(resolvedMethod.getDefiningClass()).isInterface()) {
        resolvedMethod = new ReparentedMethodReference(resolvedMethod, objectRegisterTypeProto.getType());
    } else if (!isSuper && !TypeUtils.canAccessClass(thisClass.getType(), classPath.getClassDef(resolvedMethod.getDefiningClass()))) {
        // the class is not accessible. So we start looking at objectRegisterTypeProto (which may be different
        // than resolvedMethod.getDefiningClass()), and walk up the class hierarchy.
        ClassDef methodClass = classPath.getClassDef(objectRegisterTypeProto.getType());
        while (!TypeUtils.canAccessClass(thisClass.getType(), methodClass)) {
            String superclass = methodClass.getSuperclass();
            if (superclass == null) {
                throw new ExceptionWithContext("Couldn't find accessible class while resolving method %s", ReferenceUtil.getMethodDescriptor(resolvedMethod, true));
            }
            methodClass = classPath.getClassDef(superclass);
        }
        // methodClass is now the first accessible class found. Now. we need to make sure that the method is
        // actually valid for this class
        MethodReference newResolvedMethod = classPath.getClass(methodClass.getType()).getMethodByVtableIndex(methodIndex);
        if (newResolvedMethod == null) {
            throw new ExceptionWithContext("Couldn't find accessible class while resolving method %s", ReferenceUtil.getMethodDescriptor(resolvedMethod, true));
        }
        resolvedMethod = newResolvedMethod;
        resolvedMethod = new ImmutableMethodReference(methodClass.getType(), resolvedMethod.getName(), resolvedMethod.getParameterTypes(), resolvedMethod.getReturnType());
    }
    if (normalizeVirtualMethods) {
        MethodReference replacementMethod = normalizeMethodReference(resolvedMethod);
        if (replacementMethod != null) {
            resolvedMethod = replacementMethod;
        }
    }
    Instruction deodexedInstruction;
    if (isRange) {
        Instruction3rms instruction = (Instruction3rms) analyzedInstruction.instruction;
        Opcode opcode;
        if (isSuper) {
            opcode = Opcode.INVOKE_SUPER_RANGE;
        } else {
            opcode = Opcode.INVOKE_VIRTUAL_RANGE;
        }
        deodexedInstruction = new ImmutableInstruction3rc(opcode, instruction.getStartRegister(), instruction.getRegisterCount(), resolvedMethod);
    } else {
        Instruction35ms instruction = (Instruction35ms) analyzedInstruction.instruction;
        Opcode opcode;
        if (isSuper) {
            opcode = Opcode.INVOKE_SUPER;
        } else {
            opcode = Opcode.INVOKE_VIRTUAL;
        }
        deodexedInstruction = new ImmutableInstruction35c(opcode, instruction.getRegisterCount(), instruction.getRegisterC(), instruction.getRegisterD(), instruction.getRegisterE(), instruction.getRegisterF(), instruction.getRegisterG(), resolvedMethod);
    }
    analyzedInstruction.setDeodexedInstruction(deodexedInstruction);
    analyzeInstruction(analyzedInstruction);
    return true;
}
Also used : ImmutableMethodReference(org.jf.dexlib2.immutable.reference.ImmutableMethodReference) Opcode(org.jf.dexlib2.Opcode) ExceptionWithContext(org.jf.util.ExceptionWithContext) BaseMethodReference(org.jf.dexlib2.base.reference.BaseMethodReference) ImmutableMethodReference(org.jf.dexlib2.immutable.reference.ImmutableMethodReference) MethodReference(org.jf.dexlib2.iface.reference.MethodReference)

Example 5 with TypeProto

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

the class TypeProtoUtils method getSuperclassChain.

/**
     * Get the chain of superclasses of the given class. The first element will be the immediate superclass followed by
     * it's superclass, etc. up to java.lang.Object.
     *
     * Returns an empty iterable if called on java.lang.Object or a primitive.
     *
     * If any class in the superclass chain can't be resolved, the iterable will return Ujava/lang/Object; to represent
     * the unknown class.
     *
     * @return An iterable containing the superclasses of this class.
     */
@Nonnull
public static Iterable<TypeProto> getSuperclassChain(@Nonnull final TypeProto typeProto) {
    return new Iterable<TypeProto>() {

        @Override
        public Iterator<TypeProto> iterator() {
            return new Iterator<TypeProto>() {

                @Nullable
                private TypeProto type = getSuperclassAsTypeProto(typeProto);

                @Override
                public boolean hasNext() {
                    return type != null;
                }

                @Override
                public TypeProto next() {
                    TypeProto type = this.type;
                    if (type == null) {
                        throw new NoSuchElementException();
                    }
                    this.type = getSuperclassAsTypeProto(type);
                    return type;
                }

                @Override
                public void remove() {
                    throw new UnsupportedOperationException();
                }
            };
        }
    };
}
Also used : Iterator(java.util.Iterator) TypeProto(org.jf.dexlib2.analysis.TypeProto) NoSuchElementException(java.util.NoSuchElementException) Nonnull(javax.annotation.Nonnull)

Aggregations

ClassDef (org.jf.dexlib2.iface.ClassDef)4 TypeProto (org.jf.dexlib2.analysis.TypeProto)3 Nonnull (javax.annotation.Nonnull)2 Opcode (org.jf.dexlib2.Opcode)2 ClassPath (org.jf.dexlib2.analysis.ClassPath)2 DexClassProvider (org.jf.dexlib2.analysis.DexClassProvider)2 ImmutableDexFile (org.jf.dexlib2.immutable.ImmutableDexFile)2 ImmutableMethodReference (org.jf.dexlib2.immutable.reference.ImmutableMethodReference)2 ExceptionWithContext (org.jf.util.ExceptionWithContext)2 Test (org.junit.Test)2 Iterator (java.util.Iterator)1 NoSuchElementException (java.util.NoSuchElementException)1 Matcher (java.util.regex.Matcher)1 BaseMethodReference (org.jf.dexlib2.base.reference.BaseMethodReference)1 Method (org.jf.dexlib2.iface.Method)1 FieldReference (org.jf.dexlib2.iface.reference.FieldReference)1 MethodReference (org.jf.dexlib2.iface.reference.MethodReference)1 ImmutableMethod (org.jf.dexlib2.immutable.ImmutableMethod)1 ImmutableMethodParameter (org.jf.dexlib2.immutable.ImmutableMethodParameter)1 ImmutableFieldReference (org.jf.dexlib2.immutable.reference.ImmutableFieldReference)1