Search in sources :

Example 1 with DexBackedField

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

the class DexDiffer method compareFields.

/**
 * compare filed in two dex Files
 *
 * @param baseClassDef
 * @param newClassDef
 * @param classDiffInfo
 */
private boolean compareFields(DexBackedClassDef baseClassDef, DexBackedClassDef newClassDef, ClassDiffInfo classDiffInfo) throws PatchException {
    Map<String, DexBackedField> baseFieldMaps = Maps.newHashMap();
    for (DexBackedField backedField : baseClassDef.getFields()) {
        baseFieldMaps.put(ReferenceUtil.getFieldDescriptor(backedField), backedField);
    }
    for (DexBackedField newField : newClassDef.getFields()) {
        FieldDiffInfo fieldDiffInfo = new FieldDiffInfo();
        fieldDiffInfo.setBackedField(newField);
        String fieldDesc = ReferenceUtil.getFieldDescriptor(newField);
        DexBackedField baseField = baseFieldMaps.get(fieldDesc);
        if (null == baseField) {
            fieldDiffInfo.setType(DiffType.ADD);
            classDiffInfo.getModifyFields().add(fieldDiffInfo);
            continue;
        }
        // init value
        EncodedValue baseInitaValue = baseField.getInitialValue();
        EncodedValue newInitaValue = newField.getInitialValue();
        if (!Objects.equal(baseInitaValue, newInitaValue)) {
            fieldDiffInfo.setType(DiffType.MODIFY);
            classDiffInfo.getModifyFields().add(fieldDiffInfo);
            baseFieldMaps.remove(fieldDesc);
            continue;
        }
        // annotation
        Set<? extends DexBackedAnnotation> backedAnnotations = baseField.getAnnotations();
        if (!equalsImpl(backedAnnotations, newField.getAnnotations())) {
            fieldDiffInfo.setType(DiffType.MODIFY);
            classDiffInfo.getModifyFields().add(fieldDiffInfo);
            baseFieldMaps.remove(fieldDesc);
            continue;
        }
        // type
        if (!baseField.getType().equals(newField.getType())) {
            fieldDiffInfo.setType(DiffType.MODIFY);
            classDiffInfo.getModifyFields().add(fieldDiffInfo);
            baseFieldMaps.remove(fieldDesc);
            continue;
        }
        if (baseField.getAccessFlags() != newField.getAccessFlags()) {
            fieldDiffInfo.setType(DiffType.MODIFY);
            classDiffInfo.getModifyFields().add(fieldDiffInfo);
            baseFieldMaps.remove(fieldDesc);
            continue;
        }
        baseFieldMaps.remove(fieldDesc);
    }
    // if member is removed
    if (baseFieldMaps.size() > 0) {
        for (Map.Entry<String, DexBackedField> entry : baseFieldMaps.entrySet()) {
            FieldDiffInfo fieldDiffInfo = new FieldDiffInfo();
            fieldDiffInfo.setBackedField(entry.getValue());
            fieldDiffInfo.setType(DiffType.REMOVE);
            classDiffInfo.getModifyFields().add(fieldDiffInfo);
        }
    }
    if (classDiffInfo.getModifyFields().size() > 0) {
        return true;
    }
    return false;
}
Also used : EncodedValue(org.jf.dexlib2.iface.value.EncodedValue)

Example 2 with DexBackedField

use of org.jf.dexlib2.dexbacked.DexBackedField in project smali by JesusFreke.

the class DexBackedClassDef method getStaticFields.

