Search in sources :

Example 16 with DexBackedClassDef

use of org.jf.dexlib2.dexbacked.DexBackedClassDef in project atlas by alibaba.

the class SmaliDiffUtils method diff.

public static boolean diff(DexDiffInfo diffInfo, String outterClassName, String className, File out) throws PatchException {
    String methodName = null;
    DexBackedMethod sDexBackedMethod = null;
    DexBackedClassDef oldDexBackClassDef = null;
    DexBackedClassDef newDexBackClassDef = null;
    File oldTemp = new File(out, "smaliTemp1");
    if (!oldTemp.exists()) {
        oldTemp.mkdirs();
    }
    File newTemp = new File(out, "smaliTemp2");
    if (!newTemp.exists()) {
        newTemp.mkdirs();
    }
    for (DexBackedClassDef dexBackedClassDef : diffInfo.getOldClasses()) {
        if (DexDiffer.getDalvikClassName(dexBackedClassDef.getType()).equals(outterClassName)) {
            oldDexBackClassDef = dexBackedClassDef;
        }
    }
    for (DexBackedClassDef dexBackedClassDef : diffInfo.getNewClasses()) {
        if (DexDiffer.getDalvikClassName(dexBackedClassDef.getType()).equals(outterClassName)) {
            newDexBackClassDef = dexBackedClassDef;
        }
    }
    if (oldDexBackClassDef == null) {
        return false;
    }
    disassemble(oldTemp, oldDexBackClassDef);
    disassemble(newTemp, newDexBackClassDef);
    Iterable<? extends DexBackedMethod> oldDexBackedMethods = oldDexBackClassDef.getMethods();
    Iterable<? extends DexBackedMethod> newDexBackedMethods = newDexBackClassDef.getMethods();
    boolean find = false;
    for (DexBackedMethod dexBackedMethod : newDexBackedMethods) {
        Iterator<? extends Instruction> instructions = dexBackedMethod.getImplementation().getInstructions().iterator();
        while (instructions.hasNext()) {
            Instruction instruction = instructions.next();
            if (instruction instanceof ReferenceInstruction) {
                Opcode opcode = instruction.getOpcode();
                if (opcode.referenceType == ReferenceType.METHOD) {
                    MethodReference methodReference = null;
                    try {
                        methodReference = (MethodReference) ((ReferenceInstruction) instruction).getReference();
                        if (DexDiffer.getDalvikClassName(methodReference.getDefiningClass()).equals(className)) {
                            sDexBackedMethod = dexBackedMethod;
                            find = true;
                            break;
                        }
                    } catch (DexBackedDexFile.InvalidItemIndex ex) {
                        ex.getStackTrace();
                    }
                }
            }
        }
        if (find) {
            break;
        }
    }
    for (DexBackedMethod dexBackedMethod : oldDexBackedMethods) {
        if (compare(dexBackedMethod, sDexBackedMethod)) {
            return true;
        }
    }
    return false;
}
Also used : DexBackedDexFile(org.jf.dexlib2.dexbacked.DexBackedDexFile) DexBackedMethod(org.jf.dexlib2.dexbacked.DexBackedMethod) ReferenceInstruction(org.jf.dexlib2.iface.instruction.ReferenceInstruction) Opcode(org.jf.dexlib2.Opcode) Instruction(org.jf.dexlib2.iface.instruction.Instruction) ReferenceInstruction(org.jf.dexlib2.iface.instruction.ReferenceInstruction) MethodReference(org.jf.dexlib2.iface.reference.MethodReference) DexBackedClassDef(org.jf.dexlib2.dexbacked.DexBackedClassDef) DexBackedDexFile(org.jf.dexlib2.dexbacked.DexBackedDexFile) File(java.io.File)

Example 17 with DexBackedClassDef

use of org.jf.dexlib2.dexbacked.DexBackedClassDef in project atlas by alibaba.

the class SmaliDiffUtils method buildCode.

