use of com.taobao.android.apatch.annotation.MethodReplaceAnnotation in project atlas by alibaba.
the class MethodDefinition method writeTo.
public void writeTo(IndentingWriter writer) throws IOException {
int parameterRegisterCount = 0;
if (!AccessFlags.STATIC.isSet(method.getAccessFlags())) {
parameterRegisterCount++;
}
writer.write(".method ");
writeAccessFlags(writer, method.getAccessFlags());
writer.write(method.getName());
writer.write("(");
for (MethodParameter parameter : methodParameters) {
String type = parameter.getType();
writer.write(type);
parameterRegisterCount++;
if (TypeUtils.isWideType(type)) {
parameterRegisterCount++;
}
}
writer.write(")");
writer.write(method.getReturnType());
writer.write('\n');
writer.indent(4);
if (classDef.options.useLocalsDirective) {
writer.write(".locals ");
int registerCount = methodImpl.getRegisterCount() - parameterRegisterCount;
writer.printSignedIntAsDec(registerCount);
} else {
writer.write(".registers ");
writer.printSignedIntAsDec(methodImpl.getRegisterCount());
}
writer.write('\n');
writeParameters(writer, method, methodParameters, classDef.options);
if (registerFormatter == null) {
registerFormatter = new RegisterFormatter(classDef.options, methodImpl.getRegisterCount(), parameterRegisterCount);
}
String containingClass = null;
if (classDef.options.useImplicitReferences) {
containingClass = method.getDefiningClass();
}
//如果是修改的方法,需要添加ReplaceAnnotation
if (DexDiffInfo.modifiedMethods.contains(method)) {
MethodReplaceAnnotation replaceAnnotation = new MethodReplaceAnnotation(method.getDefiningClass(), method.getName());
AnnotationFormatter.writeTo(writer, method.getAnnotations(), containingClass, replaceAnnotation);
} else {
AnnotationFormatter.writeTo(writer, method.getAnnotations(), containingClass);
}
writer.write('\n');
boolean first = true;
boolean writeCheckCast = false;
List<MethodItem> methodItems = getMethodItems();
for (MethodItem methodItem : methodItems) {
if (first && APatchTool.isApatch) {
first = false;
if (!fullMethod && !(methodItem instanceof EndPrologueMethodItem) && !DexDiffInfo.addedClasses.contains(classDef.getClassDef())) {
if (!AccessFlags.STATIC.isSet(method.getAccessFlags())) {
writer.write("check-cast p0, " + method.getDefiningClass());
writer.write('\n');
writeCheckCast = true;
}
}
}
if (methodItem.writeTo(writer)) {
writer.write('\n');
}
if (!writeCheckCast && !fullMethod && APatchTool.isApatch && !DexDiffInfo.addedClasses.contains(classDef.getClassDef())) {
if (!AccessFlags.STATIC.isSet(method.getAccessFlags())) {
if (methodItem instanceof EndPrologueMethodItem) {
writer.write("check-cast p0, " + method.getDefiningClass());
writer.write('\n');
writeCheckCast = true;
}
}
}
}
writer.deindent(4);
writer.write(".end method\n");
}
use of com.taobao.android.apatch.annotation.MethodReplaceAnnotation in project atlas by alibaba.
the class AnnotationFormatter method writeTo.
public static void writeTo(@Nonnull IndentingWriter writer, @Nonnull Collection<? extends Annotation> annotations, @Nullable String containingClass, MethodReplaceAnnotation methodReplaceAnnotation) throws IOException {
boolean first = true;
for (Annotation annotation : annotations) {
if (!first) {
writer.write('\n');
}
first = false;
writeTo(writer, annotation, containingClass);
}
if (null != methodReplaceAnnotation) {
writeTo(writer, methodReplaceAnnotation, containingClass);
}
}
use of com.taobao.android.apatch.annotation.MethodReplaceAnnotation in project atlas by alibaba.
the class MethodDefinition method writeEmptyMethodTo.
public static void writeEmptyMethodTo(IndentingWriter writer, Method method, baksmaliOptions options) throws IOException {
writer.write(".method ");
writeAccessFlags(writer, method.getAccessFlags());
writer.write(method.getName());
writer.write("(");
ImmutableList<MethodParameter> methodParameters = ImmutableList.copyOf(method.getParameters());
for (MethodParameter parameter : methodParameters) {
writer.write(parameter.getType());
}
writer.write(")");
writer.write(method.getReturnType());
writer.write('\n');
writer.indent(4);
writeParameters(writer, method, methodParameters, options);
String containingClass = null;
if (options.useImplicitReferences) {
containingClass = method.getDefiningClass();
}
//如果是修改的方法,需要添加ReplaceAnnotation
if (DexDiffInfo.modifiedMethods.contains(method)) {
MethodReplaceAnnotation replaceAnnotation = new MethodReplaceAnnotation(method.getDefiningClass(), method.getName());
AnnotationFormatter.writeTo(writer, method.getAnnotations(), containingClass, replaceAnnotation);
} else {
AnnotationFormatter.writeTo(writer, method.getAnnotations(), containingClass);
}
writer.deindent(4);
writer.write(".end method\n");
}
use of com.taobao.android.apatch.annotation.MethodReplaceAnnotation 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 com.taobao.android.apatch.annotation.MethodReplaceAnnotation 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);
}
}
}
Aggregations