@Nonnull
public Iterable<? extends DexBackedField> getStaticFields(final boolean skipDuplicates) {
    if (staticFieldCount > 0) {
        DexReader<? extends DexBuffer> reader = dexFile.getDataBuffer().readerAt(staticFieldsOffset);
        final AnnotationsDirectory annotationsDirectory = getAnnotationsDirectory();
        final int staticInitialValuesOffset = dexFile.getBuffer().readSmallUint(classDefOffset + ClassDefItem.STATIC_VALUES_OFFSET);
        final int fieldsStartOffset = reader.getOffset();
        Iterator<Integer> hiddenApiRestrictionIterator = hiddenApiRestrictionsReader == null ? null : hiddenApiRestrictionsReader.getRestrictionsForStaticFields();
        return new Iterable<DexBackedField>() {

            @Nonnull
            @Override
            public Iterator<DexBackedField> iterator() {
                final AnnotationsDirectory.AnnotationIterator annotationIterator = annotationsDirectory.getFieldAnnotationIterator();
                final EncodedArrayItemIterator staticInitialValueIterator = EncodedArrayItemIterator.newOrEmpty(dexFile, staticInitialValuesOffset);
                return new VariableSizeLookaheadIterator<DexBackedField>(dexFile.getDataBuffer(), fieldsStartOffset) {

                    private int count;

                    @Nullable
                    private FieldReference previousField;

                    private int previousIndex;

                    @Nullable
                    @Override
                    protected DexBackedField readNextItem(@Nonnull DexReader reader) {
                        while (true) {
                            if (++count > staticFieldCount) {
                                instanceFieldsOffset = reader.getOffset();
                                return endOfData();
                            }
                            int hiddenApiRestrictions = NO_HIDDEN_API_RESTRICTIONS;
                            if (hiddenApiRestrictionIterator != null) {
                                hiddenApiRestrictions = hiddenApiRestrictionIterator.next();
                            }
                            DexBackedField item = new DexBackedField(dexFile, reader, DexBackedClassDef.this, previousIndex, staticInitialValueIterator, annotationIterator, hiddenApiRestrictions);
                            FieldReference currentField = previousField;
                            FieldReference nextField = ImmutableFieldReference.of(item);
                            previousField = nextField;
                            previousIndex = item.fieldIndex;
                            if (skipDuplicates && currentField != null && currentField.equals(nextField)) {
                                continue;
                            }
                            return item;
                        }
                    }
                };
            }
        };
    } else {
        instanceFieldsOffset = staticFieldsOffset;
        return ImmutableSet.of();
    }
}
Also used : ImmutableFieldReference(org.jf.dexlib2.immutable.reference.ImmutableFieldReference) FieldReference(org.jf.dexlib2.iface.reference.FieldReference) Nonnull(javax.annotation.Nonnull) AnnotationsDirectory(org.jf.dexlib2.dexbacked.util.AnnotationsDirectory) VariableSizeLookaheadIterator(org.jf.dexlib2.dexbacked.util.VariableSizeLookaheadIterator) EncodedArrayItemIterator(org.jf.dexlib2.dexbacked.util.EncodedArrayItemIterator) Nonnull(javax.annotation.Nonnull)

Example 3 with DexBackedField

use of org.jf.dexlib2.dexbacked.DexBackedField in project smali by JesusFreke.

the class DexBackedClassDef method getSize.

/**
 * Calculate and return the private size of a class definition.
 *
 * Calculated as: class_def_item size + type_id size + interfaces type_list +
 * annotations_directory_item overhead + class_data_item + static values overhead +
 * methods size + fields size
 *
 * @return size in bytes
 */
