dex文件结构

上文分析了class文件的结构,这里我们分析dex的文件结构

通过如下命令把上文的.class文件生成dex文件

 dx --dex --output Test33.dex .\Test2.class


首先我们来看下dex文件整体的一个结构

DEX文件的基本结构如下图

header
string_ids
type_ids
proto_ids
field_ids
method_ids
class_def
data
link_data

这里我们可以用010 Editor来查看dex文件的结构


跟我们上面列出来的基本是一致的

我们先看下dex的 header

Dex文件头主要包括校验和以及其他结构的偏移地址和长度信息:

字段名称偏移值长度描述
magic0x08'Magic'值,即魔数字段,格式如”dex/n035/0”,其中的035表示结构的版本。
checksum0x84校验码。
signature0xC20SHA-1签名。
file_size0x204Dex文件的总长度。
header_size0x244文件头长度,009版本=0x5C,035版本=0x70。
endian_tag0x284标识字节顺序的常量,根据这个常量可以判断文件是否交换了字节顺序,缺省情况下=0x78563412。
link_size0x2C4连接段的大小,如果为0就表示是静态连接。
link_off0x304连接段的开始位置,从本文件头开始算起。如果连接段的大小为0,这里也是0。
map_off0x344map数据基地址。
string_ids_size0x384字符串列表的字符串个数。
string_ids_off0x3C4字符串列表表基地址。
type_ids_size0x404类型列表里类型个数。
type_ids_off0x444类型列表基地址。
proto_ids_size0x484原型列表里原型个数。
proto_ids_off0x4C4原型列表基地址。
field_ids_size0x504字段列表里字段个数。
field_ids_off0x544字段列表基地址。
method_ids_size0x584方法列表里方法个数。
method_ids_off0x5C4方法列表基地址。
class_defs_size0x604类定义类表中类的个数。
class_defs_off0x644类定义列表基地址。
data_size0x684数据段的大小,必须以4字节对齐。
data_off0x6C4数据段基地址

同样我们可以使用 010 Editor来查看header部分

看下字段介绍

magic[8]:共8个字节。目前为固定值dex\n035。
checksum:文件校验码,使用alder32算法校验文件除去magic、checksum外余下的所有文件区域,用于检查文件错误。
signature:使用 SHA-1算法hash除去magic,checksum和signature外余下的所有文件区域 ,用于唯一识别本文件 。
fileSize:DEX文件的长度。
headerSize:header大小,一般固定为0x70字节。
endianTag:指定了DEX运行环境的cpu字节序,预设值ENDIAN_CONSTANT等于0x12345678,表示默认采用Little-Endian字节序。
linkSize和linkOff:指定链接段的大小与文件偏移,大多数情况下它们的值都为0。link_size:LinkSection大小,如果为0则表示该DEX文件不是静态链接。link_off用来表示LinkSection距离DEX头的偏移地址,如果LinkSize为0,此值也会为0。
mapOff:DexMapList结构的文件偏移。
stringIdsSize和stringIdsOff:DexStringId结构的数据段大小与文件偏移。
typeIdsSize和typeIdsOff:DexTypeId结构的数据段大小与文件偏移。
protoIdsSize和protoIdsSize:DexProtoId结构的数据段大小与文件偏移。
fieldIdsSize和fieldIdsSize:DexFieldId结构的数据段大小与文件偏移。
methodIdsSize和methodIdsSize:DexMethodId结构的数据段大小与文件偏移。
classDefsSize和classDefsOff:DexClassDef结构的数据段大小与文件偏移。
dataSize和dataOff:数据段的大小与文件偏移


这里我们主要看mapOff指向的DexMapList

struct DexMapList {
    u4 size;               /* DexMapItem的个数 */
    DexMapItem list[1];    /* DexMapItem的结构 */
};

struct DexMapItem {   
    u2 type;      /* kDexType开头的类型 */
    u2 unused;  /* 未使用,用于字节对齐 */
    u4 size;    /* type指定类型的个数,它们在dex文件中连续存放 */
    u4 offset;  /* 指定类型数据的文件偏移 */
};

/* type字段为一个枚举常量,通过类型名称很容易判断它的具体类型。 */
/* map item type codes */
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,
};

这里我们可以看到通过DexMapItem中的kDexTypeStringIdItem可以找到string类型的偏移,同样通过header头中的 stringIdsOff也可以找到string的偏移,这里两者是一致的,我们通过010 Editor看看



可以看到两个地方的偏移都是112,同样,其他的字段想porto等也是这样的



通过工具,我们可以很好的分析出dex文件的结构

dex文件的string相当于一个常量池,然后其他的type,proto,field、method等都是存在一块的,各个又通过引用string中的索引来表示,而不是像class文件中直接通过常量池中的索引来表示,所以相对于class文件,dex多存储了一些信息,同样内容的class文件,转为dex文件后,dex文件会稍微大点

但是dex文件可以中可以同时包含很多个类,而一个class文件中只能对应一个类

关于dex文件结构,就了解这么多了。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值