- Added the ability to sort the offsetted sections in a way that guarantees a unique order for a given set of items (helpful when trying to compare dex files)

- Fixed an issue with decodeLong in NumberUtils


git-svn-id: https://smali.googlecode.com/svn/trunk@209 55b6fa8a-2a1e-11de-a435-ffa8d773f76a
This commit is contained in:
JesusFreke@JesusFreke.com 2009-06-22 07:57:13 +00:00
parent 6ccb8b3d2b
commit ec857fcecd
27 changed files with 347 additions and 36 deletions

View File

@ -44,6 +44,14 @@ public class AnnotationDirectoryItem extends OffsettedItem<AnnotationDirectoryIt
private final FieldListField<FieldAnnotation> fieldAnnotationListField; private final FieldListField<FieldAnnotation> fieldAnnotationListField;
private final FieldListField<MethodAnnotation> methodAnnotationListField; private final FieldListField<MethodAnnotation> methodAnnotationListField;
private final FieldListField<ParameterAnnotation> parameterAnnotationListField; private final FieldListField<ParameterAnnotation> parameterAnnotationListField;
//typically each AnnotationDirectoryItem will have a distinct parent. The only case that isn't true is when
//the AnnotationDirectoryItem *only* contains class annotations, with no other type of annotation. In that
//case, the same AnnotationDirectoryItem could be references from multiple classes.
//This isn't a problem though, because this field is only used in compareTo to determine the sort order,
//which handles it as a special case
private ClassDefItem parent = null;
protected AnnotationDirectoryItem(final DexFile dexFile, int offset) { protected AnnotationDirectoryItem(final DexFile dexFile, int offset) {
super(offset); super(offset);
@ -135,6 +143,48 @@ public class AnnotationDirectoryItem extends OffsettedItem<AnnotationDirectoryIt
return Collections.unmodifiableList(parameterAnnotationList); return Collections.unmodifiableList(parameterAnnotationList);
} }
private boolean isInternable() {
//an instance is only internable if it has only class annotations, but
//no other type of annotation
if (classAnnotationsReferenceField.getReference() == null ||
fieldAnnotationList.size() > 0 ||
methodAnnotationList.size() > 0 ||
parameterAnnotationList.size() > 0) {
return false;
}
return true;
}
public int hashCode() {
//an instance is only internable if it has only class annotations, but
//no other type of annotation
if (!isInternable()) {
return super.hashCode();
}
return classAnnotationsReferenceField.getReference().hashCode();
}
protected void setParent(ClassDefItem classDefItem) {
this.parent = classDefItem;
}
public int compareTo(AnnotationDirectoryItem annotationDirectoryItem) {
if (!isInternable()) {
if (!annotationDirectoryItem.isInternable()) {
return parent.compareTo(annotationDirectoryItem.parent);
}
return -1;
}
if (!annotationDirectoryItem.isInternable()) {
return 1;
}
return classAnnotationsReferenceField.getReference().compareTo(
annotationDirectoryItem.classAnnotationsReferenceField.getReference());
}
public static class FieldAnnotation extends CompositeField<FieldAnnotation> public static class FieldAnnotation extends CompositeField<FieldAnnotation>
implements Comparable<FieldAnnotation> { implements Comparable<FieldAnnotation> {
private final IndexedItemReference<FieldIdItem> fieldReferenceField; private final IndexedItemReference<FieldIdItem> fieldReferenceField;

View File

@ -69,6 +69,14 @@ public class AnnotationItem extends OffsettedItem<AnnotationItem> {
return annotationField; return annotationField;
} }
public int compareTo(AnnotationItem annotationItem) {
int comp = ((Integer)visibilityField.getCachedValue()).compareTo(annotationItem.visibilityField.getCachedValue());
if (comp == 0) {
comp = annotationField.compareTo(annotationItem.annotationField);
}
return comp;
}
public enum Visibility { public enum Visibility {
build(0x00), build(0x00),
runtime(0x01), runtime(0x01),

View File

@ -83,4 +83,22 @@ public class AnnotationSetItem extends OffsettedItem<AnnotationSetItem> {
} }
return annotationItems; return annotationItems;
} }
public int compareTo(AnnotationSetItem annotationSetItem) {
if (annotationSetItem == null) {
return 1;
}
int comp = ((Integer)annotationReferences.size()).compareTo(annotationSetItem.annotationReferences.size());
if (comp == 0) {
for (int i=0; i<annotationReferences.size(); i++) {
comp = annotationReferences.get(i).getReference().compareTo(
annotationSetItem.annotationReferences.get(i).getReference());
if (comp != 0) {
break;
}
}
}
return comp;
}
} }