public int getSize() {
    // class_def_item has 8 uint fields in dex files
    int size = 8 * 4;
    // type_ids size
    size += TypeIdItem.ITEM_SIZE;
    // add interface list size if any
    int interfacesLength = getInterfaces().size();
    if (interfacesLength > 0) {
        // add size of the type_list
        // uint for size
        size += 4;
        // ushort per type_item
        size += interfacesLength * 2;
    }
    // annotations directory size if it exists
    AnnotationsDirectory directory = getAnnotationsDirectory();
    if (!AnnotationsDirectory.EMPTY.equals(directory)) {
        // 4 uints in annotations_directory_item
        size += 4 * 4;
        Set<? extends DexBackedAnnotation> classAnnotations = directory.getClassAnnotations();
        if (!classAnnotations.isEmpty()) {
            // uint for size
            size += 4;
            // uint per annotation_off
            size += classAnnotations.size() * 4;
        // TODO: should we add annotation_item size? what if it's shared?
        }
    }
    // static values and/or metadata
    int staticInitialValuesOffset = dexFile.getBuffer().readSmallUint(classDefOffset + ClassDefItem.STATIC_VALUES_OFFSET);
    if (staticInitialValuesOffset != 0) {
        DexReader reader = dexFile.getDataBuffer().readerAt(staticInitialValuesOffset);
        // encoded_array size field
        size += reader.peekSmallUleb128Size();
    }
    // class_data_item
    int classDataOffset = dexFile.getBuffer().readSmallUint(classDefOffset + ClassDefItem.CLASS_DATA_OFFSET);
    if (classDataOffset > 0) {
        DexReader reader = dexFile.getDataBuffer().readerAt(classDataOffset);
        // staticFieldCount
        reader.readSmallUleb128();
        // instanceFieldCount
        reader.readSmallUleb128();
        // directMethodCount
        reader.readSmallUleb128();
        // virtualMethodCount
        reader.readSmallUleb128();
        size += reader.getOffset() - classDataOffset;
    }
    for (DexBackedField dexBackedField : getFields()) {
        size += dexBackedField.getSize();
    }
    for (DexBackedMethod dexBackedMethod : getMethods()) {
        size += dexBackedMethod.getSize();
    }
    return size;
}
Also used : AnnotationsDirectory(org.jf.dexlib2.dexbacked.util.AnnotationsDirectory)

Example 4 with DexBackedField

use of org.jf.dexlib2.dexbacked.DexBackedField in project android-bundle-support by lizhangqu.

the class PackageTreeCreator method constructPackageTree.

