dex文件使用到的数据类型
类型 |
含义 |
u1 |
等同于uint8_t,表示1字节的无符号数 |
u2 |
等同于uint16_t,表示2字节的无符号数 |
u4 |
等同于uint32_t,表示4字节的无符号数 |
u8 |
等同于uint64_t,表示8字节的无符号数 |
sleb128 |
有符号LEB128,可变长度1~5字节 |
uleb128 |
无符号LEB128,可变长度1~5字节 |
uleb128p1 |
无符号LEB128值加1,可变长度1~5字节 |
dex文件结构
dex header |
string_ids |
type_ids |
proto_ids |
field_ids |
method_ids |
class_def |
data |
link_data |
struct DexFile {
DexHeader Header;
DexStringId StringIds[stringIdsSize];
DexTypeId TypeIds[typeIdsSize];
DexProtoId ProtoIds[protoIdsSize];
DexFieldId FieldIds[fieldIdsSize];
DexMethodId MethodIds[methodIdsSize];
DexClassDef ClassDefs[classDefsSize];
DexData Data[];
DexLink LinkData;
}
struct DexHeader{
u1 magic[8]; //dex版本标识
u4 checksum; //adler32检验 u1 signature[kSHA1DIgestLen]; //SHA-1 哈希值
u4 fileSize; //整个文件大小
u4 headerSize; //DexHeader结构大小
u4 endianTag; //字节序标记
u4 linkSize; //链接段大小
u4 linkOff; //链接段偏移
u4 mapOff; //DexMapList的文件偏移
u4 stringIdsSize; //DexStringId的个数
u4 stringIdsOff; //DexStringId的文件偏移
u4 typeIdsSize; //DexTypeId的个数
u4 typeIdsOff; //DexTypeId文件的偏移
u4 protoIdsSize; //DexProtoId的个数
u4 protoIdsOff; //DexProtoId文件的偏移
u4 fieldIdsSize; //DexFieldId的个数
u4 fieldIdsOff; //DexFieldId文件的偏移
u4 methodIdsSize; //DexMethodId的个数
u4 methodIdsOff; //DexMethodId文件的偏移
u4 classDefsSize; //DexClassDef的个数
u4 classDefsOff; //DexClassDef文件的偏移
u4 dataSize; //数据段的大小
u4 dataOff; //数据段的文件偏移
}
struct DexMapList{
u4 size; //DexMapItem的个数
DexMapItem list[1]; //DexMapItem结构
}
struct DexMapItem{
u2 type; //kDexType开头的类型
u2 unused; //未使用 用于字节对齐
u4 size; //指定类型的个数
u4 offset; //指定类型数据的文件偏移
}
type字段为一枚常量通过类型名称判断具体类型
enum{
kDexTypeHeaderItem = 0x0000,
kDexTypeStringIdItem = 0x0001,
kDexTypeTypeIdItem = 0x0002,
kDexTypeProtoIdItem = 0x0003,
kDexTypeFieldIdItem = 0x0004,
kDexTypeMethodIdItem = 0x0005,
kDexTypeClassDefItem = 0x0006,
kDexTypeMapList = 0x1000,
kDexTypeTypeList = 0x1001,
kDexTypeAnnotationSetRefList = 0x1002,
kDexTypeAnnotationSetItem = 0x1003,
kDexTypeClassDataItem = 0x2000,
kDexTypeCodeItem = 0x2001,
kDexTypeStringDataItem = 0x2002,
kDexTypeDebugInfoItem = 0x2003,
kDexTypeAnnotationItem = 0x2004,
kDexTypeEncodedArrayItem = 0x2005,
kDexTypeAnnotationsDirectoryItem = 0x2006,
}
struct DexStringId{
u4 stringDataOff; //字符串数据的偏移
}
struct DexTypeId{
u4 descriptorIdx; //指向DexStringId列表的索引
}
struct DexProtoId{
u4 shortIdx; //指向DexStringId列表的索引
u4 returnTypeIdx; //指向DexTypeId列表的索引
u4 parametersOff; //指向DexTypeList的偏移
}
struct DexTypeList{
u4 Size; //DexTypeItem的个数
DexTypeItem list[1]; //DexTypeItem结构
}
struct DexTypeItem{
u2 typeIdx; //指向DexTypeId列表的索引
}
struct DexFieldId{
u2 classIdx; //类的类型 指向DexTypeId列表的索引
u2 typeIdx; //字段类型 指向DexTypeId列表的索引
u4 nameIdx; //字段名 指向DexStringId列表的索引
}
struct DexMethodId{
u2 classIdx; //类的类型 指向DexTypeId列表的索引
u2 protoIdx; //声明类型 指向DexProtoId列表的索引
u4 nameIdx; //方法名 指向DexStringId列表的索引
}
struct DexClassDef{
u4 classIdx; //类的类型 指向DexTypeId列表的索引
u4 accessFlags; //访问标识
u4 superclassIdx; //父类类型 指向DexTypeId列表的索引
u4 interfacesOff; //接口 指向DexTypeList的偏移
u4 sourceFileIdx; //源文件名
u4 annotationsOff; //注解
u4 classDataOff; //指向DexClassDATA 结构的偏移
u4 staticValuesOff; //指向DexEncodeArray结构的偏移
}
struct DexClassData{
DexClassDataHeader header; //指定字段与方法的个数
DexField* staticFields; //静态字段 DexField结构
DexField* instanceFields; //实例字段 DexField结构
DexMethod* directMethods; //直接方法 DexMethod结构
DexMethod* virtualMethods; //虚方法 DexMethod结构
}
struct DexClassDataHeader{
u4 staticFieldsSize; //静态字段个数
u4 instanceFieldsSize; //实例字段个数
u4 directMethodsSize; //直接方法的个数
u4 virtualMethodsSize; //虚方法的个数
}
struct DexField{
u4 fieldIdx; //指向DexFieldId的索引
u4 accessFlags; //访问标识
}
struct DexMethod{
u4 methodIdx; //指向DexMethodId的索引
u4 accessFlags; //访问标识
u4 codeOff; //指向DexCode结构的偏移
}
struct DexCode{
u2 registersSize; //使用寄存器的个数
u2 inSize; //参数个数
u2 outsSize; //调用其他方法时使用的寄存器个数
u2 triesSize; //tryCatch 个数
u4 debugInfoOff; //指向调试信息的偏移
u4 InsnsSize; //指令集个数以2字节为单位
u2 Insns[1]; //指令集
}
PS:参考书籍