第4章 Android dex文件格式 第三节
2016-03-04 14:00
204 查看
第4章 dex文件格式 第三节
1、 环境配置
Ubuntu 15.10 系统 IP:192.168.153.130
理解dex文件整体结构
一、dex文件整体结构
1、 dex文件由7个部分组成。Dex header为dex文件头,它指定了dex文件的一些属性,并记录了其他6部分数据结构在dex文件中的物理偏移。String_ids到class_def结构可以理解为“索引结构区”,真实的数据存放在data数据区,最后link_data为静态链接数据区,对于目前生成dex文件而言,它始终为空。
2、 dex文件结构如下:
structDexFile {
/* directly-mapped "opt" header*/
const DexOptHeader* pOptHeader;
/* pointers to directly-mapped structs andarrays in base DEX */
const DexHeader* pHeader;
const DexStringId* pStringIds;
const DexTypeId* pTypeIds;
const DexFieldId* pFieldIds;
const DexMethodId* pMethodIds;
const DexProtoId* pProtoIds;
const DexClassDef* pClassDefs;
const DexLink* pLinkData;
3、 DexHeader结构占用0x70个字节如下:
structDexHeader {
u1 magic[8]; /* includesversion number */
u4 checksum; /* adler32checksum */
u1 signature[kSHA1DigestLen]; /* SHA-1 hash */
u4 fileSize; /* length ofentire file */
u4 headerSize; /* offset tostart of next section */
u4 endianTag;
u4 linkSize;
u4 linkOff;
u4 mapOff;
u4 stringIdsSize;
u4 stringIdsOff;
u4 typeIdsSize;
u4 typeIdsOff;
u4 protoIdsSize;
u4 protoIdsOff;
u4 fieldIdsSize;
u4 fieldIdsOff;
u4 methodIdsSize;
u4 methodIdsOff;
u4 classDefsSize;
u4 classDefsOff;
u4 dataSize;
u4 dataOff;
};
1)Magic字段标识了一个有效的dex文件,目前它的值固定为“64 65 78 0a 30 33 35 00”,转换为字符串为“dex.035”。
2)chencksum段为dex文件的校验和,通过它来判断dex文件是否被损坏或修改。
3)Signature字段用来识别最佳化之间的dex文件,checksum字段与signature字段将dexopt验证与优化。
4)FileSize字段记录了包括DexHeader在内的整个dex文件的大小。
5)HeaderSize字段记录了DexHeader结构本身占用的字节数,目前它的值为0x70。
6)endianTag字段指定了dex运行环境cpu字节序,预设值ENDIAN_CONSTANT等于0x12345678,表示默认采用Little-Endian字节序。
7)linkSize字段与stringldsOff字段指定链接段的大小与文件偏移,大多数情况下它们的值为0。
8)mapOff字段指定了DexMapList结构的文件偏移。
9)其他字段分别表示DexStringid、DexTypeid、DexProtoid、DexFieldid、DexMethonid、DexClassDef以及数据段的大小与文件偏移。
4、 DexHeader结构下面的数据为“索引结构区” 与“数据区”,“索引结构区”中各数据结构的偏移地址都是从DexHeader结构的stringIdsOff~classDefsOff字段的值指定的,它们并非真正的类数据,而是指向dex文件的data数据区的偏移或数据结构索引。(DexData字段,实际上是ubyte字节数组,包含了程序所有使用到的数据)
二、dex文件结构分析
1、 Dalvik虚拟机解析dex文件的内容,最终将其映射成DexMapList数据结构。DexHeader结构的mapOff字段指明了DexMaplist结构在dex文件中的偏移,声明如下。
Struct DexMapList{
U4 size; /*DexMapItem的个数*/
DexMapItemlist[1]; /*DexMapItem结构*/
};
2、Size 字段表示接下来有多少个DexMapItem结构,DexMapItem的结构声明如下。
Struct DexMapItem {
U2 type; /*kDexType开头的类型*/
U2 unused; /*未使用,用于字节对齐*/
U4 size; /*指定类型的个数*/
U4 offset; /*指定类型数据的文件偏移*/
};
2、 type字段为一个枚举常量,如下所示名称,通过类型很容易判断它的具体类型。
Enum{
kDexTypeHeaderItem = 0x0000,
kDexTypeStringIdItem = 0x0001,
kDexTypeTypeIdItem = 0x0002,
kDexTypeProtoIdItem = 0x0003,
kDexTypeFieldIdItem = 0x0004,
kDexTypeMethodIdItem = 0x0005,
……….
……….
kDexTypeAnnotationsDirectoryItem = 0x2006,
};
DexMapItem中的size字段指定了特定类型的个数,它们以特定的类型在dex文件中连续存放。Offset为该类型的文件起始偏移地址。以Hello.dex为例,DexHeader结构的mapOff字段为0x290,读取0x290处的一个双字值为0x0d,表明接下来会有13个DexMapItem结构。使用hexdump –C命令打开Hello.dex,如下图:
注意:通过DexMapItem定义可以发现:这个定义的像类、字符串、方法等资源和dex文件头里定义的类型有很多是一样的。其实这个map的数据,就是头里类型的重复,完全是为了检验作用而存在的。当andriod系统加载dex文件时,如果比较文件头类型个数与map里类型不一致时,就会停止使用这个dex文件。
1、 环境配置
Ubuntu 15.10 系统 IP:192.168.153.130
理解dex文件整体结构
一、dex文件整体结构
1、 dex文件由7个部分组成。Dex header为dex文件头,它指定了dex文件的一些属性,并记录了其他6部分数据结构在dex文件中的物理偏移。String_ids到class_def结构可以理解为“索引结构区”,真实的数据存放在data数据区,最后link_data为静态链接数据区,对于目前生成dex文件而言,它始终为空。
Dex header |
String_ids |
Type_ids |
Proto_ids |
Field_ids |
Methon_ids |
Class_ids |
data |
Link_data |
structDexFile {
/* directly-mapped "opt" header*/
const DexOptHeader* pOptHeader;
/* pointers to directly-mapped structs andarrays in base DEX */
const DexHeader* pHeader;
const DexStringId* pStringIds;
const DexTypeId* pTypeIds;
const DexFieldId* pFieldIds;
const DexMethodId* pMethodIds;
const DexProtoId* pProtoIds;
const DexClassDef* pClassDefs;
const DexLink* pLinkData;
3、 DexHeader结构占用0x70个字节如下:
structDexHeader {
u1 magic[8]; /* includesversion number */
u4 checksum; /* adler32checksum */
u1 signature[kSHA1DigestLen]; /* SHA-1 hash */
u4 fileSize; /* length ofentire file */
u4 headerSize; /* offset tostart of next section */
u4 endianTag;
u4 linkSize;
u4 linkOff;
u4 mapOff;
u4 stringIdsSize;
u4 stringIdsOff;
u4 typeIdsSize;
u4 typeIdsOff;
u4 protoIdsSize;
u4 protoIdsOff;
u4 fieldIdsSize;
u4 fieldIdsOff;
u4 methodIdsSize;
u4 methodIdsOff;
u4 classDefsSize;
u4 classDefsOff;
u4 dataSize;
u4 dataOff;
};
1)Magic字段标识了一个有效的dex文件,目前它的值固定为“64 65 78 0a 30 33 35 00”,转换为字符串为“dex.035”。
2)chencksum段为dex文件的校验和,通过它来判断dex文件是否被损坏或修改。
3)Signature字段用来识别最佳化之间的dex文件,checksum字段与signature字段将dexopt验证与优化。
4)FileSize字段记录了包括DexHeader在内的整个dex文件的大小。
5)HeaderSize字段记录了DexHeader结构本身占用的字节数,目前它的值为0x70。
6)endianTag字段指定了dex运行环境cpu字节序,预设值ENDIAN_CONSTANT等于0x12345678,表示默认采用Little-Endian字节序。
7)linkSize字段与stringldsOff字段指定链接段的大小与文件偏移,大多数情况下它们的值为0。
8)mapOff字段指定了DexMapList结构的文件偏移。
9)其他字段分别表示DexStringid、DexTypeid、DexProtoid、DexFieldid、DexMethonid、DexClassDef以及数据段的大小与文件偏移。
4、 DexHeader结构下面的数据为“索引结构区” 与“数据区”,“索引结构区”中各数据结构的偏移地址都是从DexHeader结构的stringIdsOff~classDefsOff字段的值指定的,它们并非真正的类数据,而是指向dex文件的data数据区的偏移或数据结构索引。(DexData字段,实际上是ubyte字节数组,包含了程序所有使用到的数据)
二、dex文件结构分析
1、 Dalvik虚拟机解析dex文件的内容,最终将其映射成DexMapList数据结构。DexHeader结构的mapOff字段指明了DexMaplist结构在dex文件中的偏移,声明如下。
Struct DexMapList{
U4 size; /*DexMapItem的个数*/
DexMapItemlist[1]; /*DexMapItem结构*/
};
2、Size 字段表示接下来有多少个DexMapItem结构,DexMapItem的结构声明如下。
Struct DexMapItem {
U2 type; /*kDexType开头的类型*/
U2 unused; /*未使用,用于字节对齐*/
U4 size; /*指定类型的个数*/
U4 offset; /*指定类型数据的文件偏移*/
};
2、 type字段为一个枚举常量,如下所示名称,通过类型很容易判断它的具体类型。
Enum{
kDexTypeHeaderItem = 0x0000,
kDexTypeStringIdItem = 0x0001,
kDexTypeTypeIdItem = 0x0002,
kDexTypeProtoIdItem = 0x0003,
kDexTypeFieldIdItem = 0x0004,
kDexTypeMethodIdItem = 0x0005,
……….
……….
kDexTypeAnnotationsDirectoryItem = 0x2006,
};
DexMapItem中的size字段指定了特定类型的个数,它们以特定的类型在dex文件中连续存放。Offset为该类型的文件起始偏移地址。以Hello.dex为例,DexHeader结构的mapOff字段为0x290,读取0x290处的一个双字值为0x0d,表明接下来会有13个DexMapItem结构。使用hexdump –C命令打开Hello.dex,如下图:
注意:通过DexMapItem定义可以发现:这个定义的像类、字符串、方法等资源和dex文件头里定义的类型有很多是一样的。其实这个map的数据,就是头里类型的重复,完全是为了检验作用而存在的。当andriod系统加载dex文件时,如果比较文件头类型个数与map里类型不一致时,就会停止使用这个dex文件。
相关文章推荐
- Android Studio 更换国内源下载依赖库
- [置顶] Android WiFi开发 (一)扫描、连接、信息
- Android中Preference的使用以及监听事件分析
- Android Activity:四种启动模式,Intent Flags和任务栈
- Android万能标题栏
- 修改Android默认背光值
- AndroidWidget 桌面小控件 ; 完成效果 : 桌面展示 : xx年 xx月 xx日 xx时 xx分 xx秒
- Android 6.0 (Marshmallow) 加载svg图片 报错
- android 代码设置、打开wifi热点及热点的连接
- Android 6.0 (Marshmallow) 加载svg图片 报错
- Gitlab上如何给指定人员在指定项目里设置指定权限,给项目设置保护
- Android Hybrid开发
- (2016.5.26更新8.0.1失效问题)Android Studio上使用Butterknife注解框架与插件Android Butterknife Zelezny
- ImageView.ScaleType /android:scaleType值的意义区别
- Android4.4关机菜单添加重启系列选项
- Android,与北岛的诗
- Android错误解决方法集锦
- Gitlabr如何设置邮件提醒?
- Android内存泄漏(3)
- [AndroidAnnotations框架]AndroidAnnotations的配置