public static Set<String> buildCode(File smaliDir, File dexFile, DexDiffInfo info) throws IOException, RecognitionException {
    Set<String> classes = new HashSet<String>();
    Set<DexBackedClassDef> classDefs = new HashSet<DexBackedClassDef>();
    classDefs.addAll(info.getModifiedClasses());
    classDefs.addAll(info.getAddedClasses());
    final ClassFileNameHandler outFileNameHandler = new ClassFileNameHandler(smaliDir, ".smali");
    final ClassFileNameHandler inFileNameHandler = new ClassFileNameHandler(smaliDir, ".smali");
    DexBuilder dexBuilder = DexBuilder.makeDexBuilder();
    File smaliFile;
    String className;
    for (DexBackedClassDef classDef : classDefs) {
        ApkPatch.currentClassType = classDef.getType();
        className = TypeGenUtil.newType(classDef.getType());
        AfBakSmali.disassembleClass(classDef, outFileNameHandler, getBuildOption(classDefs, 19), false, false);
        smaliFile = inFileNameHandler.getUniqueFilenameForClass(className);
        classes.add(className.substring(1, className.length() - 1).replace('/', '.'));
        SmaliMod.assembleSmaliFile(smaliFile, dexBuilder, true, true);
    }
    dexBuilder.writeTo(new FileDataStore(dexFile));
    return classes;
}
Also used : ClassFileNameHandler(org.jf.util.ClassFileNameHandler) DexBackedClassDef(org.jf.dexlib2.dexbacked.DexBackedClassDef) DexBackedDexFile(org.jf.dexlib2.dexbacked.DexBackedDexFile) File(java.io.File) FileDataStore(org.jf.dexlib2.writer.io.FileDataStore) HashSet(java.util.HashSet) DexBuilder(org.jf.dexlib2.writer.builder.DexBuilder)

Example 18 with DexBackedClassDef

use of org.jf.dexlib2.dexbacked.DexBackedClassDef 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 19 with DexBackedClassDef

use of org.jf.dexlib2.dexbacked.DexBackedClassDef 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)

Example 20 with DexBackedClassDef

use of org.jf.dexlib2.dexbacked.DexBackedClassDef in project atlas by alibaba.

the class FastPatchTool method doPatch.

