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);
}
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;
}
Aggregations