summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeyi Gui <kgui@google.com>2024-01-12 03:13:04 +0000
committerGerrit Code Review <noreply-gerritcodereview@google.com>2024-01-12 03:13:04 +0000
commit1bed4bab8b4852209d6f24de538b5aaa2cca0b20 (patch)
treef6cf7dad0fff19e46d52892ddf9b17832eedea04
parentbd9032155f1699881a7bd87eec03c5c31fff6793 (diff)
parentd7e9884f2f0b275921df0f36b33b91fddeafe1fc (diff)
downloaddalvik-1bed4bab8b4852209d6f24de538b5aaa2cca0b20.tar.gz
Merge "Support v41 DEX version for dexdeps." into main
-rw-r--r--tools/dexdeps/src/com/android/dexdeps/DexData.java276
1 files changed, 122 insertions, 154 deletions
diff --git a/tools/dexdeps/src/com/android/dexdeps/DexData.java b/tools/dexdeps/src/com/android/dexdeps/DexData.java
index 1b6cc98ed..e7f9a53a4 100644
--- a/tools/dexdeps/src/com/android/dexdeps/DexData.java
+++ b/tools/dexdeps/src/com/android/dexdeps/DexData.java
@@ -23,13 +23,11 @@ import java.nio.ByteOrder;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
-/**
- * Data extracted from a DEX file.
- */
+/** Data extracted from a DEX file. */
public class DexData {
private RandomAccessFile mDexFile;
private HeaderItem mHeaderItem;
- private String[] mStrings; // strings from string_data_*
+ private String[] mStrings; // strings from string_data_*
private TypeIdItem[] mTypeIds;
private ProtoIdItem[] mProtoIds;
private FieldIdItem[] mFieldIds;
@@ -39,9 +37,7 @@ public class DexData {
private byte tmpBuf[] = new byte[4];
private ByteOrder mByteOrder = ByteOrder.LITTLE_ENDIAN;
- /**
- * Constructs a new DexData for this file.
- */
+ /** Constructs a new DexData for this file. */
public DexData(RandomAccessFile raf) {
mDexFile = raf;
}
@@ -65,19 +61,16 @@ public class DexData {
markInternalClasses();
}
- /**
- * Verifies the given magic number.
- */
+ /** Verifies the given magic number. */
private static boolean verifyMagic(byte[] magic) {
- return Arrays.equals(magic, HeaderItem.DEX_FILE_MAGIC_v035) ||
- Arrays.equals(magic, HeaderItem.DEX_FILE_MAGIC_v037) ||
- Arrays.equals(magic, HeaderItem.DEX_FILE_MAGIC_v038) ||
- Arrays.equals(magic, HeaderItem.DEX_FILE_MAGIC_v039);
+ return Arrays.equals(magic, HeaderItem.DEX_FILE_MAGIC_v035)
+ || Arrays.equals(magic, HeaderItem.DEX_FILE_MAGIC_v037)
+ || Arrays.equals(magic, HeaderItem.DEX_FILE_MAGIC_v038)
+ || Arrays.equals(magic, HeaderItem.DEX_FILE_MAGIC_v039)
+ || Arrays.equals(magic, HeaderItem.DEX_FILE_MAGIC_v041);
}
- /**
- * Parses the interesting bits out of the header.
- */
+ /** Parses the interesting bits out of the header. */
void parseHeaderItem() throws IOException {
mHeaderItem = new HeaderItem();
@@ -86,8 +79,7 @@ public class DexData {
byte[] magic = new byte[8];
readBytes(magic);
if (!verifyMagic(magic)) {
- System.err.println("Magic number is wrong -- are you sure " +
- "this is a DEX file?");
+ System.err.println("Magic number is wrong -- are you sure " + "this is a DEX file?");
throw new DexDataException();
}
@@ -95,20 +87,21 @@ public class DexData {
* Read the endian tag, so we properly swap things as we read
* them from here on.
*/
- seek(8+4+20+4+4);
+ seek(8 + 4 + 20 + 4 + 4);
mHeaderItem.endianTag = readInt();
if (mHeaderItem.endianTag == HeaderItem.ENDIAN_CONSTANT) {
/* do nothing */
- } else if (mHeaderItem.endianTag == HeaderItem.REVERSE_ENDIAN_CONSTANT){
+ } else if (mHeaderItem.endianTag == HeaderItem.REVERSE_ENDIAN_CONSTANT) {
/* file is big-endian (!), reverse future reads */
mByteOrder = ByteOrder.BIG_ENDIAN;
} else {
- System.err.println("Endian constant has unexpected value " +
- Integer.toHexString(mHeaderItem.endianTag));
+ System.err.println(
+ "Endian constant has unexpected value "
+ + Integer.toHexString(mHeaderItem.endianTag));
throw new DexDataException();
}
- seek(8+4+20); // magic, checksum, signature
+ seek(8 + 4 + 20); // magic, checksum, signature
ByteBuffer buffer = readByteBuffer(Integer.BYTES * 20);
mHeaderItem.fileSize = buffer.getInt();
mHeaderItem.headerSize = buffer.getInt();
@@ -135,15 +128,14 @@ public class DexData {
/**
* Loads the string table out of the DEX.
*
- * First we read all of the string_id_items, then we read all of the
- * string_data_item. Doing it this way should allow us to avoid
- * seeking around in the file.
+ * <p>First we read all of the string_id_items, then we read all of the string_data_item. Doing
+ * it this way should allow us to avoid seeking around in the file.
*/
void loadStrings() throws IOException {
int count = mHeaderItem.stringIdsSize;
int stringOffsets[] = new int[count];
- //System.out.println("reading " + count + " strings");
+ // System.out.println("reading " + count + " strings");
seek(mHeaderItem.stringIdsOff);
readByteBuffer(Integer.BYTES * count).asIntBuffer().get(stringOffsets);
@@ -152,39 +144,35 @@ public class DexData {
seek(stringOffsets[0]);
for (int i = 0; i < count; i++) {
- seek(stringOffsets[i]); // should be a no-op
+ seek(stringOffsets[i]); // should be a no-op
mStrings[i] = readString();
- //System.out.println("STR: " + i + ": " + mStrings[i]);
+ // System.out.println("STR: " + i + ": " + mStrings[i]);
}
}
- /**
- * Loads the type ID list.
- */
+ /** Loads the type ID list. */
void loadTypeIds() throws IOException {
int count = mHeaderItem.typeIdsSize;
mTypeIds = new TypeIdItem[count];
- //System.out.println("reading " + count + " typeIds");
+ // System.out.println("reading " + count + " typeIds");
seek(mHeaderItem.typeIdsOff);
ByteBuffer buffer = readByteBuffer(Integer.BYTES * count);
for (int i = 0; i < count; i++) {
mTypeIds[i] = new TypeIdItem();
mTypeIds[i].descriptorIdx = buffer.getInt();
- //System.out.println(i + ": " + mTypeIds[i].descriptorIdx +
+ // System.out.println(i + ": " + mTypeIds[i].descriptorIdx +
// " " + mStrings[mTypeIds[i].descriptorIdx]);
}
}
- /**
- * Loads the proto ID list.
- */
+ /** Loads the proto ID list. */
void loadProtoIds() throws IOException {
int count = mHeaderItem.protoIdsSize;
mProtoIds = new ProtoIdItem[count];
- //System.out.println("reading " + count + " protoIds");
+ // System.out.println("reading " + count + " protoIds");
seek(mHeaderItem.protoIdsOff);
ByteBuffer buffer = readByteBuffer(Integer.BYTES * 3 * count);
@@ -197,7 +185,7 @@ public class DexData {
mProtoIds[i].returnTypeIdx = buffer.getInt();
mProtoIds[i].parametersOff = buffer.getInt();
- //System.out.println(i + ": " + mProtoIds[i].shortyIdx +
+ // System.out.println(i + ": " + mProtoIds[i].shortyIdx +
// " " + mStrings[mProtoIds[i].shortyIdx]);
}
@@ -214,7 +202,7 @@ public class DexData {
continue;
} else {
seek(offset);
- int size = readInt(); // #of entries in list
+ int size = readInt(); // #of entries in list
buffer = readByteBuffer(Short.BYTES * size);
protoId.types = new int[size];
@@ -225,14 +213,12 @@ public class DexData {
}
}
- /**
- * Loads the field ID list.
- */
+ /** Loads the field ID list. */
void loadFieldIds() throws IOException {
int count = mHeaderItem.fieldIdsSize;
mFieldIds = new FieldIdItem[count];
- //System.out.println("reading " + count + " fieldIds");
+ // System.out.println("reading " + count + " fieldIds");
seek(mHeaderItem.fieldIdsOff);
ByteBuffer buffer = readByteBuffer((Integer.BYTES + Short.BYTES * 2) * count);
for (int i = 0; i < count; i++) {
@@ -241,19 +227,17 @@ public class DexData {
mFieldIds[i].typeIdx = buffer.getShort() & 0xffff;
mFieldIds[i].nameIdx = buffer.getInt();
- //System.out.println(i + ": " + mFieldIds[i].nameIdx +
+ // System.out.println(i + ": " + mFieldIds[i].nameIdx +
// " " + mStrings[mFieldIds[i].nameIdx]);
}
}
- /**
- * Loads the method ID list.
- */
+ /** Loads the method ID list. */
void loadMethodIds() throws IOException {
int count = mHeaderItem.methodIdsSize;
mMethodIds = new MethodIdItem[count];
- //System.out.println("reading " + count + " methodIds");
+ // System.out.println("reading " + count + " methodIds");
seek(mHeaderItem.methodIdsOff);
ByteBuffer buffer = readByteBuffer((Integer.BYTES + Short.BYTES * 2) * count);
for (int i = 0; i < count; i++) {
@@ -262,44 +246,42 @@ public class DexData {
mMethodIds[i].protoIdx = buffer.getShort() & 0xffff;
mMethodIds[i].nameIdx = buffer.getInt();
- //System.out.println(i + ": " + mMethodIds[i].nameIdx +
+ // System.out.println(i + ": " + mMethodIds[i].nameIdx +
// " " + mStrings[mMethodIds[i].nameIdx]);
}
}
- /**
- * Loads the class defs list.
- */
+ /** Loads the class defs list. */
void loadClassDefs() throws IOException {
int count = mHeaderItem.classDefsSize;
mClassDefs = new ClassDefItem[count];
- //System.out.println("reading " + count + " classDefs");
+ // System.out.println("reading " + count + " classDefs");
seek(mHeaderItem.classDefsOff);
ByteBuffer buffer = readByteBuffer(Integer.BYTES * 8 * count);
for (int i = 0; i < count; i++) {
mClassDefs[i] = new ClassDefItem();
mClassDefs[i].classIdx = buffer.getInt();
- /* access_flags = */ buffer.getInt();
- /* superclass_idx = */ buffer.getInt();
- /* interfaces_off = */ buffer.getInt();
- /* source_file_idx = */ buffer.getInt();
- /* annotations_off = */ buffer.getInt();
- /* class_data_off = */ buffer.getInt();
- /* static_values_off = */ buffer.getInt();
+ /* access_flags= */ buffer.getInt();
+ /* superclass_idx= */ buffer.getInt();
+ /* interfaces_off= */ buffer.getInt();
+ /* source_file_idx= */ buffer.getInt();
+ /* annotations_off= */ buffer.getInt();
+ /* class_data_off= */ buffer.getInt();
+ /* static_values_off= */ buffer.getInt();
- //System.out.println(i + ": " + mClassDefs[i].classIdx + " " +
+ // System.out.println(i + ": " + mClassDefs[i].classIdx + " " +
// mStrings[mTypeIds[mClassDefs[i].classIdx].descriptorIdx]);
}
}
/**
- * Sets the "internal" flag on type IDs which are defined in the
- * DEX file or within the VM (e.g. primitive classes and arrays).
+ * Sets the "internal" flag on type IDs which are defined in the DEX file or within the VM (e.g.
+ * primitive classes and arrays).
*/
void markInternalClasses() {
- for (int i = mClassDefs.length -1; i >= 0; i--) {
+ for (int i = mClassDefs.length - 1; i >= 0; i--) {
mTypeIds[mClassDefs[i].classIdx].internal = true;
}
@@ -313,29 +295,25 @@ public class DexData {
mTypeIds[i].internal = true;
}
- //System.out.println(i + " " +
+ // System.out.println(i + " " +
// (mTypeIds[i].internal ? "INTERNAL" : "external") + " - " +
// mStrings[mTypeIds[i].descriptorIdx]);
}
}
-
/*
* =======================================================================
* Queries
* =======================================================================
*/
- /**
- * Returns the class name, given an index into the type_ids table.
- */
+ /** Returns the class name, given an index into the type_ids table. */
private String classNameFromTypeIndex(int idx) {
return mStrings[mTypeIds[idx].descriptorIdx];
}
/**
- * Returns an array of method argument type strings, given an index
- * into the proto_ids table.
+ * Returns an array of method argument type strings, given an index into the proto_ids table.
*/
private String[] argArrayFromProtoIndex(int idx) {
ProtoIdItem protoId = mProtoIds[idx];
@@ -349,8 +327,8 @@ public class DexData {
}
/**
- * Returns a string representing the method's return type, given an
- * index into the proto_ids table.
+ * Returns a string representing the method's return type, given an index into the proto_ids
+ * table.
*/
private String returnTypeFromProtoIndex(int idx) {
ProtoIdItem protoId = mProtoIds[idx];
@@ -358,9 +336,8 @@ public class DexData {
}
/**
- * Returns an array with all of the class references that don't
- * correspond to classes in the DEX file. Each class reference has
- * a list of the referenced fields and methods associated with
+ * Returns an array with all of the class references that don't correspond to classes in the DEX
+ * file. Each class reference has a list of the referenced fields and methods associated with
* that class.
*/
public ClassRef[] getExternalReferences() {
@@ -371,8 +348,7 @@ public class DexData {
int count = 0;
for (int i = 0; i < mTypeIds.length; i++) {
if (!mTypeIds[i].internal) {
- sparseRefs[i] =
- new ClassRef(mStrings[mTypeIds[i].descriptorIdx]);
+ sparseRefs[i] = new ClassRef(mStrings[mTypeIds[i].descriptorIdx]);
count++;
}
}
@@ -385,8 +361,7 @@ public class DexData {
ClassRef[] classRefs = new ClassRef[count];
int idx = 0;
for (int i = 0; i < mTypeIds.length; i++) {
- if (sparseRefs[i] != null)
- classRefs[idx++] = sparseRefs[i];
+ if (sparseRefs[i] != null) classRefs[idx++] = sparseRefs[i];
}
assert idx == count;
@@ -395,87 +370,84 @@ public class DexData {
}
/**
- * Runs through the list of field references, inserting external
- * references into the appropriate ClassRef.
+ * Runs through the list of field references, inserting external references into the appropriate
+ * ClassRef.
*/
private void addExternalFieldReferences(ClassRef[] sparseRefs) {
for (int i = 0; i < mFieldIds.length; i++) {
if (!mTypeIds[mFieldIds[i].classIdx].internal) {
FieldIdItem fieldId = mFieldIds[i];
- FieldRef newFieldRef = new FieldRef(
- classNameFromTypeIndex(fieldId.classIdx),
- classNameFromTypeIndex(fieldId.typeIdx),
- mStrings[fieldId.nameIdx]);
+ FieldRef newFieldRef =
+ new FieldRef(
+ classNameFromTypeIndex(fieldId.classIdx),
+ classNameFromTypeIndex(fieldId.typeIdx),
+ mStrings[fieldId.nameIdx]);
sparseRefs[mFieldIds[i].classIdx].addField(newFieldRef);
}
}
}
/**
- * Runs through the list of method references, inserting external
- * references into the appropriate ClassRef.
+ * Runs through the list of method references, inserting external references into the
+ * appropriate ClassRef.
*/
private void addExternalMethodReferences(ClassRef[] sparseRefs) {
for (int i = 0; i < mMethodIds.length; i++) {
if (!mTypeIds[mMethodIds[i].classIdx].internal) {
MethodIdItem methodId = mMethodIds[i];
- MethodRef newMethodRef = new MethodRef(
- classNameFromTypeIndex(methodId.classIdx),
- argArrayFromProtoIndex(methodId.protoIdx),
- returnTypeFromProtoIndex(methodId.protoIdx),
- mStrings[methodId.nameIdx]);
+ MethodRef newMethodRef =
+ new MethodRef(
+ classNameFromTypeIndex(methodId.classIdx),
+ argArrayFromProtoIndex(methodId.protoIdx),
+ returnTypeFromProtoIndex(methodId.protoIdx),
+ mStrings[methodId.nameIdx]);
sparseRefs[mMethodIds[i].classIdx].addMethod(newMethodRef);
}
}
}
-
/*
* =======================================================================
* Basic I/O functions
* =======================================================================
*/
- /**
- * Seeks the DEX file to the specified absolute position.
- */
+ /** Seeks the DEX file to the specified absolute position. */
void seek(int position) throws IOException {
mDexFile.seek(position);
}
- /**
- * Fills the buffer by reading bytes from the DEX file.
- */
+ /** Fills the buffer by reading bytes from the DEX file. */
void readBytes(byte[] buffer) throws IOException {
mDexFile.readFully(buffer);
}
- /**
- * Reads a single signed byte value.
- */
+ /** Reads a single signed byte value. */
byte readByte() throws IOException {
mDexFile.readFully(tmpBuf, 0, 1);
return tmpBuf[0];
}
- /**
- * Reads a signed 32-bit integer, byte-swapping if necessary.
- */
+ /** Reads a signed 32-bit integer, byte-swapping if necessary. */
int readInt() throws IOException {
mDexFile.readFully(tmpBuf, 0, 4);
if (mByteOrder == ByteOrder.BIG_ENDIAN) {
- return (tmpBuf[3] & 0xff) | ((tmpBuf[2] & 0xff) << 8) |
- ((tmpBuf[1] & 0xff) << 16) | ((tmpBuf[0] & 0xff) << 24);
+ return (tmpBuf[3] & 0xff)
+ | ((tmpBuf[2] & 0xff) << 8)
+ | ((tmpBuf[1] & 0xff) << 16)
+ | ((tmpBuf[0] & 0xff) << 24);
} else {
- return (tmpBuf[0] & 0xff) | ((tmpBuf[1] & 0xff) << 8) |
- ((tmpBuf[2] & 0xff) << 16) | ((tmpBuf[3] & 0xff) << 24);
+ return (tmpBuf[0] & 0xff)
+ | ((tmpBuf[1] & 0xff) << 8)
+ | ((tmpBuf[2] & 0xff) << 16)
+ | ((tmpBuf[3] & 0xff) << 24);
}
}
/**
- * Reads a variable-length unsigned LEB128 value. Does not attempt to
- * verify that the value is valid.
+ * Reads a variable-length unsigned LEB128 value. Does not attempt to verify that the value is
+ * valid.
*
* @throws EOFException if we run off the end of the file
*/
@@ -504,14 +476,15 @@ public class DexData {
/**
* Reads a UTF-8 string.
*
- * We don't know how long the UTF-8 string is, so we try to read the worst case amount of bytes.
+ * <p>We don't know how long the UTF-8 string is, so we try to read the worst case amount of
+ * bytes.
*
- * Note that the dex file pointer will likely be at a wrong location after this operation, which
- * means it can't be used in the middle of sequential reads.
+ * <p>Note that the dex file pointer will likely be at a wrong location after this operation,
+ * which means it can't be used in the middle of sequential reads.
*/
String readString() throws IOException {
int utf16len = readUnsignedLeb128();
- byte inBuf[] = new byte[utf16len * 3]; // worst case
+ byte inBuf[] = new byte[utf16len * 3]; // worst case
int bytesRead = mDexFile.read(inBuf);
for (int i = 0; i < bytesRead; i++) {
@@ -530,9 +503,7 @@ public class DexData {
* =======================================================================
*/
- /**
- * Holds the contents of a header_item.
- */
+ /** Holds the contents of a header_item. */
static class HeaderItem {
public int fileSize;
public int headerSize;
@@ -546,7 +517,7 @@ public class DexData {
/* expected magic values */
public static final byte[] DEX_FILE_MAGIC_v035 =
- "dex\n035\0".getBytes(StandardCharsets.US_ASCII);
+ "dex\n035\0".getBytes(StandardCharsets.US_ASCII);
// Dex version 036 skipped because of an old dalvik bug on some versions
// of android where dex files with that version number would erroneously
@@ -554,15 +525,19 @@ public class DexData {
// V037 was introduced in API LEVEL 24
public static final byte[] DEX_FILE_MAGIC_v037 =
- "dex\n037\0".getBytes(StandardCharsets.US_ASCII);
+ "dex\n037\0".getBytes(StandardCharsets.US_ASCII);
// V038 was introduced in API LEVEL 26
public static final byte[] DEX_FILE_MAGIC_v038 =
- "dex\n038\0".getBytes(StandardCharsets.US_ASCII);
+ "dex\n038\0".getBytes(StandardCharsets.US_ASCII);
// V039 was introduced in API LEVEL 28
public static final byte[] DEX_FILE_MAGIC_v039 =
- "dex\n039\0".getBytes(StandardCharsets.US_ASCII);
+ "dex\n039\0".getBytes(StandardCharsets.US_ASCII);
+
+ // V041 will be introduced in API LEVEL 35
+ public static final byte[] DEX_FILE_MAGIC_v041 =
+ "dex\n041\0".getBytes(StandardCharsets.US_ASCII);
public static final int ENDIAN_CONSTANT = 0x12345678;
public static final int REVERSE_ENDIAN_CONSTANT = 0x78563412;
@@ -571,54 +546,47 @@ public class DexData {
/**
* Holds the contents of a type_id_item.
*
- * This is chiefly a list of indices into the string table. We need
- * some additional bits of data, such as whether or not the type ID
- * represents a class defined in this DEX, so we use an object for
- * each instead of a simple integer. (Could use a parallel array, but
- * since this is a desktop app it's not essential.)
+ * <p>This is chiefly a list of indices into the string table. We need some additional bits of
+ * data, such as whether or not the type ID represents a class defined in this DEX, so we use an
+ * object for each instead of a simple integer. (Could use a parallel array, but since this is a
+ * desktop app it's not essential.)
*/
static class TypeIdItem {
- public int descriptorIdx; // index into string_ids
+ public int descriptorIdx; // index into string_ids
- public boolean internal; // defined within this DEX file?
+ public boolean internal; // defined within this DEX file?
}
- /**
- * Holds the contents of a proto_id_item.
- */
+ /** Holds the contents of a proto_id_item. */
static class ProtoIdItem {
- public int shortyIdx; // index into string_ids
- public int returnTypeIdx; // index into type_ids
- public int parametersOff; // file offset to a type_list
+ public int shortyIdx; // index into string_ids
+ public int returnTypeIdx; // index into type_ids
+ public int parametersOff; // file offset to a type_list
- public int types[]; // contents of type list
+ public int types[]; // contents of type list
}
- /**
- * Holds the contents of a field_id_item.
- */
+ /** Holds the contents of a field_id_item. */
static class FieldIdItem {
- public int classIdx; // index into type_ids (defining class)
- public int typeIdx; // index into type_ids (field type)
- public int nameIdx; // index into string_ids
+ public int classIdx; // index into type_ids (defining class)
+ public int typeIdx; // index into type_ids (field type)
+ public int nameIdx; // index into string_ids
}
- /**
- * Holds the contents of a method_id_item.
- */
+ /** Holds the contents of a method_id_item. */
static class MethodIdItem {
- public int classIdx; // index into type_ids
- public int protoIdx; // index into proto_ids
- public int nameIdx; // index into string_ids
+ public int classIdx; // index into type_ids
+ public int protoIdx; // index into proto_ids
+ public int nameIdx; // index into string_ids
}
/**
* Holds the contents of a class_def_item.
*
- * We don't really need a class for this, but there's some stuff in
- * the class_def_item that we might want later.
+ * <p>We don't really need a class for this, but there's some stuff in the class_def_item that
+ * we might want later.
*/
static class ClassDefItem {
- public int classIdx; // index into type_ids
+ public int classIdx; // index into type_ids
}
}