View File

@ -88,4 +88,18 @@ public class AnnotationSetRefList extends OffsettedItem<AnnotationSetRefList> {
return annotationSets; return annotationSets;
} }
public int compareTo(AnnotationSetRefList annotationSetRefList) {
int comp = ((Integer)annotationSetReferences.size()).compareTo(annotationSetRefList.annotationSetReferences.size());
if (comp == 0) {
for (int i=0; i<annotationSetReferences.size(); i++) {
comp = annotationSetReferences.get(i).getReference().compareTo(
annotationSetRefList.annotationSetReferences.get(i).getReference());
if (comp != 0) {
break;
}
}
}
return comp;
}
} }

View File

@ -49,6 +49,7 @@ public class ClassDataItem extends OffsettedItem<ClassDataItem> {
private final EncodedMemberList<EncodedMethod> directMethodsListField; private final EncodedMemberList<EncodedMethod> directMethodsListField;
private final EncodedMemberList<EncodedMethod> virtualMethodsListField; private final EncodedMemberList<EncodedMethod> virtualMethodsListField;
private ClassDefItem parent = null;
public ClassDataItem(final DexFile dexFile, int offset) { public ClassDataItem(final DexFile dexFile, int offset) {
super(offset); super(offset);
@ -310,6 +311,10 @@ public class ClassDataItem extends OffsettedItem<ClassDataItem> {
this.codeItemReferenceField = new OffsettedItemReference<CodeItem>(dexFile, codeItem, this.codeItemReferenceField = new OffsettedItemReference<CodeItem>(dexFile, codeItem,
new Leb128Field(null), "code_off") new Leb128Field(null), "code_off")
}; };
if (codeItem != null) {
codeItem.setParent(methodIdItem);
}
} }
protected void setPreviousMember(EncodedMethod previousMethod) { protected void setPreviousMember(EncodedMethod previousMethod) {
@ -329,6 +334,14 @@ public class ClassDataItem extends OffsettedItem<ClassDataItem> {
AccessFlags.CONSTRUCTOR.getValue())) != 0); AccessFlags.CONSTRUCTOR.getValue())) != 0);
} }
public void readFrom(Input in) {
super.readFrom(in);
CodeItem codeItem = codeItemReferenceField.getReference();
if (codeItem != null) {
codeItem.setParent(methodReferenceField.getReference());
}
}
public int getAccessFlags() { public int getAccessFlags() {
return accessFlagsField.getCachedValue(); return accessFlagsField.getCachedValue();
} }
@ -396,4 +409,21 @@ public class ClassDataItem extends OffsettedItem<ClassDataItem> {
public String getConciseIdentity() { public String getConciseIdentity() {
return "class_data_item @0x" + Integer.toHexString(getOffset()); return "class_data_item @0x" + Integer.toHexString(getOffset());
} }
protected void setParent(ClassDefItem classDefItem) {
this.parent = classDefItem;
}
public int compareTo(ClassDataItem other) {
if (parent == null) {
if (other.parent == null) {
return 0;
}
return -1;
}
if (other.parent == null) {
return 1;
}
return parent.compareTo(other.parent);
}
} }

View File

