|
430| 2
|
[Android 原创] Dex结构 |
发表于 2026-1-21 19:58
值格式:
4. encoded_array格式
5. encoded_annotation格式
6. annotation_element格式
上面这些就是用到的比较重要的数据类型和数据结构了。 二、Dex整体结构 dex的整体结构分为三个部分:dex文件头,索引结构区,data数据区,示意图如下:
1 保存了dex的文件基本信息,例如文件大小,头大小,大小端序,索引表的起始地址和偏移等等 2. 索引结构区 这部分保存了字符串表,类型表,方法原型表,域表,方法表等结构。这些结构当中存放的是对应数据的
可以访问到对应的数据。 3. data数据区 所有的代码和数据存放在该地方。 tips 有关dex的结构体信息可以通过libdexfile/dex/dex_file.h - platform/art - Git at Google源代码进行了解。 三、文件头--DexHeader
四、Dex索引区1.
|
| 名称 | 值 | 对于类(和 InnerClass 注释) |
对于字段 | 对于方法 |
|---|---|---|---|---|
ACC_PUBLIC |
0x1 | public |
public |
public |
ACC_PRIVATE |
0x2 | private |
private |
private |
ACC_PROTECTED |
0x4 | protected |
protected |
protected |
ACC_STATIC |
0x8 | static |
static |
static |
ACC_FINAL |
0x10 | final:不可子类化 |
final:构建后不可变 |
final:不可替换 |
ACC_SYNCHRONIZED |
0x20 | synchronized:调用此方法时自动获得关联锁定。注意:这一项仅在同时设置 ACC_NATIVE 的情况下才有效。 |
||
ACC_VOLATILE |
0x40 | volatile:有助于确保线程安全的特殊访问规则 |
||
ACC_BRIDGE |
0x40 | 桥接方法,由编译器自动添加为类型安全桥 | ||
ACC_TRANSIENT |
0x80 | transient:不会通过默认序列化保存 |
||
ACC_VARARGS |
0x80 | 最后一个参数应被编译器解译为“rest”参数 | ||
ACC_NATIVE |
0x100 | native:在原生代码中实现 |
||
ACC_INTERFACE |
0x200 | interface:可多倍实现的抽象类 |
||
ACC_ABSTRACT |
0x400 | abstract:不可直接实例化 |
abstract:不通过此类实现 |
|
ACC_STRICT |
0x800 | strictfp:严格的浮点运算规则 |
||
ACC_SYNTHETIC |
0x1000 | 不在源代码中直接定义 | 不在源代码中直接定义 | 不在源代码中直接定义 |
ACC_ANNOTATION |
0x2000 | 声明为注解类 | ||
ACC_ENUM |
0x4000 | 声明为枚举类型 | 声明为枚举值 | |
| (未使用) | 0x8000 | |||
ACC_CONSTRUCTOR |
0x10000 | 构造函数方法(类或实例初始化程序) | ||
ACC_DECLARED_SYNCHRONIZED |
0x20000 | 声明了 synchronized。 |
我在这里进行类型解析的时候使用了一个比较笨的方法,但是比较有效:
void Utils::printAccessFlags(u4 flags)
{
for (u4 mask = 1; mask < 0x80000000; mask <<= 1)
{
AccessFlags flag = (AccessFlags)(flags & mask);
if (flag != 0)
printf("%s ", accessflags[flag].c_str());
}
}
annotations_off注解信息 annotations_off是dex中注解目录的偏移量。首先来简单了解一下注解是什么:
@Deprecated // 1. 类注解 (Class Annotation)
public class SimpleDemo {
@Deprecated // 2. 字段注解 (Field Annotation)
public int myField;
@Deprecated // 3. 方法注解 (Method Annotation)
public void myMethod(@Deprecated int myParam) {} // 4. 参数注解 (Parameter Annotation)
}
annotations是一个好几层的结构,下面一些用到的结构:
DexAnnotationsDirectoryItem struct DexAnnotationsDirectoryItem {
u4 classAnnotationsOff; // DexAnnotationSetItem 偏移
u4 fieldsSize; // DexFieldAnnotationsItem 的数量
u4 methodsSize; // DexMethodAnnotationsItem 的数量
u4 parametersSize; // DexParameterAnnotationsItem 的数量
/* followed by DexFieldAnnotationsItem[fieldsSize] */
/* followed by DexMethodAnnotationsItem[methodsSize] */
/* followed by DexParameterAnnotationsItem[parametersSize] */
};
这个是注解的目录信息,分别是
DexAnnotationSetItem结构DexFieldAnnotationsItem项的数量DexMethodAnnotationsItem项的数量DexParameterAnnotationsItem项的数量 如果fieldsSize,methodsSize,parametersSize这三个成员不为0的话,在该结构中会多出对应的数组DexFieldAnnotationsItem[fieldsSize],DexMethodAnnotationsItem[methodsSize],DexParameterAnnotationsItem[parametersSize]。
DexAnnotationSetItemstruct DexAnnotationSetItem {
u4 size;
u4 entries[1]; // DexAnnotationItem 的偏移
};
size指出了entries有多少项。
DexAnnotationItemstruct DexAnnotationItem {
u1 visibility;
u1 annotation[1]; /* data in encoded_annotation format */
};
visibility的值在官方文档当中的定义如下:
| 名称 | 值 | 说明 |
|---|---|---|
VISIBILITY_BUILD |
0x00 | 预计仅在构建(例如,在编译其他代码期间)时可见 |
VISIBILITY_RUNTIME |
0x01 | 预计在运行时可见 |
VISIBILITY_SYSTEM |
0x02 | 预计在运行时可见,但仅对基本系统(而不是常规用户代码)可见 |
annotation是encoded_annotation的开头,也就是说encoded_annotation是连在visibility后面的,
encoded_annotation结构如下:
struct encoded_annotation{
uleb128 type_idx; // typeIds索引
uleb128 size; // elements 的长度
annotation_element elements[1]; // 后续紧接annotation_element结构
};
elements指向的是annotation_element结构:
struct annotation_element{
uleb128 name_idx; // stringIds索引
encoded_value value; // encoded_value值
};
注意:这里的三个结构其实是紧紧连接到一起的,解析的时候需要动态解析
要解析类注解,就需要熟悉上面的结构体,整理这些结构之后的关系图解如下:
DexFieldAnnotationsItem 该结构的作用是:记录哪个字段,带有什么注解。
struct DexFieldAnnotationsItem {
u4 fieldIdx;
u4 annotationsOff; // DexAnnotationSetItem偏移
};
DexMethodAnnotationsItem 该结构的作用是:记录某个方法,带有什么注解
struct DexMethodAnnotationsItem {
u4 methodIdx;
u4 annotationsOff; // DexAnnotationSetItem偏移
};
对于字段注解、方法注解的解析方式都是大差不差的,结构层次如下图:
DexParameterAnnotationsItem 该结构的作用是:记录参数的所属的方法,以及各个参数的注释
struct DexParameterAnnotationsItem {
u4 methodIdx;
u4 annotationsOff; // DexAnotationSetRefList的偏移
};
DexAnotationSetRefListstruct DexAnnotationSetRefList {
u4 size;
DexAnnotationSetRefItem list[1];
};
struct DexAnnotationSetRefItem {
u4 annotationsOff; // DexAnnotationSetItem的偏移
};
由于一个方法可能包含多个参数,即包含多个参数注解。所以参数注解的解析稍微有些不同,首先先通过DexAnotationSetRefList找到该方法的所有参数注解。接着在通过DexAnnotationSetItem获取详细的参数注解信息。
结构层次如下图:
可见这个参数注解信息还是比较复杂的。不过一般情况下也遇不到
class_data_off字段 这个字段指向的是class_data_item的结构,这个结构存储了这个类真正拥有的所有变量(字段),方法信息。
接下来了解一下与这个结构有关的一些结构:
DexClassDatastruct DexClassData {
DexClassDataHeader header; // 指定字段与方法的个数
DexField* staticFields; // static字段
DexField* instanceFields; // 实例字段
DexMethod* directMethods; // 直接方法
DexMethod* virtualMethods; // 虚方法,虚函数
};
struct DexClassDataHeader {
u4 staticFieldsSize; // static字段个数
u4 instanceFieldsSize; // 实例字段个数
u4 directMethodsSize; // 直接方法个数
u4 virtualMethodsSize; // 虚方法个数
};
class_data_off指向的就是DexClassData这个结构。该结构中的header存储着该类所拥有的字段个数与方法个数。而且只有当这些size不为,对应的DexField或者DexMethod指针才不为0。
DexFieldstruct DexField {
u4 fieldIdx; // fieldIds_idx
u4 accessFlags; // 访问标志
};
该结构存放着字段在fieldIds的索引值,以及字段的属性,通过该结构可以找出一个完整的字段,如下图所示:
DexMethodstruct DexMethod {
u4 methodIdx; // methodIds 索引
u4 accessFlags;
u4 codeOff; // code_item 偏移量
};
该结构存放的是methodIds的索引值,以及方法的属性,还有方法的Code所在位置,Code结构体如下:
DexCodestruct DexCode {
u2 registersSize; // 使用寄存器个数
u2 insSize; // 参数个数
u2 outsSize; // 调用其他方法时使用的寄存器个数
u2 triesSize; // try/catch语句的个数
u4 debugInfoOff; // 调试信息偏移量 dexDecodeDebugInfo
u4 insnsSize; // 指令集个数,两个字节为单位
u2 insns[1]; // 指令集
/* optional u2 padding */
/* try_item[triesSize] (DexTry结构)*/
/* uleb128 handlersSize (try/catch语句中handler个数)*/
/* catch_handler_item[handlersSize] (DexCatchHandler结构)*/
};
通过这个Code结构可以获取到该方法所使用的寄存器个数,参数个数,调用其他方法使用的寄存器个数,以及指令集。这里的指令集可以被反汇编成smali代码。
classData结构层次如下:
至此这里已经把Dex的大部分结构分析完了
发帖前要善用【论坛搜索】功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。
|
发表于 2026-1-23 17:51
| ||
RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )
GMT+8, 2026-1-24 04:48
Powered by Discuz!
Copyright © 2001-2020, Tencent Cloud.