Search in sources :

Example 6 with ImmutableMethodReference

use of org.jf.dexlib2.immutable.reference.ImmutableMethodReference 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 7 with ImmutableMethodReference

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

Aggregations

ImmutableMethodReference (org.jf.dexlib2.immutable.reference.ImmutableMethodReference)7 MethodReference (org.jf.dexlib2.iface.reference.MethodReference)4 ArrayList (java.util.ArrayList)3 ImmutableStringReference (org.jf.dexlib2.immutable.reference.ImmutableStringReference)3 HashSet (java.util.HashSet)2 Opcode (org.jf.dexlib2.Opcode)2 BuilderInstruction (org.jf.dexlib2.builder.BuilderInstruction)2 MutableMethodImplementation (org.jf.dexlib2.builder.MutableMethodImplementation)2 BuilderInstruction21c (org.jf.dexlib2.builder.instruction.BuilderInstruction21c)2 BuilderInstruction35c (org.jf.dexlib2.builder.instruction.BuilderInstruction35c)2 AnnotationElement (org.jf.dexlib2.iface.AnnotationElement)2 ArrayEncodedValue (org.jf.dexlib2.iface.value.ArrayEncodedValue)2 EncodedValue (org.jf.dexlib2.iface.value.EncodedValue)2 MethodEncodedValue (org.jf.dexlib2.iface.value.MethodEncodedValue)2 StringEncodedValue (org.jf.dexlib2.iface.value.StringEncodedValue)2 TypeEncodedValue (org.jf.dexlib2.iface.value.TypeEncodedValue)2 ImmutableAnnotation (org.jf.dexlib2.immutable.ImmutableAnnotation)2 ImmutableAnnotationElement (org.jf.dexlib2.immutable.ImmutableAnnotationElement)2 ImmutableArrayEncodedValue (org.jf.dexlib2.immutable.value.ImmutableArrayEncodedValue)2 List (java.util.List)1