Fix up some minor issues with --normalize-virtual-methods

This commit is contained in:
Ben Gruver 2016-09-18 19:07:41 -07:00
parent 815f023e4e
commit ecd89816b3
2 changed files with 50 additions and 35 deletions

View File

@ -172,7 +172,6 @@ public class DisassembleCommand extends DexInputCommand {
} }
} }
protected boolean needsClassPath() { protected boolean needsClassPath() {
return !registerInfoTypes.isEmpty() || normalizeVirtualMethods; return !registerInfoTypes.isEmpty() || normalizeVirtualMethods;
} }

View File

@ -1760,41 +1760,9 @@ public class MethodAnalyzer {
targetMethod = (MethodReference)instruction.getReference(); targetMethod = (MethodReference)instruction.getReference();
} }
TypeProto typeProto = classPath.getClass(targetMethod.getDefiningClass()); MethodReference replacementMethod = normalizeMethodReference(targetMethod);
int methodIndex;
try {
methodIndex = typeProto.findMethodIndexInVtable(targetMethod);
} catch (UnresolvedClassException ex) {
return true;
}
if (methodIndex < 0) { if (replacementMethod == null || replacementMethod.equals(targetMethod)) {
return true;
}
Method replacementMethod = typeProto.getMethodByVtableIndex(methodIndex);
assert replacementMethod != null;
while (true) {
String superType = typeProto.getSuperclass();
if (superType == null) {
break;
}
typeProto = classPath.getClass(superType);
Method resolvedMethod = typeProto.getMethodByVtableIndex(methodIndex);
if (resolvedMethod == null) {
break;
}
if (!resolvedMethod.equals(replacementMethod)) {
if (!AnalyzedMethodUtil.canAccess(typeProto, replacementMethod, true, true, true)) {
continue;
}
replacementMethod = resolvedMethod;
}
}
if (replacementMethod.equals(method)) {
return true; return true;
} }
@ -1893,6 +1861,14 @@ public class MethodAnalyzer {
resolvedMethod = newResolvedMethod; resolvedMethod = newResolvedMethod;
resolvedMethod = new ImmutableMethodReference(methodClass.getType(), resolvedMethod.getName(), resolvedMethod = new ImmutableMethodReference(methodClass.getType(), resolvedMethod.getName(),
resolvedMethod.getParameterTypes(), resolvedMethod.getReturnType()); resolvedMethod.getParameterTypes(), resolvedMethod.getReturnType());
}
if (normalizeVirtualMethods) {
MethodReference replacementMethod = normalizeMethodReference(resolvedMethod);
if (replacementMethod != null) {
resolvedMethod = replacementMethod;
}
} }
Instruction deodexedInstruction; Instruction deodexedInstruction;
@ -1993,4 +1969,44 @@ public class MethodAnalyzer {
"pair because it is the last register.", registerNumber)); "pair because it is the last register.", registerNumber));
} }
} }
@Nullable
private MethodReference normalizeMethodReference(@Nonnull MethodReference methodRef) {
TypeProto typeProto = classPath.getClass(methodRef.getDefiningClass());
int methodIndex;
try {
methodIndex = typeProto.findMethodIndexInVtable(methodRef);
} catch (UnresolvedClassException ex) {
return null;
}
if (methodIndex < 0) {
return null;
}
ClassProto thisClass = (ClassProto)classPath.getClass(method.getDefiningClass());
Method replacementMethod = typeProto.getMethodByVtableIndex(methodIndex);
assert replacementMethod != null;
while (true) {
String superType = typeProto.getSuperclass();
if (superType == null) {
break;
}
typeProto = classPath.getClass(superType);
Method resolvedMethod = typeProto.getMethodByVtableIndex(methodIndex);
if (resolvedMethod == null) {
break;
}
if (!resolvedMethod.equals(replacementMethod)) {
if (!AnalyzedMethodUtil.canAccess(thisClass, resolvedMethod, false, false, true)) {
continue;
}
replacementMethod = resolvedMethod;
}
}
return replacementMethod;
}
} }