public void doPatch() throws IOException, PatchException, RecognitionException {
    MappingReader mappingReader = null;
    MappingProcessor mappingProcessor = null;
    if (outDir == null || !outDir.exists()) {
        return;
    }
    outPatchFile = new File(outDir, "apatch-unsigned.apatch");
    if (mappingFile != null && mappingFile.exists()) {
        mappingReader = new MappingReader(mappingFile);
        mappingProcessor = new MappingProcessorImpl(superClassMap);
        mappingReader.pump(mappingProcessor);
        mappingProcessor.updateMethod();
        mappingProcessor.updateFieldType();
    }
    for (FastPatchObject fastPatchObject : patchObjects) {
        Set<ClassDef> classes = new HashSet<ClassDef>();
        Map<ClassDef, List<Method>> patchClassDefs = new HashMap<ClassDef, List<Method>>();
        Set<ClassDef> addedClasses = new HashSet<ClassDef>();
        Map<ClassDef, List<Method>> newClassDef = new HashMap<ClassDef, List<Method>>();
        ArrayList<Method> methods = new ArrayList<Method>();
        for (File dexFile : fastPatchObject.DexFiles) {
            DexFile dFile = DexFileFactory.loadDexFile(dexFile.getAbsolutePath(), 19, true);
            classes.addAll(dFile.getClasses());
        }
        final Set<ClassDef> newClasses = new HashSet<ClassDef>();
        for (ClassDef classDef : classes) {
            String type = classDef.getType();
            if (fastPatchObject.addedClass.contains(SmaliUtils.getDalvikClassName(type))) {
                System.out.println("patch added class:" + type);
                addedClasses.add(classDef);
                continue;
            }
            for (Map.Entry<String, List<String>> entry : fastPatchObject.modifyClasses.entrySet()) {
                if (entry.getKey().equals(SmaliUtils.getDalvikClassName(type))) {
                    ArrayList<Method> newMethods = new ArrayList<Method>();
                    for (Method method : classDef.getMethods()) {
                        System.err.println(getMethodFullName(method));
                        if (entry.getValue().contains(getMethodFullName(method))) {
                            newMethods.add(method);
                        }
                    }
                    patchClassDefs.put(classDef, newMethods);
                    break;
                }
            }
        }
        if (patchClassDefs.size() == 0 && addedClasses.size() == 0) {
            continue;
        }
        if (mappingFile != null && mappingFile.exists()) {
            //第一步先将prepareclass混淆掉
            for (String className : fastPatchObject.prepareClasses) {
                ApkPatch.prepareClasses.add(mappingProcessor.getNewClassName(className).className);
            }
            //将replaceanatation混淆掉
            MethodReplaceAnnotation.ANNOTATION = DefineUtils.getDefineClassName(mappingProcessor.getNewClassName(DefineUtils.getDalvikClassName("Lcom/alipay/euler/andfix/annotation/MethodReplace;")).className, false);
            //将dex代码混淆掉
            InsTructionsReIClassDef insTructionsReDef = new InsTructionsReIClassDef(new MappingClassProcessor(mappingProcessor));
            for (ClassDef c : classes) {
                if (patchClassDefs.containsKey(c)) {
                    for (Method method : c.getMethods()) {
                        if (patchClassDefs.get(c).contains(method)) {
                            methods.add(insTructionsReDef.reMethod(method));
                        }
                    }
                    newClassDef.put(insTructionsReDef.reClassDef(c), methods);
                } else if (addedClasses.contains(c)) {
                    newClassDef.put(insTructionsReDef.reClassDef(c), new ArrayList<Method>());
                }
                if (c.getType().contains("/R$")) {
                    continue;
                }
                newClasses.add(insTructionsReDef.reClassDef(c));
            }
        } else {
            ApkPatch.prepareClasses.addAll(fastPatchObject.prepareClasses);
        }
        File patchDexFile = new File(outDir, "patch.dex");
        for (ClassDef classDef : newClassDef.keySet()) {
            System.out.println("modify class:" + classDef.getType());
        }
        if (newClassDef.size() > 0) {
            DexFileFactory.writeDexFile(patchDexFile.getAbsolutePath(), new ImmutableDexFile(newClassDef.keySet()));
        } else if (patchClassDefs.size() > 0) {
            DexFileFactory.writeDexFile(patchDexFile.getAbsolutePath(), new ImmutableDexFile(patchClassDefs.keySet()));
        }
        File tempDexFile = new File(outDir, "temp.dex");
        if (newClasses.size() > 0) {
            DexFileFactory.writeDexFile(tempDexFile.getAbsolutePath(), new DexFile() {

                @Nonnull
                @Override
                public Set<? extends ClassDef> getClasses() {
                    return new AbstractSet<ClassDef>() {

                        @Nonnull
                        @Override
                        public Iterator<ClassDef> iterator() {
                            return newClasses.iterator();
                        }

                        @Override
                        public int size() {
                            return newClasses.size();
                        }
                    };
                }
            });
        } else if (classes.size() > 0) {
            DexFileFactory.writeDexFile(tempDexFile.getAbsolutePath(), new ImmutableDexFile(classes));
        }
        SmaliDiffUtils.scanClasses(new File(outDir, "smali2"), Lists.newArrayList(tempDexFile));
        DexFile patchDex = DexFileFactory.loadDexFile(patchDexFile.getAbsolutePath(), 19, true);
        DexFile tempDex = DexFileFactory.loadDexFile(tempDexFile.getAbsolutePath(), 19, true);
        Set<? extends ClassDef> patchClasses = patchDex.getClasses();
        DexDiffInfo dexDiffInfo = new DexDiffInfo();
        for (ClassDef patchClassDef : patchClasses) {
            String type = patchClassDef.getType();
            if (fastPatchObject.addedClass.contains(SmaliUtils.getDalvikClassName(type))) {
                dexDiffInfo.getAddedClasses().add((DexBackedClassDef) patchClassDef);
                dexDiffInfo.addManifestAddClass(type);
                continue;
            }
            for (Method method : patchClassDef.getMethods()) {
                List<? extends CharSequence> parameters = method.getParameterTypes();
                if (methods.size() > 0) {
                    for (Method modifyMethod : methods) {
                        List<? extends CharSequence> modifyParameters = modifyMethod.getParameterTypes();
                        if (parameters.size() != modifyParameters.size() || !isEqualObj(parameters, modifyParameters)) {
                            continue;
                        }
                        if (modifyMethod.getName().equals(method.getName()))
                            dexDiffInfo.addModifiedMethods((DexBackedMethod) method);
                    }
                } else if (patchClassDefs.size() > 0) {
                    for (ClassDef classDef : patchClassDefs.keySet()) {
                        if (classDef.getType().equals(patchClassDef.getType())) {
                            List<Method> methodList = patchClassDefs.get(classDef);
                            for (Method method1 : methodList) {
                                if (method1.getName().equals(method.getName())) {
                                    dexDiffInfo.addModifiedMethods((DexBackedMethod) method);
                                }
                            }
                        }
                    }
                }
            }
        }
        FastBuild fastBuild = new FastBuild(fastPatchObject.bundleName, new File(outDir, bundleName));
        fastBuild.setClasses(tempDex.getClasses());
        fastBuild.setDiffInfo(dexDiffInfo);
        new AndFixFilterImpl(dexDiffInfo).filterDex();
        dexDiffInfo.update();
        APatchTool.isApatch = true;
        File adiffFile = new File(outDir, "apatch-diff.txt");
        File adiffJsonFile = new File(outDir, "apatch-diff.json");
        dexDiffInfo.writeToFile(fastPatchObject.bundleName, adiffFile, adiffJsonFile);
        try {
            File patchJarFile = fastBuild.dopatch();
            patchJarFiles.add(patchJarFile);
        } catch (CertificateException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (KeyStoreException e) {
            e.printStackTrace();
        } catch (UnrecoverableEntryException e) {
            e.printStackTrace();
        }
    }
    File[] aPatchFiles = new File[patchJarFiles.size()];
    aPatchFiles = patchJarFiles.toArray(aPatchFiles);
    File mergePatchFile = null;
    if (null != aPatchFiles && aPatchFiles.length > 1) {
        MergePatch mergePatch = new MergePatch(aPatchFiles, "com_taobao_android", outDir);
        mergePatchFile = mergePatch.doMerge();
    } else if (null != aPatchFiles && aPatchFiles.length == 1) {
        mergePatchFile = aPatchFiles[0];
    }
    if (null != mergePatchFile && mergePatchFile.exists()) {
        FileUtils.moveFile(mergePatchFile, outPatchFile);
    }
}
Also used : DexBackedMethod(org.jf.dexlib2.dexbacked.DexBackedMethod) CertificateException(java.security.cert.CertificateException) NoSuchAlgorithmException(java.security.NoSuchAlgorithmException) DexBackedClassDef(org.jf.dexlib2.dexbacked.DexBackedClassDef) InsTructionsReIClassDef(com.taobao.android.repatch.InsTructionsReIClassDef) ClassDef(org.jf.dexlib2.iface.ClassDef) MappingReader(com.taobao.android.repatch.mapping.MappingReader) UnrecoverableEntryException(java.security.UnrecoverableEntryException) Nonnull(javax.annotation.Nonnull) AndFixFilterImpl(com.taobao.android.apatch.AndFixFilterImpl) MappingClassProcessor(com.taobao.android.repatch.processor.MappingClassProcessor) Method(org.jf.dexlib2.iface.Method) DexBackedMethod(org.jf.dexlib2.dexbacked.DexBackedMethod) KeyStoreException(java.security.KeyStoreException) FastBuild(com.taobao.android.apatch.FastBuild) ImmutableDexFile(org.jf.dexlib2.immutable.ImmutableDexFile) DexFile(org.jf.dexlib2.iface.DexFile) DexDiffInfo(com.taobao.android.object.DexDiffInfo) FastPatchObject(com.taobao.android.repatch.FastPatchObject) MappingProcessor(com.taobao.android.repatch.mapping.MappingProcessor) MappingProcessorImpl(com.taobao.android.repatch.mapping.MappingProcessorImpl) InsTructionsReIClassDef(com.taobao.android.repatch.InsTructionsReIClassDef) ImmutableDexFile(org.jf.dexlib2.immutable.ImmutableDexFile) File(java.io.File) DexFile(org.jf.dexlib2.iface.DexFile) ImmutableDexFile(org.jf.dexlib2.immutable.ImmutableDexFile) MergePatch(com.taobao.android.apatch.MergePatch)

Aggregations

DexBackedClassDef (org.jf.dexlib2.dexbacked.DexBackedClassDef)19 IndentingWriter (org.jf.util.IndentingWriter)9 HashSet (java.util.HashSet)7 File (java.io.File)6 DexBackedDexFile (org.jf.dexlib2.dexbacked.DexBackedDexFile)6 ClassFileNameHandler (org.jf.util.ClassFileNameHandler)4 IOException (java.io.IOException)3 DexBackedMethod (org.jf.dexlib2.dexbacked.DexBackedMethod)3 Method (org.jf.dexlib2.iface.Method)3 MethodReplaceAnnotation (com.taobao.android.apatch.annotation.MethodReplaceAnnotation)2 PatchException (com.taobao.android.differ.dex.PatchException)2 Set (java.util.Set)2 Nonnull (javax.annotation.Nonnull)2 NotNull (org.jetbrains.annotations.NotNull)2 Field (org.jf.dexlib2.iface.Field)2 MethodImplementation (org.jf.dexlib2.iface.MethodImplementation)2 MethodReference (org.jf.dexlib2.iface.reference.MethodReference)2 EncodedValue (org.jf.dexlib2.iface.value.EncodedValue)2 DexClassNode (com.googlecode.d2j.node.DexClassNode)1 AndFixFilterImpl (com.taobao.android.apatch.AndFixFilterImpl)1