public void constructPackageTree(@NonNull io.github.lizhangqu.intellij.android.bundle.analyzer.dex.tree.DexPackageNode root, @Nullable Path dexFilePath, @NonNull DexBackedDexFile dexFile) {
    // get all methods, fields and types referenced in this dex (includes defined)
    Multimap<String, MethodReference> methodRefsByClassName = getAllMethodReferencesByClassName(dexFile);
    Multimap<String, FieldReference> fieldRefsByClassName = getAllFieldReferencesByClassName(dexFile);
    Map<String, TypeReference> typeRefsByName = getAllTypeReferencesByClassName(dexFile);
    // remove methods and fields that are defined in this dex from the maps
    for (DexBackedClassDef classDef : dexFile.getClasses()) {
        for (DexBackedMethod method : classDef.getMethods()) {
            methodRefsByClassName.remove(classDef.getType(), method);
        }
        for (DexBackedField field : classDef.getFields()) {
            fieldRefsByClassName.remove(classDef.getType(), field);
        }
    }
    // add classes (and their methods and fields) defined in this file to the tree
    for (DexBackedClassDef classDef : dexFile.getClasses()) {
        TypeReference typeRef = typeRefsByName.get(classDef.getType());
        String className = decodeClassName(classDef.getType(), proguardMap);
        io.github.lizhangqu.intellij.android.bundle.analyzer.dex.tree.DexClassNode classNode = root.getOrCreateClass("", className, typeRef);
        classNode.setUserObject(dexFilePath);
        classNode.setDefined(true);
        classNode.setSize(classNode.getSize() + classDef.getSize());
        addMethods(classNode, classDef.getMethods(), dexFilePath);
        addFields(classNode, classDef.getFields(), dexFilePath);
    }
    // add method references which are not in a class defined in this dex file to the tree
    for (String className : methodRefsByClassName.keySet()) {
        TypeReference typeRef = typeRefsByName.get(className);
        String cleanClassName = decodeClassName(className, proguardMap);
        io.github.lizhangqu.intellij.android.bundle.analyzer.dex.tree.DexClassNode classNode = root.getOrCreateClass("", cleanClassName, typeRef);
        addMethods(classNode, methodRefsByClassName.get(className), dexFilePath);
    }
    // add field references which are not in a class defined in this dex file
    for (String className : fieldRefsByClassName.keySet()) {
        TypeReference typeRef = typeRefsByName.get(className);
        String cleanClassName = decodeClassName(className, proguardMap);
        io.github.lizhangqu.intellij.android.bundle.analyzer.dex.tree.DexClassNode classNode = root.getOrCreateClass("", cleanClassName, typeRef);
        addFields(classNode, fieldRefsByClassName.get(className), dexFilePath);
    }
    // add classes, methods and fields removed by Proguard
    if (usagesMap != null) {
        for (String className : usagesMap.getClasses()) {
            io.github.lizhangqu.intellij.android.bundle.analyzer.dex.tree.DexClassNode classNode = root.getOrCreateClass("", className, null);
            classNode.setDefined(false);
            classNode.setRemoved(true);
        }
        Multimap<String, String> removedMethodsByClass = usagesMap.getMethodsByClass();
        for (String className : removedMethodsByClass.keySet()) {
            io.github.lizhangqu.intellij.android.bundle.analyzer.dex.tree.DexClassNode classNode = root.getOrCreateClass("", className, null);
            for (String removedMethodName : removedMethodsByClass.get(className)) {
                io.github.lizhangqu.intellij.android.bundle.analyzer.dex.tree.DexMethodNode methodNode = new io.github.lizhangqu.intellij.android.bundle.analyzer.dex.tree.DexMethodNode(removedMethodName, null);
                methodNode.setDefined(false);
                methodNode.setRemoved(true);
                classNode.add(methodNode);
            }
        }
        Multimap<String, String> removedFieldsByClass = usagesMap.getFieldsByClass();
        for (String className : removedFieldsByClass.keySet()) {
            io.github.lizhangqu.intellij.android.bundle.analyzer.dex.tree.DexClassNode classNode = root.getOrCreateClass("", className, null);
            for (String removedFieldName : removedFieldsByClass.get(className)) {
                io.github.lizhangqu.intellij.android.bundle.analyzer.dex.tree.DexFieldNode fieldNode = new io.github.lizhangqu.intellij.android.bundle.analyzer.dex.tree.DexFieldNode(removedFieldName, null);
                fieldNode.setDefined(false);
                fieldNode.setRemoved(true);
                classNode.add(fieldNode);
            }
        }
    }
    root.update();
    root.sort(Comparator.comparing(io.github.lizhangqu.intellij.android.bundle.analyzer.dex.tree.DexElementNode::getMethodReferencesCount).reversed());
}
Also used : DexClassNode(io.github.lizhangqu.intellij.android.bundle.analyzer.dex.tree.DexClassNode) DexBackedMethod(org.jf.dexlib2.dexbacked.DexBackedMethod) DexBackedField(org.jf.dexlib2.dexbacked.DexBackedField) TypeReference(org.jf.dexlib2.iface.reference.TypeReference) DexBackedTypeReference(org.jf.dexlib2.dexbacked.reference.DexBackedTypeReference) DexBackedClassDef(org.jf.dexlib2.dexbacked.DexBackedClassDef) DexBackedFieldReference(org.jf.dexlib2.dexbacked.reference.DexBackedFieldReference) FieldReference(org.jf.dexlib2.iface.reference.FieldReference) ImmutableFieldReference(org.jf.dexlib2.immutable.reference.ImmutableFieldReference) DexBackedMethodReference(org.jf.dexlib2.dexbacked.reference.DexBackedMethodReference) ImmutableMethodReference(org.jf.dexlib2.immutable.reference.ImmutableMethodReference) MethodReference(org.jf.dexlib2.iface.reference.MethodReference)

Example 5 with DexBackedField

