use of org.jf.dexlib2.iface.ClassDef in project atlas by alibaba.
the class ClassDefinition method writeDirectMethods.
private Set<String> writeDirectMethods(IndentingWriter writer) throws IOException {
boolean wroteHeader = false;
Set<String> writtenMethods = new HashSet<String>();
Iterable<? extends Method> directMethods;
Set<? extends Method> modifieds = null;
if (classDef instanceof DexBackedClassDef) {
directMethods = ((DexBackedClassDef) classDef).getDirectMethods(false);
modifieds = (Set<? extends Method>) DexDiffInfo.modifiedMethods;
} else {
directMethods = classDef.getDirectMethods();
}
MethodReplaceAnnotation replaceAnnotaion;
for (Method method : directMethods) {
if (!fullMethod && !DexDiffInfo.addedClasses.contains(classDef)) {
if (!modifieds.contains(method) && !DexDiffInfo.addedMethods.contains(method)) {
continue;
}
}
if (!wroteHeader) {
writer.write("\n\n");
writer.write("# direct methods");
wroteHeader = true;
}
writer.write('\n');
// TODO: check for method validation errors
String methodString = ReferenceUtil.getMethodDescriptor(method, true);
IndentingWriter methodWriter = writer;
if (!writtenMethods.add(methodString)) {
writer.write("# duplicate method ignored\n");
methodWriter = new CommentingIndentingWriter(writer);
}
MethodImplementation methodImpl = method.getImplementation();
if (methodImpl == null) {
MethodDefinition.writeEmptyMethodTo(methodWriter, method, options);
} else {
MethodDefinition methodDefinition = new MethodDefinition(this, method, methodImpl);
methodDefinition.setFullMethod(fullMethod);
methodDefinition.writeTo(methodWriter);
}
}
return writtenMethods;
}
use of org.jf.dexlib2.iface.ClassDef in project atlas by alibaba.
the class ClassDefinition method writeVirtualMethods.
private void writeVirtualMethods(IndentingWriter writer, Set<String> directMethods) throws IOException {
boolean wroteHeader = false;
Set<String> writtenMethods = new HashSet<String>();
Iterable<? extends Method> virtualMethods;
Set<? extends Method> modifieds = null;
if (classDef instanceof DexBackedClassDef) {
virtualMethods = ((DexBackedClassDef) classDef).getVirtualMethods(false);
modifieds = (Set<? extends Method>) DexDiffInfo.modifiedMethods;
} else {
virtualMethods = classDef.getVirtualMethods();
}
MethodReplaceAnnotation replaceAnnotaion;
for (Method method : virtualMethods) {
if (!fullMethod && !DexDiffInfo.addedClasses.contains(classDef)) {
if (!modifieds.contains(method) && !DexDiffInfo.addedMethods.contains(method)) {
continue;
}
}
if (!wroteHeader) {
writer.write("\n\n");
writer.write("# virtual methods");
wroteHeader = true;
}
writer.write('\n');
// TODO: check for method validation errors
String methodString = ReferenceUtil.getMethodDescriptor(method, true);
IndentingWriter methodWriter = writer;
if (!writtenMethods.add(methodString)) {
writer.write("# duplicate method ignored\n");
methodWriter = new CommentingIndentingWriter(writer);
} else if (directMethods.contains(methodString)) {
writer.write("# There is both a direct and virtual method with this signature.\n" + "# You will need to rename one of these methods, including all references.\n");
System.err.println(String.format("Duplicate direct+virtual method found: %s->%s", classDef.getType(), methodString));
System.err.println("You will need to rename one of these methods, including all references.");
}
MethodImplementation methodImpl = method.getImplementation();
if (methodImpl == null) {
MethodDefinition.writeEmptyMethodTo(methodWriter, method, options);
} else {
MethodDefinition methodDefinition = new MethodDefinition(this, method, methodImpl);
methodDefinition.writeTo(methodWriter);
}
}
}
use of org.jf.dexlib2.iface.ClassDef 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.iface.ClassDef 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;
}
use of org.jf.dexlib2.iface.ClassDef 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