Search in sources :

Example 1 with BuilderMethod

use of org.jf.dexlib2.writer.builder.BuilderMethod in project smali by JesusFreke.

the class CallSiteTest method testBuilderCallSite.

@Test
public void testBuilderCallSite() throws IOException {
    DexBuilder dexBuilder = new DexBuilder(Opcodes.forArtVersion(111));
    BuilderCallSiteReference callSite = dexBuilder.internCallSite(new ImmutableCallSiteReference("call_site_1", new ImmutableMethodHandleReference(MethodHandleType.INVOKE_STATIC, new ImmutableMethodReference("Lcls1;", "loader", ImmutableList.of("Ljava/lang/invoke/Lookup;", "Ljava/lang/String;", "Ljava/lang/invoke/MethodType;"), "Ljava/lang/invoke/CallSite;")), "someMethod", new ImmutableMethodProtoReference(ImmutableList.of(), "V"), ImmutableList.of()));
    MethodImplementationBuilder methodImplementationBuilder = new MethodImplementationBuilder(10);
    methodImplementationBuilder.addInstruction(new BuilderInstruction35c(Opcode.INVOKE_CUSTOM, 0, 0, 0, 0, 0, 0, callSite));
    BuilderMethod method = dexBuilder.internMethod("Lcls1;", "method1", null, "V", 0, ImmutableSet.of(), ImmutableSet.of(), methodImplementationBuilder.getMethodImplementation());
    dexBuilder.internClassDef("Lcls1;", AccessFlags.PUBLIC.getValue(), "Ljava/lang/Object;", null, null, ImmutableSet.of(), null, ImmutableList.of(method));
    File tempFile = File.createTempFile("dex", ".dex");
    dexBuilder.writeTo(new FileDataStore(tempFile));
    verifyDexFile(DexFileFactory.loadDexFile(tempFile, Opcodes.forArtVersion(111)));
}
Also used : ImmutableMethodProtoReference(org.jf.dexlib2.immutable.reference.ImmutableMethodProtoReference) ImmutableMethodReference(org.jf.dexlib2.immutable.reference.ImmutableMethodReference) ImmutableMethodHandleReference(org.jf.dexlib2.immutable.reference.ImmutableMethodHandleReference) BuilderInstruction35c(org.jf.dexlib2.builder.instruction.BuilderInstruction35c) BuilderMethod(org.jf.dexlib2.writer.builder.BuilderMethod) ImmutableDexFile(org.jf.dexlib2.immutable.ImmutableDexFile) File(java.io.File) DexFile(org.jf.dexlib2.iface.DexFile) FileDataStore(org.jf.dexlib2.writer.io.FileDataStore) BuilderCallSiteReference(org.jf.dexlib2.writer.builder.BuilderCallSiteReference) MethodImplementationBuilder(org.jf.dexlib2.builder.MethodImplementationBuilder) DexBuilder(org.jf.dexlib2.writer.builder.DexBuilder) ImmutableCallSiteReference(org.jf.dexlib2.immutable.reference.ImmutableCallSiteReference) Test(org.junit.Test)

Example 2 with BuilderMethod

use of org.jf.dexlib2.writer.builder.BuilderMethod in project tinker by Tencent.

the class DexDiffDecoder method generateChangedClassesDexFile.