use of org.jf.dexlib2.dexbacked.DexBackedField in project android-bundle-support by lizhangqu.

the class PackageTreeCreator method addFields.

private void addFields(@NonNull DexClassNode classNode, @NonNull Iterable<? extends FieldReference> fieldRefs, Path dexFilePath) {
    for (FieldReference fieldRef : fieldRefs) {
        String fieldName = decodeFieldName(fieldRef, proguardMap);
        String fieldType = decodeClassName(fieldRef.getType(), proguardMap);
        String fieldSig = fieldType + " " + fieldName;
        io.github.lizhangqu.intellij.android.bundle.analyzer.dex.tree.DexFieldNode fieldNode = classNode.getChildByType(fieldSig, io.github.lizhangqu.intellij.android.bundle.analyzer.dex.tree.DexFieldNode.class);
        if (fieldNode == null) {
            fieldNode = new io.github.lizhangqu.intellij.android.bundle.analyzer.dex.tree.DexFieldNode(fieldSig, ImmutableFieldReference.of(fieldRef));
            classNode.add(fieldNode);
        }
        if (fieldRef instanceof DexBackedField) {
            fieldNode.setDefined(true);
            fieldNode.setUserObject(dexFilePath);
            fieldNode.setSize(fieldNode.getSize() + ((DexBackedField) fieldRef).getSize());
        } else if (fieldRef instanceof DexBackedFieldReference) {
            fieldNode.setSize(fieldNode.getSize() + ((DexBackedFieldReference) fieldRef).getSize());
        }
    }
}
Also used : DexBackedFieldReference(org.jf.dexlib2.dexbacked.reference.DexBackedFieldReference) FieldReference(org.jf.dexlib2.iface.reference.FieldReference) ImmutableFieldReference(org.jf.dexlib2.immutable.reference.ImmutableFieldReference) DexBackedFieldReference(org.jf.dexlib2.dexbacked.reference.DexBackedFieldReference) DexBackedField(org.jf.dexlib2.dexbacked.DexBackedField)

Aggregations

FieldReference (org.jf.dexlib2.iface.reference.FieldReference)5 ImmutableFieldReference (org.jf.dexlib2.immutable.reference.ImmutableFieldReference)4 DexBackedFieldReference (org.jf.dexlib2.dexbacked.reference.DexBackedFieldReference)3 AnnotationsDirectory (org.jf.dexlib2.dexbacked.util.AnnotationsDirectory)3 Nonnull (javax.annotation.Nonnull)2 DexBackedField (org.jf.dexlib2.dexbacked.DexBackedField)2 DexBackedMethodReference (org.jf.dexlib2.dexbacked.reference.DexBackedMethodReference)2 DexBackedTypeReference (org.jf.dexlib2.dexbacked.reference.DexBackedTypeReference)2 VariableSizeLookaheadIterator (org.jf.dexlib2.dexbacked.util.VariableSizeLookaheadIterator)2 MethodReference (org.jf.dexlib2.iface.reference.MethodReference)2 TypeReference (org.jf.dexlib2.iface.reference.TypeReference)2 DexClassNode (io.github.lizhangqu.intellij.android.bundle.analyzer.dex.tree.DexClassNode)1 DexBackedClassDef (org.jf.dexlib2.dexbacked.DexBackedClassDef)1 DexBackedMethod (org.jf.dexlib2.dexbacked.DexBackedMethod)1 EncodedArrayItemIterator (org.jf.dexlib2.dexbacked.util.EncodedArrayItemIterator)1 Annotation (org.jf.dexlib2.iface.Annotation)1 DualReferenceInstruction (org.jf.dexlib2.iface.instruction.DualReferenceInstruction)1 Instruction (org.jf.dexlib2.iface.instruction.Instruction)1 ReferenceInstruction (org.jf.dexlib2.iface.instruction.ReferenceInstruction)1 Reference (org.jf.dexlib2.iface.reference.Reference)1