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;
}
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();
}
}
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;
}
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());
}
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());
}
}
}
Aggregations