@SuppressWarnings("NewApi")
private void generateChangedClassesDexFile() throws IOException {
    final String dexMode = config.mDexRaw ? "raw" : "jar";
    List<File> oldDexList = new ArrayList<>();
    List<File> newDexList = new ArrayList<>();
    for (AbstractMap.SimpleEntry<File, File> oldAndNewDexFilePair : oldAndNewDexFilePairList) {
        File oldDexFile = oldAndNewDexFilePair.getKey();
        File newDexFile = oldAndNewDexFilePair.getValue();
        if (oldDexFile != null) {
            oldDexList.add(oldDexFile);
        }
        if (newDexFile != null) {
            newDexList.add(newDexFile);
        }
    }
    DexGroup oldDexGroup = DexGroup.wrap(oldDexList);
    DexGroup newDexGroup = DexGroup.wrap(newDexList);
    ChangedClassesDexClassInfoCollector collector = new ChangedClassesDexClassInfoCollector();
    collector.setExcludedClassPatterns(config.mDexLoaderPattern);
    collector.setLogger(dexPatcherLoggerBridge);
    collector.setIncludeRefererToRefererAffectedClasses(true);
    Set<DexClassInfo> classInfosInChangedClassesDex = collector.doCollect(oldDexGroup, newDexGroup);
    Set<Dex> owners = new HashSet<>();
    Map<Dex, Set<String>> ownerToDescOfChangedClassesMap = new HashMap<>();
    for (DexClassInfo classInfo : classInfosInChangedClassesDex) {
        owners.add(classInfo.owner);
        Set<String> descOfChangedClasses = ownerToDescOfChangedClassesMap.get(classInfo.owner);
        if (descOfChangedClasses == null) {
            descOfChangedClasses = new HashSet<>();
            ownerToDescOfChangedClassesMap.put(classInfo.owner, descOfChangedClasses);
        }
        descOfChangedClasses.add(classInfo.classDesc);
    }
    StringBuilder metaBuilder = new StringBuilder();
    int changedDexId = 1;
    for (Dex dex : owners) {
        Set<String> descOfChangedClassesInCurrDex = ownerToDescOfChangedClassesMap.get(dex);
        DexFile dexFile = new DexBackedDexFile(org.jf.dexlib2.Opcodes.forApi(20), dex.getBytes());
        boolean isCurrentDexHasChangedClass = false;
        for (org.jf.dexlib2.iface.ClassDef classDef : dexFile.getClasses()) {
            if (descOfChangedClassesInCurrDex.contains(classDef.getType())) {
                isCurrentDexHasChangedClass = true;
                break;
            }
        }
        if (!isCurrentDexHasChangedClass) {
            continue;
        }
        DexBuilder dexBuilder = new DexBuilder(Opcodes.forApi(23));
        for (org.jf.dexlib2.iface.ClassDef classDef : dexFile.getClasses()) {
            if (!descOfChangedClassesInCurrDex.contains(classDef.getType())) {
                continue;
            }
            Logger.d("Class %s will be added into changed classes dex ...", classDef.getType());
            List<BuilderField> builderFields = new ArrayList<>();
            for (Field field : classDef.getFields()) {
                final BuilderField builderField = dexBuilder.internField(field.getDefiningClass(), field.getName(), field.getType(), field.getAccessFlags(), field.getInitialValue(), field.getAnnotations());
                builderFields.add(builderField);
            }
            List<BuilderMethod> builderMethods = new ArrayList<>();
            for (Method method : classDef.getMethods()) {
                MethodImplementation methodImpl = method.getImplementation();
                if (methodImpl != null) {
                    methodImpl = new BuilderMutableMethodImplementation(dexBuilder, methodImpl);
                }
                BuilderMethod builderMethod = dexBuilder.internMethod(method.getDefiningClass(), method.getName(), method.getParameters(), method.getReturnType(), method.getAccessFlags(), method.getAnnotations(), methodImpl);
                builderMethods.add(builderMethod);
            }
            dexBuilder.internClassDef(classDef.getType(), classDef.getAccessFlags(), classDef.getSuperclass(), classDef.getInterfaces(), classDef.getSourceFile(), classDef.getAnnotations(), builderFields, builderMethods);
        }
        // Write constructed changed classes dex to file and record it in meta file.
        String changedDexName = null;
        if (changedDexId == 1) {
            changedDexName = "classes.dex";
        } else {
            changedDexName = "classes" + changedDexId + ".dex";
        }
        final File dest = new File(config.mTempResultDir + "/" + changedDexName);
        final FileDataStore fileDataStore = new FileDataStore(dest);
        dexBuilder.writeTo(fileDataStore);
        final String md5 = MD5.getMD5(dest);
        appendMetaLine(metaBuilder, changedDexName, "", md5, md5, 0, 0, 0, dexMode);
        ++changedDexId;
    }
    final String meta = metaBuilder.toString();
    Logger.d("\nDexDecoder:write changed classes dex meta file data:\n%s", meta);
    metaWriter.writeLineToInfoFile(meta);
}
Also used : DexGroup(com.tencent.tinker.build.util.DexClassesComparator.DexGroup) MethodImplementation(org.jf.dexlib2.iface.MethodImplementation) BuilderMutableMethodImplementation(org.jf.dexlib2.builder.BuilderMutableMethodImplementation) Set(java.util.Set) HashSet(java.util.HashSet) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) AbstractMap(java.util.AbstractMap) BuilderField(org.jf.dexlib2.writer.builder.BuilderField) Field(org.jf.dexlib2.iface.Field) BuilderField(org.jf.dexlib2.writer.builder.BuilderField) FileDataStore(org.jf.dexlib2.writer.io.FileDataStore) HashSet(java.util.HashSet) DexBackedDexFile(org.jf.dexlib2.dexbacked.DexBackedDexFile) ChangedClassesDexClassInfoCollector(com.tencent.tinker.build.dexpatcher.util.ChangedClassesDexClassInfoCollector) BuilderMutableMethodImplementation(org.jf.dexlib2.builder.BuilderMutableMethodImplementation) Method(org.jf.dexlib2.iface.Method) BuilderMethod(org.jf.dexlib2.writer.builder.BuilderMethod) DexFile(org.jf.dexlib2.iface.DexFile) DexBackedDexFile(org.jf.dexlib2.dexbacked.DexBackedDexFile) DexBuilder(org.jf.dexlib2.writer.builder.DexBuilder) Dex(com.tencent.tinker.android.dex.Dex) BuilderMethod(org.jf.dexlib2.writer.builder.BuilderMethod) JarFile(java.util.jar.JarFile) DexFile(org.jf.dexlib2.iface.DexFile) DexBackedDexFile(org.jf.dexlib2.dexbacked.DexBackedDexFile) File(java.io.File) DexClassInfo(com.tencent.tinker.build.util.DexClassesComparator.DexClassInfo)

