Search in sources :

Example 1 with MethodReplaceAnnotation

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");
}
Also used : MethodReplaceAnnotation(com.taobao.android.apatch.annotation.MethodReplaceAnnotation) EndPrologueMethodItem(com.taobao.android.baksmali.adaptors.Debug.EndPrologueMethodItem) DebugMethodItem(com.taobao.android.baksmali.adaptors.Debug.DebugMethodItem) EndPrologueMethodItem(com.taobao.android.baksmali.adaptors.Debug.EndPrologueMethodItem) MethodParameter(org.jf.dexlib2.iface.MethodParameter)

Example 2 with MethodReplaceAnnotation

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);
    }
}
Also used : Annotation(org.jf.dexlib2.iface.Annotation) MethodReplaceAnnotation(com.taobao.android.apatch.annotation.MethodReplaceAnnotation)

Example 3 with MethodReplaceAnnotation

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");
}
Also used : MethodReplaceAnnotation(com.taobao.android.apatch.annotation.MethodReplaceAnnotation) MethodParameter(org.jf.dexlib2.iface.MethodParameter)

Example 4 with MethodReplaceAnnotation

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;
}
Also used : MethodImplementation(org.jf.dexlib2.iface.MethodImplementation) Method(org.jf.dexlib2.iface.Method) MethodReplaceAnnotation(com.taobao.android.apatch.annotation.MethodReplaceAnnotation) IndentingWriter(org.jf.util.IndentingWriter) DexBackedClassDef(org.jf.dexlib2.dexbacked.DexBackedClassDef) HashSet(java.util.HashSet)

Example 5 with MethodReplaceAnnotation

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);
        }
    }
}
Also used : MethodImplementation(org.jf.dexlib2.iface.MethodImplementation) Method(org.jf.dexlib2.iface.Method) MethodReplaceAnnotation(com.taobao.android.apatch.annotation.MethodReplaceAnnotation) IndentingWriter(org.jf.util.IndentingWriter) DexBackedClassDef(org.jf.dexlib2.dexbacked.DexBackedClassDef) HashSet(java.util.HashSet)

Aggregations

MethodReplaceAnnotation (com.taobao.android.apatch.annotation.MethodReplaceAnnotation)5 HashSet (java.util.HashSet)2 DexBackedClassDef (org.jf.dexlib2.dexbacked.DexBackedClassDef)2 Method (org.jf.dexlib2.iface.Method)2 MethodImplementation (org.jf.dexlib2.iface.MethodImplementation)2 MethodParameter (org.jf.dexlib2.iface.MethodParameter)2 IndentingWriter (org.jf.util.IndentingWriter)2 DebugMethodItem (com.taobao.android.baksmali.adaptors.Debug.DebugMethodItem)1 EndPrologueMethodItem (com.taobao.android.baksmali.adaptors.Debug.EndPrologueMethodItem)1 Annotation (org.jf.dexlib2.iface.Annotation)1