Refactor how information about indexed items are exposed in DexBackedDexFile

This adds a unified IndexedSection/OptionalIndexedSection class for
all indexed items
This commit is contained in:
Ben Gruver 2019-08-01 15:48:45 -07:00
parent 2412f1f741
commit 8faa4b31ec
28 changed files with 338 additions and 289 deletions

View File

@ -63,7 +63,7 @@ public class DisassemblyTest extends DexTest {
protected void runTest(@Nonnull String testName, @Nonnull BaksmaliOptions options) {
try {
DexBackedDexFile inputDex = getInputDexFile(testName, options);
Assert.assertEquals(1, inputDex.getClassCount());
Assert.assertEquals(1, inputDex.getClassSection().size());
ClassDef inputClass = Iterables.getFirst(inputDex.getClasses(), null);
Assert.assertNotNull(inputClass);
String input = BaksmaliTestUtils.getNormalizedSmali(inputClass, options, true);

View File

@ -36,8 +36,8 @@ import org.jf.util.ExceptionWithContext;
import javax.annotation.Nonnull;
public class BaseDexBuffer {
@Nonnull /* package private */ final byte[] buf;
/* package private */ final int baseOffset;
@Nonnull final byte[] buf;
final int baseOffset;
public BaseDexBuffer(@Nonnull byte[] buf) {
this(buf, 0);

View File

@ -55,7 +55,7 @@ public class DexBackedAnnotation extends BaseAnnotation {
}
@Override public int getVisibility() { return visibility; }
@Nonnull @Override public String getType() { return dexFile.getType(typeIndex); }
@Nonnull @Override public String getType() { return dexFile.getTypeSection().get(typeIndex); }
@Nonnull
@Override

View File

@ -48,6 +48,6 @@ public class DexBackedAnnotationElement extends BaseAnnotationElement {
this.value = DexBackedEncodedValue.readFrom(reader);
}
@Nonnull @Override public String getName() { return dexFile.getString(nameIndex); }
@Nonnull @Override public String getName() { return dexFile.getStringSection().get(nameIndex); }
@Nonnull @Override public EncodedValue getValue() { return value; }
}

View File

@ -95,13 +95,13 @@ public class DexBackedClassDef extends BaseTypeReference implements ClassDef {
@Nonnull
@Override
public String getType() {
return dexFile.getType(dexFile.readSmallUint(classDefOffset + ClassDefItem.CLASS_OFFSET));
return dexFile.getTypeSection().get(dexFile.readSmallUint(classDefOffset + ClassDefItem.CLASS_OFFSET));
}
@Nullable
@Override
public String getSuperclass() {
return dexFile.getOptionalType(dexFile.readOptionalUint(classDefOffset + ClassDefItem.SUPERCLASS_OFFSET));
return dexFile.getTypeSection().getOptional(dexFile.readOptionalUint(classDefOffset + ClassDefItem.SUPERCLASS_OFFSET));
}
@Override
@ -112,7 +112,8 @@ public class DexBackedClassDef extends BaseTypeReference implements ClassDef {
@Nullable
@Override
public String getSourceFile() {
return dexFile.getOptionalString(dexFile.readOptionalUint(classDefOffset + ClassDefItem.SOURCE_FILE_OFFSET));
return dexFile.getStringSection().getOptional(
dexFile.readOptionalUint(classDefOffset + ClassDefItem.SOURCE_FILE_OFFSET));
}
@Nonnull
@ -125,7 +126,7 @@ public class DexBackedClassDef extends BaseTypeReference implements ClassDef {
@Override
@Nonnull
public String get(int index) {
return dexFile.getType(dexFile.readUshort(interfacesOffset + 4 + (2*index)));
return dexFile.getTypeSection().get(dexFile.readUshort(interfacesOffset + 4 + (2*index)));
}
@Override public int size() { return size; }

View File

@ -35,16 +35,12 @@ import com.google.common.io.ByteStreams;
import org.jf.dexlib2.Opcodes;
import org.jf.dexlib2.ReferenceType;
import org.jf.dexlib2.dexbacked.raw.*;
import org.jf.dexlib2.dexbacked.reference.DexBackedFieldReference;
import org.jf.dexlib2.dexbacked.reference.DexBackedMethodReference;
import org.jf.dexlib2.dexbacked.reference.DexBackedStringReference;
import org.jf.dexlib2.dexbacked.reference.DexBackedTypeReference;
import org.jf.dexlib2.dexbacked.reference.*;
import org.jf.dexlib2.dexbacked.util.FixedSizeList;
import org.jf.dexlib2.dexbacked.util.FixedSizeSet;
import org.jf.dexlib2.iface.DexFile;
import org.jf.dexlib2.iface.reference.Reference;
import org.jf.dexlib2.iface.reference.*;
import org.jf.dexlib2.util.DexUtil;
import org.jf.util.ExceptionWithContext;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@ -123,7 +119,7 @@ public class DexBackedDexFile extends BaseDexBuffer implements DexFile {
return new DexBackedDexFile(opcodes, buf, 0, false);
}
@Override @Nonnull public Opcodes getOpcodes() {
@Nonnull public Opcodes getOpcodes() {
return opcodes;
}
@ -132,13 +128,12 @@ public class DexBackedDexFile extends BaseDexBuffer implements DexFile {
}
@Nonnull
@Override
public Set<? extends DexBackedClassDef> getClasses() {
return new FixedSizeSet<DexBackedClassDef>() {
@Nonnull
@Override
public DexBackedClassDef readItem(int index) {
return new DexBackedClassDef(DexBackedDexFile.this, getClassDefItemOffset(index));
return getClassSection().get(index);
}
@Override
@ -148,192 +143,32 @@ public class DexBackedDexFile extends BaseDexBuffer implements DexFile {
};
}
public int getStringIdItemOffset(int stringIndex) {
if (stringIndex < 0 || stringIndex >= stringCount) {
throw new InvalidItemIndex(stringIndex, "String index out of bounds: %d", stringIndex);
}
return stringStartOffset + stringIndex*StringIdItem.ITEM_SIZE;
}
public int getTypeIdItemOffset(int typeIndex) {
if (typeIndex < 0 || typeIndex >= typeCount) {
throw new InvalidItemIndex(typeIndex, "Type index out of bounds: %d", typeIndex);
}
return typeStartOffset + typeIndex*TypeIdItem.ITEM_SIZE;
}
public int getFieldIdItemOffset(int fieldIndex) {
if (fieldIndex < 0 || fieldIndex >= fieldCount) {
throw new InvalidItemIndex(fieldIndex, "Field index out of bounds: %d", fieldIndex);
}
return fieldStartOffset + fieldIndex*FieldIdItem.ITEM_SIZE;
}
public int getMethodIdItemOffset(int methodIndex) {
if (methodIndex < 0 || methodIndex >= methodCount) {
throw new InvalidItemIndex(methodIndex, "Method index out of bounds: %d", methodIndex);
}
return methodStartOffset + methodIndex*MethodIdItem.ITEM_SIZE;
}
public int getProtoIdItemOffset(int protoIndex) {
if (protoIndex < 0 || protoIndex >= protoCount) {
throw new InvalidItemIndex(protoIndex, "Proto index out of bounds: %d", protoIndex);
}
return protoStartOffset + protoIndex*ProtoIdItem.ITEM_SIZE;
}
public int getClassDefItemOffset(int classIndex) {
if (classIndex < 0 || classIndex >= classCount) {
throw new InvalidItemIndex(classIndex, "Class index out of bounds: %d", classIndex);
}
return classStartOffset + classIndex*ClassDefItem.ITEM_SIZE;
}
public int getCallSiteIdItemOffset(int callSiteIndex) {
MapItem mapItem = getMapItemForSection(ItemType.CALL_SITE_ID_ITEM);
if (mapItem == null || callSiteIndex >= mapItem.getItemCount()) {
throw new InvalidItemIndex(callSiteIndex, "Call site index out of bounds: %d", callSiteIndex);
}
return mapItem.getOffset() + callSiteIndex * CallSiteIdItem.ITEM_SIZE;
}
public int getMethodHandleItemOffset(int methodHandleIndex) {
MapItem mapItem = getMapItemForSection(ItemType.METHOD_HANDLE_ITEM);
if (mapItem == null || methodHandleIndex >= mapItem.getItemCount()) {
throw new InvalidItemIndex(methodHandleIndex , "Method handle index out of bounds: %d", methodHandleIndex);
}
return mapItem.getOffset() + methodHandleIndex * MethodHandleItem.ITEM_SIZE;
}
public int getClassCount() {
return classCount;
}
public int getStringCount() {
return stringCount;
}
public int getTypeCount() {
return typeCount;
}
public int getProtoCount() {
return protoCount;
}
public int getFieldCount() {
return fieldCount;
}
public int getMethodCount() {
return methodCount;
}
public int getCallSiteCount() {
MapItem mapItem = getMapItemForSection(ItemType.CALL_SITE_ID_ITEM);
if (mapItem == null) {
return 0;
}
return mapItem.getItemCount();
}
public int getMethodHandleCount() {
MapItem mapItem = getMapItemForSection(ItemType.METHOD_HANDLE_ITEM);
if (mapItem == null) {
return 0;
}
return mapItem.getItemCount();
}
@Nonnull
public String getString(int stringIndex) {
int stringOffset = getStringIdItemOffset(stringIndex);
int stringDataOffset = readSmallUint(stringOffset);
DexReader reader = readerAt(stringDataOffset);
int utf16Length = reader.readSmallUleb128();
return reader.readString(utf16Length);
}
@Nullable
public String getOptionalString(int stringIndex) {
if (stringIndex == -1) {
return null;
}
return getString(stringIndex);
}
@Nonnull
public String getType(int typeIndex) {
int typeOffset = getTypeIdItemOffset(typeIndex);
int stringIndex = readSmallUint(typeOffset);
return getString(stringIndex);
}
@Nullable
public String getOptionalType(int typeIndex) {
if (typeIndex == -1) {
return null;
}
return getType(typeIndex);
}
public List<DexBackedStringReference> getStrings() {
public List<DexBackedStringReference> getStringReferences() {
return new AbstractList<DexBackedStringReference>() {
@Override public DexBackedStringReference get(int index) {
if (index < 0 || index >= getStringCount()) {
if (index < 0 || index >= getStringSection().size()) {
throw new IndexOutOfBoundsException();
}
return new DexBackedStringReference(DexBackedDexFile.this, index);
}
@Override public int size() {
return getStringCount();
return getStringSection().size();
}
};
}
public List<DexBackedTypeReference> getTypes() {
public List<DexBackedTypeReference> getTypeReferences() {
return new AbstractList<DexBackedTypeReference>() {
@Override public DexBackedTypeReference get(int index) {
if (index < 0 || index >= getTypeCount()) {
if (index < 0 || index >= getTypeSection().size()) {
throw new IndexOutOfBoundsException();
}
return new DexBackedTypeReference(DexBackedDexFile.this, index);
}
@Override public int size() {
return getTypeCount();
}
};
}
public List<DexBackedMethodReference> getMethods() {
return new AbstractList<DexBackedMethodReference>() {
@Override public DexBackedMethodReference get(int index) {
if (index < 0 || index >= getMethodCount()) {
throw new IndexOutOfBoundsException();
}
return new DexBackedMethodReference(DexBackedDexFile.this, index);
}
@Override public int size() {
return getMethodCount();
}
};
}
public List<DexBackedFieldReference> getFields() {
return new AbstractList<DexBackedFieldReference>() {
@Override public DexBackedFieldReference get(int index) {
if (index < 0 || index >= getFieldCount()) {
throw new IndexOutOfBoundsException();
}
return new DexBackedFieldReference(DexBackedDexFile.this, index);
}
@Override public int size() {
return getFieldCount();
return getTypeSection().size();
}
};
}
@ -341,13 +176,13 @@ public class DexBackedDexFile extends BaseDexBuffer implements DexFile {
public List<? extends Reference> getReferences(int referenceType) {
switch (referenceType) {
case ReferenceType.STRING:
return getStrings();
return getStringReferences();
case ReferenceType.TYPE:
return getTypes();
return getTypeReferences();
case ReferenceType.METHOD:
return getMethods();
return getMethodSection();
case ReferenceType.FIELD:
return getFields();
return getFieldSection();
default:
throw new IllegalArgumentException(String.format("Invalid reference type: %d", referenceType));
}
@ -402,21 +237,259 @@ public class DexBackedDexFile extends BaseDexBuffer implements DexFile {
}
}
public static class InvalidItemIndex extends ExceptionWithContext {
private final int itemIndex;
public InvalidItemIndex(int itemIndex) {
super("");
this.itemIndex = itemIndex;
private OptionalIndexedSection<String> stringSection = new OptionalIndexedSection<String>() {
@Override
public String get(int index) {
int stringOffset = getOffset(index);
int stringDataOffset = readSmallUint(stringOffset);
DexReader reader = readerAt(stringDataOffset);
int utf16Length = reader.readSmallUleb128();
return reader.readString(utf16Length);
}
public InvalidItemIndex(int itemIndex, String message, Object... formatArgs) {
super(message, formatArgs);
this.itemIndex = itemIndex;
@Override
public int size() {
return stringCount;
}
public int getInvalidIndex() {
return itemIndex;
@Nullable
@Override
public String getOptional(int index) {
if (index == -1) {
return null;
}
return get(index);
}
@Override
public int getOffset(int index) {
if (index < 0 || index >= size()) {
throw new IndexOutOfBoundsException(
String.format("Invalid string index %d, not in [0, %d)", index, size()));
}
return stringStartOffset + index*StringIdItem.ITEM_SIZE;
}
};
public OptionalIndexedSection<String> getStringSection() {
return stringSection;
}
private OptionalIndexedSection<String> typeSection = new OptionalIndexedSection<String>() {
@Override
public String get(int index) {
int typeOffset = getOffset(index);
int stringIndex = readSmallUint(typeOffset);
return getStringSection().get(stringIndex);
}
@Override
public int size() {
return typeCount;
}
@Nullable
@Override
public String getOptional(int index) {
if (index == -1) {
return null;
}
return get(index);
}
@Override
public int getOffset(int index) {
if (index < 0 || index >= size()) {
throw new IndexOutOfBoundsException(
String.format("Invalid type index %d, not in [0, %d)", index, size()));
}
return typeStartOffset + index * TypeIdItem.ITEM_SIZE;
}
};
public OptionalIndexedSection<String> getTypeSection() {
return typeSection;
}
private IndexedSection<FieldReference> fieldSection = new IndexedSection<FieldReference>() {
@Override
public FieldReference get(int index) {
return new DexBackedFieldReference(DexBackedDexFile.this, index);
}
@Override
public int size() {
return fieldCount;
}
@Override
public int getOffset(int index) {
if (index < 0 || index >= size()) {
throw new IndexOutOfBoundsException(
String.format("Invalid field index %d, not in [0, %d)", index, size()));
}
return fieldStartOffset + index * FieldIdItem.ITEM_SIZE;
}
};
public IndexedSection<FieldReference> getFieldSection() {
return fieldSection;
}
private IndexedSection<MethodReference> methodSection = new IndexedSection<MethodReference>() {
@Override
public MethodReference get(int index) {
return new DexBackedMethodReference(DexBackedDexFile.this, index);
}
@Override
public int size() {
return methodCount;
}
@Override
public int getOffset(int index) {
if (index < 0 || index >= size()) {
throw new IndexOutOfBoundsException(
String.format("Invalid method index %d, not in [0, %d)", index, size()));
}
return methodStartOffset + index * MethodIdItem.ITEM_SIZE;
}
};
public IndexedSection<MethodReference> getMethodSection() {
return methodSection;
}
private IndexedSection<MethodProtoReference> protoSection = new IndexedSection<MethodProtoReference>() {
@Override
public MethodProtoReference get(int index) {
return new DexBackedMethodProtoReference(DexBackedDexFile.this, index);
}
@Override
public int size() {
return protoCount;
}
@Override
public int getOffset(int index) {
if (index < 0 || index >= size()) {
throw new IndexOutOfBoundsException(
String.format("Invalid proto index %d, not in [0, %d)", index, size()));
}
return protoStartOffset + index * ProtoIdItem.ITEM_SIZE;
}
};
public IndexedSection<MethodProtoReference> getProtoSection() {
return protoSection;
}
private IndexedSection<DexBackedClassDef> classSection = new IndexedSection<DexBackedClassDef>() {
@Override
public DexBackedClassDef get(int index) {
return new DexBackedClassDef(DexBackedDexFile.this, getOffset(index));
}
@Override
public int size() {
return classCount;
}
@Override
public int getOffset(int index) {
if (index < 0 || index >= size()) {
throw new IndexOutOfBoundsException(
String.format("Invalid class index %d, not in [0, %d)", index, size()));
}
return classStartOffset + index * ClassDefItem.ITEM_SIZE;
}
};
public IndexedSection<DexBackedClassDef> getClassSection() {
return classSection;
}
private IndexedSection<CallSiteReference> callSiteSection = new IndexedSection<CallSiteReference>() {
@Override
public CallSiteReference get(int index) {
return new DexBackedCallSiteReference(DexBackedDexFile.this, index);
}
@Override
public int size() {
MapItem mapItem = getMapItemForSection(ItemType.CALL_SITE_ID_ITEM);
if (mapItem == null) {
return 0;
}
return mapItem.getItemCount();
}
@Override
public int getOffset(int index) {
MapItem mapItem = getMapItemForSection(ItemType.CALL_SITE_ID_ITEM);
if (index < 0 || index >= size()) {
throw new IndexOutOfBoundsException(
String.format("Invalid callsite index %d, not in [0, %d)", index, size()));
}
return mapItem.getOffset() + index * CallSiteIdItem.ITEM_SIZE;
}
};
public IndexedSection<CallSiteReference> getCallSiteSection() {
return callSiteSection;
}
private IndexedSection<MethodHandleReference> methodHandleSection = new IndexedSection<MethodHandleReference>() {
@Override
public MethodHandleReference get(int index) {
return new DexBackedMethodHandleReference(DexBackedDexFile.this, index);
}
@Override
public int size() {
MapItem mapItem = getMapItemForSection(ItemType.METHOD_HANDLE_ITEM);
if (mapItem == null) {
return 0;
}
return mapItem.getItemCount();
}
@Override
public int getOffset(int index) {
MapItem mapItem = getMapItemForSection(ItemType.METHOD_HANDLE_ITEM);
if (index < 0 || index >= size()) {
throw new IndexOutOfBoundsException(
String.format("Invalid method handle index %d, not in [0, %d)", index, size()));
}
return mapItem.getOffset() + index * MethodHandleItem.ITEM_SIZE;
}
};
public IndexedSection<MethodHandleReference> getMethodHandleSection() {
return methodHandleSection;
}
public static abstract class OptionalIndexedSection<T> extends IndexedSection<T> {
/**
* @param index The index of the item, or -1 for a null item.
* @return The value at the given index, or null if index is -1.
* @throws IndexOutOfBoundsException if the index is out of bounds and is not -1.
*/
@Nullable public abstract T getOptional(int index);
}
public static abstract class IndexedSection<T> extends AbstractList<T> {
/**
* @param index The index of the item to get the offset for.
* @return The offset from the beginning of the dex file to the specified item.
* @throws IndexOutOfBoundsException if the index is out of bounds.
*/
public abstract int getOffset(int index);
}
}

View File

@ -101,13 +101,13 @@ public class DexBackedField extends BaseFieldReference implements Field {
@Nonnull
@Override
public String getName() {
return dexFile.getString(dexFile.readSmallUint(getFieldIdItemOffset() + FieldIdItem.NAME_OFFSET));
return dexFile.getStringSection().get(dexFile.readSmallUint(getFieldIdItemOffset() + FieldIdItem.NAME_OFFSET));
}
@Nonnull
@Override
public String getType() {
return dexFile.getType(dexFile.readUshort(getFieldIdItemOffset() + FieldIdItem.TYPE_OFFSET));
return dexFile.getTypeSection().get(dexFile.readUshort(getFieldIdItemOffset() + FieldIdItem.TYPE_OFFSET));
}
@Nonnull @Override public String getDefiningClass() { return classDef.getType(); }
@ -135,7 +135,7 @@ public class DexBackedField extends BaseFieldReference implements Field {
private int getFieldIdItemOffset() {
if (fieldIdItemOffset == 0) {
fieldIdItemOffset = dexFile.getFieldIdItemOffset(fieldIndex);
fieldIdItemOffset = dexFile.getFieldSection().getOffset(fieldIndex);
}
return fieldIdItemOffset;
}

View File

@ -43,7 +43,6 @@ import org.jf.dexlib2.dexbacked.util.FixedSizeList;
import org.jf.dexlib2.dexbacked.util.ParameterIterator;
import org.jf.dexlib2.iface.Annotation;
import org.jf.dexlib2.iface.Method;
import org.jf.dexlib2.iface.MethodImplementation;
import org.jf.dexlib2.iface.MethodParameter;
import org.jf.util.AbstractForwardSequentialList;
@ -115,13 +114,14 @@ public class DexBackedMethod extends BaseMethodReference implements Method {
@Nonnull
@Override
public String getName() {
return dexFile.getString(dexFile.readSmallUint(getMethodIdItemOffset() + MethodIdItem.NAME_OFFSET));
return dexFile.getStringSection().get(dexFile.readSmallUint(getMethodIdItemOffset() + MethodIdItem.NAME_OFFSET));
}
@Nonnull
@Override
public String getReturnType() {
return dexFile.getType(dexFile.readSmallUint(getProtoIdItemOffset() + ProtoIdItem.RETURN_TYPE_OFFSET));
return dexFile.getTypeSection().get(
dexFile.readSmallUint(getProtoIdItemOffset() + ProtoIdItem.RETURN_TYPE_OFFSET));
}
@Nonnull
@ -171,7 +171,7 @@ public class DexBackedMethod extends BaseMethodReference implements Method {
@Nonnull
@Override
public String readItem(final int index) {
return dexFile.getType(dexFile.readUshort(paramListStart + 2*index));
return dexFile.getTypeSection().get(dexFile.readUshort(paramListStart + 2*index));
}
@Override public int size() { return parameterCount; }
};
@ -196,7 +196,7 @@ public class DexBackedMethod extends BaseMethodReference implements Method {
private int getMethodIdItemOffset() {
if (methodIdItemOffset == 0) {
methodIdItemOffset = dexFile.getMethodIdItemOffset(methodIndex);
methodIdItemOffset = dexFile.getMethodSection().getOffset(methodIndex);
}
return methodIdItemOffset;
}
@ -204,7 +204,7 @@ public class DexBackedMethod extends BaseMethodReference implements Method {
private int getProtoIdItemOffset() {
if (protoIdItemOffset == 0) {
int protoIndex = dexFile.readUshort(getMethodIdItemOffset() + MethodIdItem.PROTO_OFFSET);
protoIdItemOffset = dexFile.getProtoIdItemOffset(protoIndex);
protoIdItemOffset = dexFile.getProtoSection().getOffset(protoIndex);
}
return protoIdItemOffset;
}

View File

@ -44,6 +44,6 @@ public class DexBackedTypedExceptionHandler extends DexBackedExceptionHandler {
this.handlerCodeAddress = reader.readSmallUleb128();
}
@Nonnull @Override public String getExceptionType() { return dexFile.getType(typeId); }
@Nonnull @Override public String getExceptionType() { return dexFile.getTypeSection().get(typeId); }
@Override public int getHandlerCodeAddress() { return handlerCodeAddress; }
}

View File

@ -80,7 +80,7 @@ public class AnnotationItem {
DexReader reader = dexFile.readerAt(annotationItemOffset);
reader.readUbyte();
int typeIndex = reader.readSmallUleb128();
String annotationType = dexFile.getType(typeIndex);
String annotationType = dexFile.getTypeSection().get(typeIndex);
return String.format("annotation_item[0x%x]: %s", annotationItemOffset, annotationType);
} catch (Exception ex) {
ex.printStackTrace(System.err);

View File

@ -98,7 +98,7 @@ public class ClassDefItem {
out.annotate(4, "class_data_off = class_data_item[NO_OFFSET]");
} else {
out.annotate(4, "class_data_off = class_data_item[0x%x]", classDataOffset);
addClassDataIdentity(classDataOffset, dexFile.getType(classIndex));
addClassDataIdentity(classDataOffset, dexFile.getTypeSection().get(classIndex));
}
int staticValuesOffset = dexFile.readSmallUint(out.getCursor());
@ -119,9 +119,9 @@ public class ClassDefItem {
@Nonnull
public static String asString(@Nonnull DexBackedDexFile dexFile, int classIndex) {
int offset = dexFile.getClassDefItemOffset(classIndex);
int offset = dexFile.getClassSection().getOffset(classIndex);
int typeIndex = dexFile.readSmallUint(offset + CLASS_OFFSET);
return dexFile.getType(typeIndex);
return dexFile.getTypeSection().get(typeIndex);
}
public static String[] getClasses(@Nonnull RawDexFile dexFile) {

View File

@ -68,15 +68,15 @@ public class FieldIdItem {
@Nonnull
public static String asString(@Nonnull DexBackedDexFile dexFile, int fieldIndex) {
int fieldOffset = dexFile.getFieldIdItemOffset(fieldIndex);
int fieldOffset = dexFile.getFieldSection().getOffset(fieldIndex);
int classIndex = dexFile.readUshort(fieldOffset + CLASS_OFFSET);
String classType = dexFile.getType(classIndex);
String classType = dexFile.getTypeSection().get(classIndex);
int typeIndex = dexFile.readUshort(fieldOffset + TYPE_OFFSET);
String fieldType = dexFile.getType(typeIndex);
String fieldType = dexFile.getTypeSection().get(typeIndex);
int nameIndex = dexFile.readSmallUint(fieldOffset + NAME_OFFSET);
String fieldName = dexFile.getString(nameIndex);
String fieldName = dexFile.getStringSection().get(nameIndex);
return String.format("%s->%s:%s", classType, fieldName, fieldType);
}

View File

@ -68,15 +68,15 @@ public class MethodIdItem {
@Nonnull
public static String asString(@Nonnull DexBackedDexFile dexFile, int methodIndex) {
int methodOffset = dexFile.getMethodIdItemOffset(methodIndex);
int methodOffset = dexFile.getMethodSection().getOffset(methodIndex);
int classIndex = dexFile.readUshort(methodOffset + CLASS_OFFSET);
String classType = dexFile.getType(classIndex);
String classType = dexFile.getTypeSection().get(classIndex);
int protoIndex = dexFile.readUshort(methodOffset + PROTO_OFFSET);
String protoString = ProtoIdItem.asString(dexFile, protoIndex);
int nameIndex = dexFile.readSmallUint(methodOffset + NAME_OFFSET);
String methodName = dexFile.getString(nameIndex);
String methodName = dexFile.getStringSection().get(nameIndex);
return String.format("%s->%s%s", classType, methodName, protoString);
}

View File

@ -79,7 +79,7 @@ public class ProtoIdItem {
@Nonnull
public static String asString(@Nonnull DexBackedDexFile dexFile, int protoIndex) {
int offset = dexFile.getProtoIdItemOffset(protoIndex);
int offset = dexFile.getProtoSection().getOffset(protoIndex);
StringBuilder sb = new StringBuilder();
sb.append("(");
@ -89,7 +89,7 @@ public class ProtoIdItem {
sb.append(")");
int returnTypeIndex = dexFile.readSmallUint(offset + RETURN_TYPE_OFFSET);
String returnType = dexFile.getType(returnTypeIndex);
String returnType = dexFile.getTypeSection().get(returnTypeIndex);
sb.append(returnType);
return sb.toString();

View File

@ -53,7 +53,7 @@ public class StringIdItem {
public void annotateItem(@Nonnull AnnotatedBytes out, int itemIndex, @Nullable String itemIdentity) {
int stringDataOffset = dexFile.readSmallUint(out.getCursor());
try {
String stringValue = dexFile.getString(itemIndex);
String stringValue = dexFile.getStringSection().get(itemIndex);
out.annotate(4, "string_data_item[0x%x]: \"%s\"", stringDataOffset,
StringUtils.escapeString(stringValue));
return;
@ -76,7 +76,7 @@ public class StringIdItem {
public static String getReferenceAnnotation(@Nonnull DexBackedDexFile dexFile, int stringIndex, boolean quote) {
try {
String string = dexFile.getString(stringIndex);
String string = dexFile.getStringSection().get(stringIndex);
if (quote) {
string = String.format("\"%s\"", StringUtils.escapeString(string));
}
@ -101,18 +101,4 @@ public class StringIdItem {
}
return getReferenceAnnotation(dexFile, stringIndex, quote);
}
public static String[] getStrings(@Nonnull RawDexFile dexFile) {
MapItem mapItem = dexFile.getMapItemForSection(ItemType.STRING_ID_ITEM);
if (mapItem == null) {
return new String[0];
}
int stringCount = mapItem.getItemCount();
String[] ret = new String[stringCount];
for (int i=0; i<stringCount; i++) {
ret[i] = dexFile.getString(i);
}
return ret;
}
}

View File

@ -59,7 +59,7 @@ public class TypeIdItem {
@Nonnull
public static String getReferenceAnnotation(@Nonnull DexBackedDexFile dexFile, int typeIndex) {
try {
String typeString = dexFile.getType(typeIndex);
String typeString = dexFile.getTypeSection().get(typeIndex);
return String.format("type_id_item[%d]: %s", typeIndex, typeString);
} catch (Exception ex) {
ex.printStackTrace(System.err);
@ -74,18 +74,4 @@ public class TypeIdItem {
}
return getReferenceAnnotation(dexFile, typeIndex);
}
public static String[] getTypes(@Nonnull RawDexFile dexFile) {
MapItem mapItem = dexFile.getMapItemForSection(ItemType.TYPE_ID_ITEM);
if (mapItem == null) {
return new String[0];
}
int typeCount = mapItem.getItemCount();
String[] ret = new String[typeCount];
for (int i=0; i<typeCount; i++) {
ret[i] = dexFile.getType(i);
}
return ret;
}
}

View File

@ -92,7 +92,7 @@ public class TypeListItem {
int size = dexFile.readSmallUint(typeListOffset);
for (int i=0; i<size; i++) {
int typeIndex = dexFile.readUshort(typeListOffset + 4 + i*2);
String type = dexFile.getType(typeIndex);
String type = dexFile.getTypeSection().get(typeIndex);
sb.append(type);
}
return sb.toString();

View File

@ -56,7 +56,7 @@ public class DexBackedCallSiteReference extends BaseCallSiteReference {
public DexBackedCallSiteReference(DexBackedDexFile dexFile, int callSiteIndex) {
this.dexFile = dexFile;
this.callSiteIndex = callSiteIndex;
this.callSiteIdOffset = dexFile.getCallSiteIdItemOffset(callSiteIndex);
this.callSiteIdOffset = dexFile.getCallSiteSection().getOffset(callSiteIndex);
}
@Nonnull
@ -160,7 +160,7 @@ public class DexBackedCallSiteReference extends BaseCallSiteReference {
@Override
public void validateReference() throws InvalidReferenceException {
if (callSiteIndex < 0 || callSiteIndex >= dexFile.getCallSiteCount()) {
if (callSiteIndex < 0 || callSiteIndex >= dexFile.getCallSiteSection().size()) {
throw new InvalidReferenceException("callsite@" + callSiteIndex);
}
}

View File

@ -49,20 +49,22 @@ public class DexBackedFieldReference extends BaseFieldReference {
@Nonnull
@Override
public String getDefiningClass() {
return dexFile.getType(dexFile.readUshort(dexFile.getFieldIdItemOffset(fieldIndex) + FieldIdItem.CLASS_OFFSET));
return dexFile.getTypeSection().get(
dexFile.readUshort(dexFile.getFieldSection().getOffset(fieldIndex) + FieldIdItem.CLASS_OFFSET));
}
@Nonnull
@Override
public String getName() {
return dexFile.getString(dexFile.readSmallUint(dexFile.getFieldIdItemOffset(fieldIndex) +
return dexFile.getStringSection().get(dexFile.readSmallUint(dexFile.getFieldSection().getOffset(fieldIndex) +
FieldIdItem.NAME_OFFSET));
}
@Nonnull
@Override
public String getType() {
return dexFile.getType(dexFile.readUshort(dexFile.getFieldIdItemOffset(fieldIndex) + FieldIdItem.TYPE_OFFSET));
return dexFile.getTypeSection().get(
dexFile.readUshort(dexFile.getFieldSection().getOffset(fieldIndex) + FieldIdItem.TYPE_OFFSET));
}
/**
@ -78,7 +80,7 @@ public class DexBackedFieldReference extends BaseFieldReference {
@Override
public void validateReference() throws InvalidReferenceException {
if (fieldIndex < 0 || fieldIndex >= dexFile.getFieldCount()) {
if (fieldIndex < 0 || fieldIndex >= dexFile.getFieldSection().size()) {
throw new InvalidReferenceException("field@" + fieldIndex);
}
}

View File

@ -48,7 +48,7 @@ public class DexBackedMethodHandleReference extends BaseMethodHandleReference {
public DexBackedMethodHandleReference(DexBackedDexFile dexFile, int methodHandleIndex) {
this.dexFile = dexFile;
this.methodHandleIndex = methodHandleIndex;
this.methodHandleOffset = dexFile.getMethodHandleItemOffset(methodHandleIndex);
this.methodHandleOffset = dexFile.getMethodHandleSection().getOffset(methodHandleIndex);
}
@Override
@ -79,7 +79,7 @@ public class DexBackedMethodHandleReference extends BaseMethodHandleReference {
@Override
public void validateReference() throws InvalidReferenceException {
if (methodHandleIndex < 0 || methodHandleIndex >= dexFile.getMethodHandleCount()) {
if (methodHandleIndex < 0 || methodHandleIndex >= dexFile.getMethodHandleSection().size()) {
throw new InvalidReferenceException("methodhandle@" + methodHandleIndex);
}

View File

@ -53,7 +53,7 @@ public class DexBackedMethodProtoReference extends BaseMethodProtoReference {
@Nonnull
@Override
public List<String> getParameterTypes() {
final int parametersOffset = dexFile.readSmallUint(dexFile.getProtoIdItemOffset(protoIndex) +
final int parametersOffset = dexFile.readSmallUint(dexFile.getProtoSection().getOffset(protoIndex) +
ProtoIdItem.PARAMETERS_OFFSET);
if (parametersOffset > 0) {
final int parameterCount = dexFile.readSmallUint(parametersOffset + TypeListItem.SIZE_OFFSET);
@ -62,7 +62,7 @@ public class DexBackedMethodProtoReference extends BaseMethodProtoReference {
@Nonnull
@Override
public String readItem(final int index) {
return dexFile.getType(dexFile.readUshort(paramListStart + 2*index));
return dexFile.getTypeSection().get(dexFile.readUshort(paramListStart + 2*index));
}
@Override public int size() { return parameterCount; }
};
@ -73,7 +73,7 @@ public class DexBackedMethodProtoReference extends BaseMethodProtoReference {
@Nonnull
@Override
public String getReturnType() {
return dexFile.getType(dexFile.readSmallUint(dexFile.getProtoIdItemOffset(protoIndex) +
return dexFile.getTypeSection().get(dexFile.readSmallUint(dexFile.getProtoSection().getOffset(protoIndex) +
ProtoIdItem.RETURN_TYPE_OFFSET));
}
@ -95,7 +95,7 @@ public class DexBackedMethodProtoReference extends BaseMethodProtoReference {
@Override
public void validateReference() throws InvalidReferenceException {
if (protoIndex < 0 || protoIndex >= dexFile.getProtoCount()) {
if (protoIndex < 0 || protoIndex >= dexFile.getProtoSection().size()) {
throw new InvalidReferenceException("proto@" + protoIndex);
}
}

View File

@ -55,14 +55,14 @@ public class DexBackedMethodReference extends BaseMethodReference {
@Nonnull
@Override
public String getDefiningClass() {
return dexFile.getType(dexFile.readUshort(dexFile.getMethodIdItemOffset(methodIndex) +
return dexFile.getTypeSection().get(dexFile.readUshort(dexFile.getMethodSection().getOffset(methodIndex) +
MethodIdItem.CLASS_OFFSET));
}
@Nonnull
@Override
public String getName() {
return dexFile.getString(dexFile.readSmallUint(dexFile.getMethodIdItemOffset(methodIndex) +
return dexFile.getStringSection().get(dexFile.readSmallUint(dexFile.getMethodSection().getOffset(methodIndex) +
MethodIdItem.NAME_OFFSET));
}
@ -78,7 +78,7 @@ public class DexBackedMethodReference extends BaseMethodReference {
@Nonnull
@Override
public String readItem(final int index) {
return dexFile.getType(dexFile.readUshort(paramListStart + 2*index));
return dexFile.getTypeSection().get(dexFile.readUshort(paramListStart + 2*index));
}
@Override public int size() { return parameterCount; }
};
@ -90,13 +90,13 @@ public class DexBackedMethodReference extends BaseMethodReference {
@Override
public String getReturnType() {
int protoIdItemOffset = getProtoIdItemOffset();
return dexFile.getType(dexFile.readSmallUint(protoIdItemOffset + ProtoIdItem.RETURN_TYPE_OFFSET));
return dexFile.getTypeSection().get(dexFile.readSmallUint(protoIdItemOffset + ProtoIdItem.RETURN_TYPE_OFFSET));
}
private int getProtoIdItemOffset() {
if (protoIdItemOffset == 0) {
protoIdItemOffset = dexFile.getProtoIdItemOffset(
dexFile.readUshort(dexFile.getMethodIdItemOffset(methodIndex) + MethodIdItem.PROTO_OFFSET));
protoIdItemOffset = dexFile.getProtoSection().getOffset(
dexFile.readUshort(dexFile.getMethodSection().getOffset(methodIndex) + MethodIdItem.PROTO_OFFSET));
}
return protoIdItemOffset;
}
@ -114,7 +114,7 @@ public class DexBackedMethodReference extends BaseMethodReference {
@Override
public void validateReference() throws InvalidReferenceException {
if (methodIndex < 0 || methodIndex >= dexFile.getMethodCount()) {
if (methodIndex < 0 || methodIndex >= dexFile.getMethodSection().size()) {
throw new InvalidReferenceException("method@" + methodIndex);
}
}

View File

@ -50,10 +50,9 @@ public class DexBackedStringReference extends BaseStringReference {
@Nonnull
public String getString() {
return dexFile.getString(stringIndex);
return dexFile.getStringSection().get(stringIndex);
}
/**
* Calculate and return the private size of a string reference.
*
@ -64,7 +63,7 @@ public class DexBackedStringReference extends BaseStringReference {
public int getSize() {
int size = StringIdItem.ITEM_SIZE; //uint for string_data_off
//add the string data length:
int stringOffset = dexFile.getStringIdItemOffset(stringIndex);
int stringOffset = dexFile.getStringSection().getOffset(stringIndex);
int stringDataOffset = dexFile.readSmallUint(stringOffset);
DexReader reader = dexFile.readerAt(stringDataOffset);
size += reader.peekSmallUleb128Size();
@ -76,7 +75,7 @@ public class DexBackedStringReference extends BaseStringReference {
@Override
public void validateReference() throws InvalidReferenceException {
if (stringIndex < 0 || stringIndex >= dexFile.getStringCount()) {
if (stringIndex < 0 || stringIndex >= dexFile.getStringSection().size()) {
throw new InvalidReferenceException("string@" + stringIndex);
}
}

View File

@ -48,7 +48,7 @@ public class DexBackedTypeReference extends BaseTypeReference {
}
@Nonnull public String getType() {
return dexFile.getType(typeIndex);
return dexFile.getTypeSection().get(typeIndex);
}
@ -65,7 +65,7 @@ public class DexBackedTypeReference extends BaseTypeReference {
@Override
public void validateReference() throws InvalidReferenceException {
if (typeIndex < 0 || typeIndex >= dexFile.getTypeCount()) {
if (typeIndex < 0 || typeIndex >= dexFile.getTypeSection().size()) {
throw new InvalidReferenceException("type@" + typeIndex);
}
}

View File

@ -190,8 +190,8 @@ public abstract class DebugInfo implements Iterable<DebugItem> {
}
case DebugItemType.START_LOCAL: {
int register = reader.readSmallUleb128();
String name = dexFile.getOptionalString(reader.readSmallUleb128() - 1);
String type = dexFile.getOptionalType(reader.readSmallUleb128() - 1);
String name = dexFile.getStringSection().getOptional(reader.readSmallUleb128() - 1);
String type = dexFile.getTypeSection().getOptional(reader.readSmallUleb128() - 1);
ImmutableStartLocal startLocal =
new ImmutableStartLocal(codeAddress, register, name, type, null);
if (register >= 0 && register < locals.length) {
@ -201,9 +201,10 @@ public abstract class DebugInfo implements Iterable<DebugItem> {
}
case DebugItemType.START_LOCAL_EXTENDED: {
int register = reader.readSmallUleb128();
String name = dexFile.getOptionalString(reader.readSmallUleb128() - 1);
String type = dexFile.getOptionalType(reader.readSmallUleb128() - 1);
String signature = dexFile.getOptionalString(reader.readSmallUleb128() - 1);
String name = dexFile.getStringSection().getOptional(reader.readSmallUleb128() - 1);
String type = dexFile.getTypeSection().getOptional(reader.readSmallUleb128() - 1);
String signature = dexFile.getStringSection().getOptional(
reader.readSmallUleb128() - 1);
ImmutableStartLocal startLocal =
new ImmutableStartLocal(codeAddress, register, name, type, signature);
if (register >= 0 && register < locals.length) {
@ -261,7 +262,8 @@ public abstract class DebugInfo implements Iterable<DebugItem> {
return new ImmutableEpilogueBegin(codeAddress);
}
case DebugItemType.SET_SOURCE_FILE: {
String sourceFile = dexFile.getOptionalString(reader.readSmallUleb128() - 1);
String sourceFile = dexFile.getStringSection().getOptional(
reader.readSmallUleb128() - 1);
return new ImmutableSetSourceFile(codeAddress, sourceFile);
}
default: {
@ -287,7 +289,7 @@ public abstract class DebugInfo implements Iterable<DebugItem> {
final int parameterNameCount = reader.readSmallUleb128();
return new VariableSizeIterator<String>(reader, parameterNameCount) {
@Override protected String readNextItem(@Nonnull DexReader reader, int index) {
return dexFile.getOptionalString(reader.readSmallUleb128() - 1);
return dexFile.getStringSection().getOptional(reader.readSmallUleb128() - 1);
}
};
}

View File

@ -49,7 +49,7 @@ public class DexBackedAnnotationEncodedValue extends BaseAnnotationEncodedValue
public DexBackedAnnotationEncodedValue(@Nonnull DexReader reader) {
this.dexFile = reader.dexBuf;
this.type = dexFile.getType(reader.readSmallUleb128());
this.type = dexFile.getTypeSection().get(reader.readSmallUleb128());
this.elementCount = reader.readSmallUleb128();
this.elementsOffset = reader.getOffset();
skipElements(reader, elementCount);

View File

@ -47,6 +47,6 @@ public class DexBackedStringEncodedValue extends BaseStringEncodedValue {
}
@Nonnull @Override public String getValue() {
return dexFile.getString(stringIndex);
return dexFile.getStringSection().get(stringIndex);
}
}

View File

@ -47,6 +47,6 @@ public class DexBackedTypeEncodedValue extends BaseTypeEncodedValue {
}
@Nonnull @Override public String getValue() {
return dexFile.getType(typeIndex);
return dexFile.getTypeSection().get(typeIndex);
}
}