Aggregations

File (java.io.File)2 DexFile (org.jf.dexlib2.iface.DexFile)2 BuilderMethod (org.jf.dexlib2.writer.builder.BuilderMethod)2 DexBuilder (org.jf.dexlib2.writer.builder.DexBuilder)2 FileDataStore (org.jf.dexlib2.writer.io.FileDataStore)2 Dex (com.tencent.tinker.android.dex.Dex)1 ChangedClassesDexClassInfoCollector (com.tencent.tinker.build.dexpatcher.util.ChangedClassesDexClassInfoCollector)1 DexClassInfo (com.tencent.tinker.build.util.DexClassesComparator.DexClassInfo)1 DexGroup (com.tencent.tinker.build.util.DexClassesComparator.DexGroup)1 AbstractMap (java.util.AbstractMap)1 ArrayList (java.util.ArrayList)1 HashMap (java.util.HashMap)1 HashSet (java.util.HashSet)1 Set (java.util.Set)1 JarFile (java.util.jar.JarFile)1 BuilderMutableMethodImplementation (org.jf.dexlib2.builder.BuilderMutableMethodImplementation)1 MethodImplementationBuilder (org.jf.dexlib2.builder.MethodImplementationBuilder)1 BuilderInstruction35c (org.jf.dexlib2.builder.instruction.BuilderInstruction35c)1 DexBackedDexFile (org.jf.dexlib2.dexbacked.DexBackedDexFile)1 Field (org.jf.dexlib2.iface.Field)1