dex文件格式入门

参考

        参考一

        参考二

        参考三

结构图

图一:


点击查看来源

header

        从上图中列表可以看出,每一荐占有的字节数。除magic(就是用于标识该文件是dex文件与当前的版本号的)以及signature(签名验证)外,其余都是占四个字节。uint指的是unsigned int即无符号int类型。

        对于method_ids_size来说,它一共32位,所以表示的最大数为2的32次方,因此一个dex文件最多就只能有65536个方法。

map_offset

        这应该是header中最难理解的一个。其实它指的是map_list的偏移量。首先看一个.dex文件的header。如下:


其中红框中的就是map_list的偏移量——3c48,因为endian_tag是78563412,所以读的值是3c48。

        再看3c48处的内容


        其4个字节的值是0x12,也就是18。

        现在看一下map_list的数据结构。如下:

/*
*Direct-mapped "map_list".
*/   typedef struct DexMapList {
    u4 size; /* #of entries inlist */
    DexMapItem list[1]; /* entries */
}DexMapList;
        从中可以看出,3c48处的值0x12指的就是该结构体的size,因为0x12指的是一共有18个DexMapItem。

        再看一下DexMapItem的数据结构。如下:

/*
*Direct-mapped "map_item".
*/   typedef struct DexMapItem {
    u2 type; /* type code (seekDexType* above) */
    u2 unused;
    u4 size; /* count of items ofthe indicated type */
    u4 offset; /* file offset tothe start of data */
}DexMapItem;

        从中可以看出,每一个item一共有12个字节(这一点从图一中的最右边的上半部分也可以看得出来)。

        从3c4c开始(含,因为3c48用于存储map_list的size,不能算在内),每12个字节算一个,数到.dex文件最后,一共会有18个(即3c48指定的0x12)。

        下面分析3c4c到3c57这12个字节的里的内容——从上面知道它是一个map_item。

        3c3c-3c4d表示map_item中的type,此时是00,所以type类型为0,再对照type表格,可以看出它指的是HEADER_ITEM;3c4e-3c4f指的是map_item中的unused,也就是没有使用的部分,所以全部是0。3c50-3c53,指的是map_item中的size,此处值为1,也就是只有一个dex文件;3c54-3c57,全部是0,也就是说header的偏移为0,即从.dex的开头处开始算。

        再看3c58-3c63,根据上面的分析可以看出,它指的是STRING_ID_ITEM,共有0x118个,偏移量为0x70。再跟header中指向string_id的进行比对,可以发现是一样的。如下:

图二


其余的几个item一样可以进行比对,都是一样的。

string_id_size/off

        用于标识字符串,前者表示字符串的个数,后者表示字符串开始的处的偏移量。从上图中可以看出,字符串共有0x118个,从0x70处开始;type共有0x3e个,从0x4d0开始。而(0x4d0-0x70)/0x118结果为4,也就是说从0x70处开始,每4个字节表示一个字符串具体值在dex文件中的偏移量。这一点,从其定义处也可以看出来:

/*
 * Direct-mapped "string_id_item".
 */
typedef struct DexStringId {
    u4  stringDataOff;      /* file offset to string_data_item */
} DexStringId;
下面是0x22a6处的数据,如下:


在0x22a6的下一个字符串为0x22a8,这中间的的数据就是0x0000。

        字符串的结尾是为'\0'字符标识的,所以上面的0x0000中的后两位就是用来表示字符串结束符的。而前两个0表示字符串一个有多少个字节(不包含最后的结尾符,也不包含这个字节本身)

        如上图,0x22AB处为0x06,也就表示有6个字节,因此0x3c696e69743e表示一个字符串<init>,而后面的00表示这个字符串的结束。下一个字符串开始的位置就是0x22b3,正好可以与图二对住。

type_ids_size/offset

        用于标识type的个数与偏移量。偏移位置处存储的是一些type_ids_item,它的结构体如下:

struct type_ids_item
{
uint descriptor_idx;
}
        由上可以知道每一个item只占四个字节,这四个字节表示的值是descriptor_idx(即描述下标)——它定义了这些type_item在string_item中的下标,而通过string_item又可以找到具体的文字,这些文字就是这个type的描述。如下是一个dex文件的信息(图三)


        从中可以看出一共有6个type,type_item的偏移量为0xa8。从0xa8处往下数6个,分别是0x2,0x3,0x4,0x5,0x6与0x7。这些值分别表示这个type的描述在string_item中的下标。

        而string_item的偏移量为0x70,且每四位代表一个string,所以下标为0x2的string的偏移量为0x186。在0x186处,数据为0x01,再根据前面关于string的理解可以知道,这个string只有一个字符,就是0x01下面的一个——0x4a(它对应的是J,即long),0x4a下一个字节为00,代表这个字符串的结束。

        同样,可知0x3的偏移量为0x189,在0x189处为0x26,即共38个字节,到0xaf结束(下一个0x1b1表示这个字符串的结束,不考虑),这中间的字符串就是Lcom/android/tools/fd/runtime/AppInfo;,再根据类的签名可知:它代表的是com.android.tools.fd.runtime包下的AppInfo类,这即是0x3的type的描述。

        根据上面的思路可以分析出0x6为void,0x7为boolean的。




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值