@ -31,10 +31,9 @@ package org.jf.dexlib;
import org.jf.dexlib.EncodedValue.EncodedValue; import org.jf.dexlib.EncodedValue.EncodedValue;
import org.jf.dexlib.EncodedValue.EncodedValueSubField; import org.jf.dexlib.EncodedValue.EncodedValueSubField;
import org.jf.dexlib.Util.TypeUtils; import org.jf.dexlib.Util.TypeUtils;
import org.jf.dexlib.Util.Input;
import java.util.ArrayList; import java.util.*;
import java.util.HashMap;
import java.util.List;
public class ClassDefItem extends IndexedItem<ClassDefItem> { public class ClassDefItem extends IndexedItem<ClassDefItem> {
private final IndexedItemReference<TypeIdItem> classTypeReferenceField; private final IndexedItemReference<TypeIdItem> classTypeReferenceField;
@ -90,6 +89,10 @@ public class ClassDefItem extends IndexedItem<ClassDefItem> {
classInterfacesListReferenceField.setReference(implementsList); classInterfacesListReferenceField.setReference(implementsList);
sourceFileReferenceField.setReference(source); sourceFileReferenceField.setReference(source);
classDataReferenceField.setReference(classDataItem); classDataReferenceField.setReference(classDataItem);
if (classDataItem != null) {
classDataItem.setParent(this);
}
} }
public TypeIdItem getSuperclass() { public TypeIdItem getSuperclass() {
@ -162,9 +165,10 @@ public class ClassDefItem extends IndexedItem<ClassDefItem> {
} }
public int compareTo(ClassDefItem o) { public int compareTo(ClassDefItem o) {
//sorting is implemented in SortClassDefItemSection, so this class doesn't //The actual sorting for this class is implemented in SortClassDefItemSection.
//need an implementation of compareTo //This method is just used for sorting the associated ClassDataItem items, so
return 0; //we can just do the comparison based on the offsets of the items
return ((Integer)this.offset).compareTo(o.offset);
} }
public void addField(ClassDataItem.EncodedField encodedField, EncodedValue initialValue) { public void addField(ClassDataItem.EncodedField encodedField, EncodedValue initialValue) {
@ -205,10 +209,28 @@ public class ClassDefItem extends IndexedItem<ClassDefItem> {
public void setAnnotations(AnnotationDirectoryItem annotations) { public void setAnnotations(AnnotationDirectoryItem annotations) {
this.classAnnotationsReferenceField.setReference(annotations); this.classAnnotationsReferenceField.setReference(annotations);
annotations.setParent(this);
} }
public void setClassDataItem(ClassDataItem classDataItem) { public void setClassDataItem(ClassDataItem classDataItem) {
this.classDataReferenceField.setReference(classDataItem); this.classDataReferenceField.setReference(classDataItem);
if (classDataItem != null) {
classDataItem.setParent(this);
}
}
public void readFrom(Input in, int index) {
super.readFrom(in, index);
ClassDataItem classDataItem = classDataReferenceField.getReference();
if (classDataItem != null) {
classDataItem.setParent(this);
}
AnnotationDirectoryItem annotationDirectoryItem = classAnnotationsReferenceField.getReference();
if (annotationDirectoryItem != null) {
annotationDirectoryItem.setParent(this);
}
} }
public static int placeClassDefItems(IndexedSection<ClassDefItem> section, int offset) { public static int placeClassDefItems(IndexedSection<ClassDefItem> section, int offset) {
@ -238,6 +260,18 @@ public class ClassDefItem extends IndexedItem<ClassDefItem> {
public int placeSection(int offset) { public int placeSection(int offset) {
currentOffset = offset; currentOffset = offset;
//presort the list, to guarantee a unique ordering
Collections.sort(section.items, new Comparator<ClassDefItem>() {
public int compare(ClassDefItem classDefItem, ClassDefItem classDefItem1) {
return classDefItem.getClassType().compareTo(classDefItem1.getClassType());
}
});
for (ClassDefItem classDefItem: section.items) {
classDefItem.offset = -1;
}
for (ClassDefItem classDefItem: section.items) { for (ClassDefItem classDefItem: section.items) {
placeClass(classDefItem); placeClass(classDefItem);
} }

View File

@ -54,6 +54,8 @@ public class CodeItem extends OffsettedItem<CodeItem> {
private final FieldListField<TryItem> triesListField; private final FieldListField<TryItem> triesListField;
private final EncodedCatchHandlerList catchHandlersListField; private final EncodedCatchHandlerList catchHandlersListField;
private MethodIdItem parent = null;
public CodeItem(final DexFile dexFile, int offset) { public CodeItem(final DexFile dexFile, int offset) {
super(offset); super(offset);
@ -105,6 +107,10 @@ public class CodeItem extends OffsettedItem<CodeItem> {
inArgumentCountField.cacheValue(inArguments); inArgumentCountField.cacheValue(inArguments);
outArgumentCountField.cacheValue(instructionListField.getOutArguments()); outArgumentCountField.cacheValue(instructionListField.getOutArguments());
debugInfoReferenceField.setReference(debugInfo); debugInfoReferenceField.setReference(debugInfo);
if (debugInfo != null) {
debugInfo.setParent(this);
}
} }
protected int getAlignment() { protected int getAlignment() {
@ -131,6 +137,10 @@ public class CodeItem extends OffsettedItem<CodeItem> {
return debugInfoReferenceField.getReference(); return debugInfoReferenceField.getReference();
} }
protected void setParent(MethodIdItem methodIdItem) {
this.parent = methodIdItem;
}
public void copyTo(DexFile dexFile, CodeItem copy) public void copyTo(DexFile dexFile, CodeItem copy)
{ {
for (int i = 0; i < fields.length-2; i++) { for (int i = 0; i < fields.length-2; i++) {
@ -140,6 +150,20 @@ public class CodeItem extends OffsettedItem<CodeItem> {
//the catchHandler copies will already exist //the catchHandler copies will already exist
catchHandlersListField.copyTo(dexFile, copy.catchHandlersListField); catchHandlersListField.copyTo(dexFile, copy.catchHandlersListField);
triesListField.copyTo(dexFile, copy.triesListField); triesListField.copyTo(dexFile, copy.triesListField);
DebugInfoItem copyDebugInfo = copy.getDebugInfo();
if (copy != null) {
copyDebugInfo.setParent(copy);
}
}
public void readFrom(Input in, int index) {
super.readFrom(in, index);
DebugInfoItem debugInfoItem = debugInfoReferenceField.getReference();
if (debugInfoItem != null) {
debugInfoItem.setParent(this);
}
} }
public String getConciseIdentity() { public String getConciseIdentity() {
@ -147,6 +171,19 @@ public class CodeItem extends OffsettedItem<CodeItem> {
return "code_item @0x" + Integer.toHexString(getOffset()); return "code_item @0x" + Integer.toHexString(getOffset());
} }
public int compareTo(CodeItem other) {
if (parent == null) {
if (other.parent == null) {
return 0;
}
return -1;
}
if (other.parent == null) {
return 1;
}
return parent.compareTo(other.parent);
}
public static class TryItem extends CompositeField<TryItem> { public static class TryItem extends CompositeField<TryItem> {
private final IntegerField startAddr; private final IntegerField startAddr;
private final ShortIntegerField insnCount; private final ShortIntegerField insnCount;

View File

@ -49,6 +49,8 @@ public class DebugInfoItem extends OffsettedItem<DebugInfoItem> {
private final FieldListField<IndexedItemReference<StringIdItem>> parameterNamesField; private final FieldListField<IndexedItemReference<StringIdItem>> parameterNamesField;
private final DebugInstructionList debugInstructionListField; private final DebugInstructionList debugInstructionListField;
private CodeItem parent = null;
public DebugInfoItem(final DexFile dexFile, int offset) { public DebugInfoItem(final DexFile dexFile, int offset) {
super(offset); super(offset);
@ -87,6 +89,10 @@ public class DebugInfoItem extends OffsettedItem<DebugInfoItem> {
return ItemType.TYPE_DEBUG_INFO_ITEM; return ItemType.TYPE_DEBUG_INFO_ITEM;
} }
protected void setParent(CodeItem codeItem) {
this.parent = codeItem;
}
public String getConciseIdentity() { public String getConciseIdentity() {
return "debug_info_item @0x" + Integer.toHexString(getOffset()); return "debug_info_item @0x" + Integer.toHexString(getOffset());
} }
@ -113,6 +119,18 @@ public class DebugInfoItem extends OffsettedItem<DebugInfoItem> {
return parameterNamesList; return parameterNamesList;
} }
public int compareTo(DebugInfoItem other) {
if (parent == null) {
if (other.parent == null) {
return 0;
}
return -1;
}
if (other.parent == null) {
return 1;
}
return parent.compareTo(other.parent);
}
private class DebugInstructionList implements Field<DebugInstructionList> { private class DebugInstructionList implements Field<DebugInstructionList> {

View File

@ -38,6 +38,7 @@ import java.security.DigestException;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.zip.Adler32; import java.util.zip.Adler32;
public class DexFile public class DexFile
@ -90,10 +91,10 @@ public class DexFile
AnnotationDirectoriesSection, AnnotationDirectoriesSection,
TypeListsSection, TypeListsSection,
StringDataSection, StringDataSection,
DebugInfoItemsSection,
AnnotationsSection, AnnotationsSection,
EncodedArraysSection, EncodedArraysSection,
ClassDataSection ClassDataSection,
DebugInfoItemsSection
}; };
} }
@ -135,9 +136,9 @@ public class DexFile
ItemType.TYPE_ANNOTATION_SET_REF_LIST.getMapValue(), ItemType.TYPE_ANNOTATION_SET_REF_LIST.getMapValue(),
ItemType.TYPE_ANNOTATIONS_DIRECTORY_ITEM.getMapValue(), ItemType.TYPE_ANNOTATIONS_DIRECTORY_ITEM.getMapValue(),
ItemType.TYPE_TYPE_LIST.getMapValue(), ItemType.TYPE_TYPE_LIST.getMapValue(),
ItemType.TYPE_DEBUG_INFO_ITEM.getMapValue(),
ItemType.TYPE_CODE_ITEM.getMapValue(), ItemType.TYPE_CODE_ITEM.getMapValue(),
ItemType.TYPE_CLASS_DATA_ITEM.getMapValue(), ItemType.TYPE_CLASS_DATA_ITEM.getMapValue(),
ItemType.TYPE_DEBUG_INFO_ITEM.getMapValue(),
ItemType.TYPE_MAP_LIST.getMapValue() ItemType.TYPE_MAP_LIST.getMapValue()
}; };
@ -191,7 +192,7 @@ public class DexFile
return forDumping; return forDumping;
} }
public void place() { public void place(boolean sort) {
int offset = 0; int offset = 0;
offset = HeaderItemSection.place(offset); offset = HeaderItemSection.place(offset);
@ -203,6 +204,9 @@ public class DexFile
dataOffset = offset; dataOffset = offset;
for (OffsettedSection offsettedSection: offsettedSections) { for (OffsettedSection offsettedSection: offsettedSections) {
if (sort) {
offsettedSection.sortSection();
}
offset = offsettedSection.place(offset); offset = offsettedSection.place(offset);
} }

View File

@ -72,4 +72,8 @@ public class EncodedArrayItem extends OffsettedItem<EncodedArrayItem> {
public ArrayEncodedValueSubField getEncodedArray() { public ArrayEncodedValueSubField getEncodedArray() {
return encodedArray; return encodedArray;
} }
public int compareTo(EncodedArrayItem encodedArrayItem) {
return encodedArray.compareTo(encodedArrayItem.encodedArray);
}
} }

View File

@ -54,7 +54,11 @@ public class AnnotationElement extends CompositeField<AnnotationElement>
} }
public int compareTo(AnnotationElement annotationElement) { public int compareTo(AnnotationElement annotationElement) {
return elementName.compareTo(annotationElement.elementName); int comp = elementName.compareTo(annotationElement.elementName);
if (comp == 0) {
comp = encodedValue.compareTo(annotationElement.encodedValue);
}
return comp;
} }
public StringIdItem getName() { public StringIdItem getName() {

View File

@ -35,7 +35,7 @@ import java.util.Collections;
import java.util.List; import java.util.List;
public class AnnotationEncodedValueSubField extends CompositeField<AnnotationEncodedValueSubField> public class AnnotationEncodedValueSubField extends CompositeField<AnnotationEncodedValueSubField>
implements EncodedValueSubField<AnnotationEncodedValueSubField> { implements EncodedValueSubField<AnnotationEncodedValueSubField>, Comparable<EncodedValueSubField> {
private final ArrayList<AnnotationElement> annotationElementList = new ArrayList<AnnotationElement>(); private final ArrayList<AnnotationElement> annotationElementList = new ArrayList<AnnotationElement>();
@ -88,4 +88,25 @@ public class AnnotationEncodedValueSubField extends CompositeField<AnnotationEnc
public List<AnnotationElement> getAnnotationElements() { public List<AnnotationElement> getAnnotationElements() {
return Collections.unmodifiableList(annotationElementList); return Collections.unmodifiableList(annotationElementList);
} }
public int compareTo(EncodedValueSubField t) {
int comp = getValueType().compareTo(t.getValueType());
if (comp == 0) {
AnnotationEncodedValueSubField other = (AnnotationEncodedValueSubField)t;
comp = annotationType.compareTo(other.annotationType);
if (comp == 0) {
comp = ((Integer)annotationElementList.size()).compareTo(other.annotationElementList.size());
if (comp == 0) {
for (int i=0; i<annotationElementList.size(); i++) {
comp = annotationElementList.get(i).compareTo(other.annotationElementList.get(i));
if (comp != 0) {
break;
}
}
}
}
}
return comp;
}
} }

View File

@ -35,7 +35,7 @@ import java.util.List;
import java.util.Collections; import java.util.Collections;
public class ArrayEncodedValueSubField extends CompositeField<ArrayEncodedValueSubField> public class ArrayEncodedValueSubField extends CompositeField<ArrayEncodedValueSubField>
implements EncodedValueSubField<ArrayEncodedValueSubField> implements EncodedValueSubField<ArrayEncodedValueSubField>, Comparable<EncodedValueSubField>
{ {
private final ArrayList<EncodedValue> encodedValues; private final ArrayList<EncodedValue> encodedValues;
@ -88,4 +88,22 @@ public class ArrayEncodedValueSubField extends CompositeField<ArrayEncodedValueS
public List<EncodedValue> getValues() { public List<EncodedValue> getValues() {
return Collections.unmodifiableList(encodedValues); return Collections.unmodifiableList(encodedValues);
} }
public int compareTo(EncodedValueSubField t) {
int comp = getValueType().compareTo(t.getValueType());
if (comp == 0) {
ArrayEncodedValueSubField other = (ArrayEncodedValueSubField)t;
comp = ((Integer)encodedValues.size()).compareTo(other.encodedValues.size());
if (comp == 0) {
for (int i=0; i<encodedValues.size(); i++) {
comp = encodedValues.get(i).compareTo(other.encodedValues.get(i));
if (comp != 0) {
break;
}
}
}
}
return comp;
}
} }

View File

@ -34,7 +34,7 @@ import org.jf.dexlib.Util.EncodedValueUtils;
import org.jf.dexlib.Util.Input; import org.jf.dexlib.Util.Input;
public class EncodedIndexedItemReference<T extends IndexedItem<T>> public class EncodedIndexedItemReference<T extends IndexedItem<T>>
implements EncodedValueSubField<EncodedIndexedItemReference<T>> { implements EncodedValueSubField<EncodedIndexedItemReference<T>>, Comparable<EncodedValueSubField> {
private int initialValueArg; private int initialValueArg;
private ValueType valueType; private ValueType valueType;
@ -140,4 +140,12 @@ public class EncodedIndexedItemReference<T extends IndexedItem<T>>
return other.item == null; return other.item == null;
} }
} }
public int compareTo(EncodedValueSubField t) {
int comp = getValueType().compareTo(t.getValueType());
if (comp == 0) {
return item.compareTo(((EncodedIndexedItemReference<T>)t).item);
}
return comp;
}
} }

View File

@ -34,7 +34,7 @@ import org.jf.dexlib.Field;
import org.jf.dexlib.Util.AnnotatedOutput; import org.jf.dexlib.Util.AnnotatedOutput;
import org.jf.dexlib.Util.Input; import org.jf.dexlib.Util.Input;
public class EncodedValue extends CompositeField<EncodedValue> { public class EncodedValue extends CompositeField<EncodedValue> implements Comparable<EncodedValue> {
private class ValueTypeArgField implements Field<ValueTypeArgField> { private class ValueTypeArgField implements Field<ValueTypeArgField> {
private ValueType valueType; private ValueType valueType;
private byte valueArg; private byte valueArg;
@ -89,7 +89,8 @@ public class EncodedValue extends CompositeField<EncodedValue> {
} }
} }
private class EncodedValueSubFieldWrapper implements Field<EncodedValueSubFieldWrapper> { private class EncodedValueSubFieldWrapper
implements Field<EncodedValueSubFieldWrapper>, Comparable<EncodedValueSubFieldWrapper> {
private final DexFile dexFile; private final DexFile dexFile;
private EncodedValueSubField subField; private EncodedValueSubField subField;
@ -141,6 +142,10 @@ public class EncodedValue extends CompositeField<EncodedValue> {
EncodedValueSubFieldWrapper other = (EncodedValueSubFieldWrapper)o; EncodedValueSubFieldWrapper other = (EncodedValueSubFieldWrapper)o;
return subField.equals(other.subField); return subField.equals(other.subField);
} }
public int compareTo(EncodedValueSubFieldWrapper encodedValueSubFieldWrapper) {
return subField.compareTo(encodedValueSubFieldWrapper.subField);
}
} }
private final ValueTypeArgField valueTypeArg; private final ValueTypeArgField valueTypeArg;
@ -181,4 +186,8 @@ public class EncodedValue extends CompositeField<EncodedValue> {
public EncodedValueSubField getValue() { public EncodedValueSubField getValue() {
return encodedValue.getEncodedValueSubField(); return encodedValue.getEncodedValueSubField();
} }
public int compareTo(EncodedValue encodedValue) {
return this.encodedValue.compareTo(encodedValue.encodedValue);
}
} }

View File

@ -35,4 +35,5 @@ public interface EncodedValueSubField<T extends EncodedValueSubField> extends Fi
public void setInitialValueArg(byte valueArg); public void setInitialValueArg(byte valueArg);
public byte getValueArg(); public byte getValueArg();
public ValueType getValueType(); public ValueType getValueType();
public int compareTo(EncodedValueSubField encodedValueSubField);
} }

View File

@ -32,7 +32,7 @@ import org.jf.dexlib.Util.AnnotatedOutput;
import org.jf.dexlib.Util.Input; import org.jf.dexlib.Util.Input;
public class NullEncodedValueSubField public class NullEncodedValueSubField
extends SimpleEncodedValueSubField<Object, NullEncodedValueSubField> extends SimpleEncodedValueSubField<Integer, NullEncodedValueSubField>
{ {
public NullEncodedValueSubField() { public NullEncodedValueSubField() {
} }
@ -55,4 +55,8 @@ public class NullEncodedValueSubField
public ValueType getValueType() { public ValueType getValueType() {
return ValueType.VALUE_NULL; return ValueType.VALUE_NULL;
} }
public int compareTo(EncodedValueSubField t) {
return getValueType().compareTo(t.getValueType());
}
} }

View File

@ -30,7 +30,8 @@ package org.jf.dexlib.EncodedValue;
import org.jf.dexlib.DexFile; import org.jf.dexlib.DexFile;
public abstract class SimpleEncodedValueSubField<V, T extends SimpleEncodedValueSubField<V,T>> implements EncodedValueSubField<T> public abstract class SimpleEncodedValueSubField<V extends Comparable<V>, T extends SimpleEncodedValueSubField<V,T>>
implements EncodedValueSubField<T>, Comparable<EncodedValueSubField>
{ {
protected V value; protected V value;
protected byte valueArg = 0; protected byte valueArg = 0;
@ -65,4 +66,12 @@ public abstract class SimpleEncodedValueSubField<V, T extends SimpleEncodedValue
} }
return value.equals(other.value); return value.equals(other.value);
} }
public int compareTo(EncodedValueSubField t) {
int comp = getValueType().compareTo(t.getValueType());
if (comp == 0) {
return value.compareTo(((SimpleEncodedValueSubField<V, T>)t).value);
}
return comp;
}
} }

View File

@ -28,7 +28,7 @@
package org.jf.dexlib; package org.jf.dexlib;
public abstract class IndexedItem<T extends IndexedItem> extends Item<T> implements Comparable<T> { public abstract class IndexedItem<T extends IndexedItem> extends Item<T> {
protected IndexedItem(int index) { protected IndexedItem(int index) {
this.index = index; this.index = index;
} }

View File

@ -77,10 +77,6 @@ public abstract class IndexedSection<T extends IndexedItem<T>> extends Section<T
return itemToReturn; return itemToReturn;
} }
protected void sortSection() {
Collections.sort(items);
}
public int place(int offset) { public int place(int offset) {
sortSection(); sortSection();

View File

@ -31,7 +31,7 @@ package org.jf.dexlib;
import org.jf.dexlib.Util.AnnotatedOutput; import org.jf.dexlib.Util.AnnotatedOutput;
import org.jf.dexlib.Util.Input; import org.jf.dexlib.Util.Input;
public abstract class Item<T extends Item> { public abstract class Item<T extends Item> implements Comparable<T> {
protected int offset = -1; protected int offset = -1;
protected int index = -1; protected int index = -1;

View File

@ -33,6 +33,8 @@ import org.jf.dexlib.Util.Input;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
import java.util.List;
import java.util.Collections;
public abstract class Section<T extends Item> { public abstract class Section<T extends Item> {
protected ArrayList<T> items; protected ArrayList<T> items;
@ -112,6 +114,10 @@ public abstract class Section<T extends Item> {
return offset; return offset;
} }
public List<T> getItems() {
return Collections.unmodifiableList(items);
}
protected T getInternedItem(T item) { protected T getInternedItem(T item) {
if (uniqueItems == null) { if (uniqueItems == null) {
buildInternedItemMap(); buildInternedItemMap();
@ -126,5 +132,9 @@ public abstract class Section<T extends Item> {
} }
} }
protected void sortSection() {
Collections.sort(items);
}
public abstract T intern(DexFile dexFile, T item); public abstract T intern(DexFile dexFile, T item);
} }

View File

@ -69,11 +69,17 @@ public class StringDataItem extends OffsettedItem<StringDataItem> implements Com
return value; return value;
} }
public byte[] getStringBytes() {
return stringByteArray.value;
}
public String getConciseIdentity() { public String getConciseIdentity() {
return "string_data_item: " + getStringValue(); return "string_data_item: " + Utf8Utils.escapeString(getStringValue());
} }
public int compareTo(StringDataItem o) { public int compareTo(StringDataItem o) {
return getStringValue().compareTo(o.getStringValue()); return getStringValue().compareTo(o.getStringValue());
} }
} }

View File

@ -28,6 +28,8 @@
package org.jf.dexlib; package org.jf.dexlib;
import org.jf.dexlib.Util.Utf8Utils;
public class StringIdItem extends IndexedItem<StringIdItem> { public class StringIdItem extends IndexedItem<StringIdItem> {
private final OffsettedItemReference<StringDataItem> stringDataReferenceField; private final OffsettedItemReference<StringDataItem> stringDataReferenceField;
@ -57,13 +59,17 @@ public class StringIdItem extends IndexedItem<StringIdItem> {
} }
public String getConciseIdentity() { public String getConciseIdentity() {
return "string_id_item: " + getStringValue(); return "string_id_item: " + Utf8Utils.escapeString(getStringValue());
} }
public String getStringValue() { public String getStringValue() {
return stringDataReferenceField.getReference().getStringValue(); return stringDataReferenceField.getReference().getStringValue();
} }
public StringDataItem getStringData() {
return stringDataReferenceField.getReference();
}
public int compareTo(StringIdItem o) { public int compareTo(StringIdItem o) {
//sort by the string value //sort by the string value
return getStringValue().compareTo(o.getStringValue()); return getStringValue().compareTo(o.getStringValue());

View File

@ -31,7 +31,7 @@ package org.jf.dexlib;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class TypeListItem extends OffsettedItem<TypeListItem> implements Comparable<TypeListItem> { public class TypeListItem extends OffsettedItem<TypeListItem> {
private final ArrayList<IndexedItemReference<TypeIdItem>> typeList = new ArrayList<IndexedItemReference<TypeIdItem>>(); private final ArrayList<IndexedItemReference<TypeIdItem>> typeList = new ArrayList<IndexedItemReference<TypeIdItem>>();
private final ListSizeField sizeField; private final ListSizeField sizeField;

View File

@ -66,13 +66,13 @@ public class NumberUtils {
} }
public static long decodeLong(byte[] array, int startIndex) { public static long decodeLong(byte[] array, int startIndex) {
return array[startIndex++] | return (array[startIndex++] & 0xffL) |
(array[startIndex++] >> 8) | ((array[startIndex++] & 0xffL) << 8) |
(array[startIndex++] >> 16) | ((array[startIndex++] & 0xffL) << 16) |
(array[startIndex++] >> 24) | ((array[startIndex++] & 0xffL) << 24) |
((long)array[startIndex++] >> 32) | ((array[startIndex++] & 0xffL) << 32) |
((long)array[startIndex++] >> 40) | ((array[startIndex++] & 0xffL) << 40) |
((long)array[startIndex++] >> 48) | ((array[startIndex++] & 0xffL) << 48) |
((long)array[startIndex++] >> 56); ((array[startIndex] & 0xffL) << 56);
} }
} }

View File

@ -33,11 +33,13 @@ import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.tree.CommonTree; import org.antlr.runtime.tree.CommonTree;
import org.antlr.runtime.tree.CommonTreeNodeStream; import org.antlr.runtime.tree.CommonTreeNodeStream;
import org.jf.dexlib.DexFile; import org.jf.dexlib.DexFile;
import org.jf.dexlib.AnnotationItem;
import org.jf.dexlib.Util.ByteArrayAnnotatedOutput; import org.jf.dexlib.Util.ByteArrayAnnotatedOutput;
import java.io.*; import java.io.*;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.Set; import java.util.Set;
import java.util.List;
public class smali public class smali
{ {
@ -125,7 +127,7 @@ public class smali
System.exit(1); System.exit(1);
} }
dexFile.place(); dexFile.place(false);
try try
{ {
ByteArrayAnnotatedOutput out = new ByteArrayAnnotatedOutput(); ByteArrayAnnotatedOutput out = new ByteArrayAnnotatedOutput();