Android - DEX - 文件格式详解

更新时间:2024-06-22 02:15:01 阅读量: 综合文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

DEX文件格式

0. 实验

$ vi test.java class test{

public static void main(String[] argc){ System.out.println(\ } }

$ javac test.java

$ dx --dex --output=test.dex test.class $ hexdump test.dex

0000000 6564 0a78 3330 0035 5eb4 4f7a 94e6 65f0 0000010 fb3e d5f3 e185 dd62 fce7 c887 a7ec 5329 0000020 02d8 0000 0070 0000 5678 1234 0000 0000 0000030 0000 0000 0238 0000 000e 0000 0070 0000 0000040 0007 0000 00a8 0000 0003 0000 00c4 0000 0000050 0001 0000 00e8 0000 0004 0000 00f0 0000 0000060 0001 0000 0110 0000 01a8 0000 0130 0000 0000070 0176 0000 017e 0000 0195 0000 01a9 0000 0000080 01bd 0000 01d1 0000 01d9 0000 01dc 0000 0000090 01e0 0000 01f5 0000 01fb 0000 0200 0000 00000a0 0209 0000 0210 0000 0001 0000 0002 0000 00000b0 0003 0000 0004 0000 0005 0000 0006 0000 00000c0 0008 0000 0006 0000 0005 0000 0000 0000 00000d0 0007 0000 0005 0000 0168 0000 0007 0000 00000e0 0005 0000 0170 0000 0003 0000 000a 0000 00000f0 0000 0001 000b 0000 0001 0000 0000 0000 0000100 0004 0000 0000 0000 0004 0002 0009 0000 0000110 0004 0000 0000 0000 0001 0000 0000 0000 0000120 000d 0000 0000 0000 0227 0000 0000 0000 0000130 0001 0001 0001 0000 021b 0000 0004 0000 0000140 1070 0001 0000 000e 0003 0001 0002 0000 0000150 0220 0000 0008 0000 0062 0000 011a 000c 0000160 206e 0000 0010 000e 0001 0000 0002 0000 0000170 0001 0000 0006 3c06 6e69 7469 003e 4c15 0000180 616a 6176 692f 2f6f 7250 6e69 5374 7274 0000190 6165 3b6d 1200 6a4c 7661 2f61 616c 676e 00001a0 4f2f 6a62 6365 3b74 1200 6a4c 7661 2f61 00001b0 616c 676e 532f 7274 6e69 3b67 1200 6a4c 00001c0 7661 2f61 616c 676e 532f 7379 6574 3b6d 00001d0 0600 744c 7365 3b74 0100 0056 5602 004c 00001e0 5b13 6a4c 7661 2f61 616c 676e 532f 7274 00001f0 6e69 3b67 0400 616d 6e69 0300 756f 0074 0000200 7007 6972 746e 6e6c 0500 6574 7473 0021

0000210 7409 7365 2e74 616a 6176 0100 0700 000e 0000220 0103 0700 780e 0000 0200 0200 8080 b004 0000230 0102 c809 0002 0000 000d 0000 0000 0000 0000240 0001 0000 0000 0000 0001 0000 000e 0000 0000250 0070 0000 0002 0000 0007 0000 00a8 0000 0000260 0003 0000 0003 0000 00c4 0000 0004 0000 0000270 0001 0000 00e8 0000 0005 0000 0004 0000 0000280 00f0 0000 0006 0000 0001 0000 0110 0000 0000290 2001 0000 0002 0000 0130 0000 1001 0000 00002a0 0002 0000 0168 0000 2002 0000 000e 0000 00002b0 0176 0000 2003 0000 0002 0000 021b 0000 00002c0 2000 0000 0001 0000 0227 0000 1000 0000 00002d0 0001 0000 0238 0000 00002d8

1. map_list

map_list数据结构为: Name Format Description size uint size of the list, in entries list map_item[size] elements of the list 第一项为map_list的大小,其中map_item的结构为: Name Format Description type ushort type of the items; see table below unused ushort (unused) count of the number of items to be found at the size uint indicated offset offset from the start of the file to the items in offset uint question

type的值如下表:

Item Type Constant Value header_item TYPE_HEADER_ITEM 0x0000 string_id_item TYPE_STRING_ID_ITEM 0x0001 type_id_item TYPE_TYPE_ID_ITEM 0x0002 proto_id_item TYPE_PROTO_ID_ITEM 0x0003 field_id_item TYPE_FIELD_ID_ITEM 0x0004 method_id_item TYPE_METHOD_ID_ITEM 0x0005 class_def_item TYPE_CLASS_DEF_ITEM 0x0006 map_list TYPE_MAP_LIST 0x1000 type_list TYPE_TYPE_LIST 0x1001 annotation_set_ref_list TYPE_ANNOTATION_SET_REF_LIST 0x1002 annotation_set_item TYPE_ANNOTATION_SET_ITEM 0x1003 class_data_item TYPE_CLASS_DATA_ITEM 0x2000 code_item TYPE_CODE_ITEM 0x2001 string_data_item TYPE_STRING_DATA_ITEM 0x2002 debug_info_item TYPE_DEBUG_INFO_ITEM 0x2003 Item Size In Bytes 0x70 0x04 0x04 0x0c 0x08 0x08 0x20 4 + (item.size * 12) 4 + (item.size * 2) 4 + (item.size * 4) 4 + (item.size * 4) implicit; must parse implicit; must parse implicit; must parse implicit; must parse annotation_item TYPE_ANNOTATION_ITEM 0x2004 implicit; must parse encoded_array_item TYPE_ENCODED_ARRAY_ITEM 0x2005 implicit; must parse annotations_directory_item TYPE_ANNOTATIONS_DIRECTORY_ITEM 0x2006 implicit; must parse

这个map_list有13个map_item,分别是: 值 type size offset 0x0000 header_item 0x1 0x0 0x0001 string_id_item 0xe 0x70 0x0002 type_id_item 0x7 0xa8 0x0003 proto_id_item 0x3 0xc4 0x0004 field_id_item 0x1 0xe8 0x0005 method_id_item 0x4 0xf0 0x0006 class_def_item 0x1 0x110 0x2001 code_item 0x2 0x130 0x1001 type_list 0x2 0x168 0x2002 string_data_item 0xe 0x176 0x2003 debug_info_item 0x2 0x21b 0x2000 class_data_item 0x1 0x227 0x1000 map_list 0x1 0x238 发现这个表中的size和offset和header_item中的值一致。

2. string_id_item

批注10得出string id列表的位置为0x70,批注9得出string id列表中string_id_item的数量为0xe。string id的结构为string_id_item: Name Format Description offset from the start of the file to the string data for this item. The offset should be to a location in the data section, and the data should be in the format specified by \for the offset. string_data_off uint string_data_off指向string的数据,string的数据的结构为string_data_item: Name Format Description size of this string, in UTF-16 code units (which is the \length%utf16_size uleb128 the string. (The encoded length is implied by the position of the 0 byte.)字符串的字节个数。 data

a series of MUTF-8 code units (a.k.a. octets, a.k.a. bytes) followed by a byte of value 0. See \Encoding\above for details and discussion about the data format. Note: It is acceptable to have a string which includes (the encoded

ubyte[] form of) UTF-16 surrogate code units (that is, U+d800 ? U+dfff)

either in isolation or out-of-order with respect to the usual encoding of Unicode into UTF-16. It is up to higher-level uses of strings to reject such invalid encodings, if appropriate. 字符串的实际数据。

LEB128

每个LEB128由1到5个字节组成,所有字节组合到一起代表一个32位值。除了最后一个字节的最高标志位为0,其它的为1.剩下的7位为有效负荷,第二个字节的7位接上。有符号LEB128的符号由最后字节的有效负荷最高位决定。如下:

如果是有符号的LEB128,符号位取决于bit13。如下举例: Encoded Sequence As sleb128 As uleb128 0 0 0 1 1 1 7f -1 127 80 7f -128 16256 uleb128p1的值加1为uleb128。 算法参见附录1。

As uleb128p1 -1 0 126 16255 从文件的0x70得出string id列表如下,共有14个string_id_item。 0176 0000 017e 0000 0195 0000 01a9 0000 01bd 0000 01d1 0000 01d9 0000 01dc 0000 01e0 0000 01f5 0000 01fb 0000 0200 0000 0209 0000 0210 0000 例如:

1)String Data在0x176处,可以从文件的0x176得到以下数据,以0结尾。 3c06 6e69 7469 003e

先读取第一个字节为0x06,得出String Data的长度为6,所以String Data的ASCII码序列为:3c 69 6e 69 74 3e 得到:

2)String Data在0x17e处,可以从文件的0x17e得到以下数据,以0结尾。 4c15 616a 6176 692f 2f6f 7250 6e69 5374 7274 6165 3b6d 1200

先读取第一个字节为0x15,得出String Data的长度为21,所以String Data的ASCII码序列为: 4c 6a 61 76 61 2f 69 6f 2f 50 72 69 6e 74 53 74 72 65 61 6d 3b 得到:Ljava/io/PrintStream;

以此类推,可得其它String Data。

3) 6a4c 7661 2f61 616c 676e 4f2f 6a62 6365 3b74 得到:Ljava/lang/Object; 4) 6a4c 7661 2f61 616c 676e 532f 7274 6e69 3b67 得到:Ljava/lang/String; 5) 6a4c 7661 2f61 616c 676e 532f 7379 6574 3b6d 得到:Ljava/lang/System; 6) 744c 7365 3b74 得到:Ltest; 7) 56 得到:V 8) 56 4c 得到:VL

9) 5b 6a4c 7661 2f61 616c 676e 532f 7274 6e69 3b67得到:[Ljava/lang/String; 10) 616d 6e69 得到:main 11) 756f 74 得到:out

12) 70 6972 746e 6e6c 得到:println 13) 6574 7473 21 得到:test!

14) 74 7365 2e74 616a 6176 得到:test.java 得出索引如下表: 3. type_id_item

批注12得出type id列表的位置为0xa8,批注11得出type id列表中type_id_item的数量为0x7。type id的结构为type_id_item: Name Format Description index into the string_ids list for the descriptor string of this descriptor_idx uint type. The string must conform to the syntax for TypeDescriptor, defined above. descriptor_idx为String id列表的索引。

索引为:0001 0000 0002 0000 0003 0000 0004 0000 0005 0000 0006 0000 0008 0000

依次代表:Ljava/io/PrintStream; Ljava/lang/Object; Ljava/lang/String; Ljava/lang/System; Ltest; V [Ljava/lang/String;

Type_id_list列表如下:

Ljava/io/PrintStream; 0 Ljava/lang/Object; 1 Ljava/lang/String; 2 Ljava/lang/System; 3 Ltest; 4 V 5 [Ljava/lang/String; 6

4. proto_id_item

批注14得出prototype id列表的位置为0xc4,批注13的处prototype id列表中proto_id_item的数量为0x3。prototype id的结构为proto_id_item:

Name Format Description index into the string_ids list for the short-form descriptor string of this prototype. The string must conform to the syntax for ShortyDescriptor, defined above, and must correspond to the return type and parameters of this item. shorty_idx uint

return_type_idx uint index into the type_ids list for the return type of this prototype offset from the start of the file to the list of parameter types for this prototype, or 0 if this prototype has no parameters. This offset, if non-zero, should be in the data section, and the data there should be in the format specified by \below. Additionally, there should be no reference to the type void in the list. parameters_off uint shorty_idx为String Id列表的索引,return_type_idx为Type Id列表的索引,parameters_off指向type_list。type_list结构如下: Name Format Description size uint size of the list, in entries list type_item[size] elements of the list type_item结构入下: Name Format Description type_idx ushort index into the type_ids list type_idx为type id列表的索引。

从文件的0xc4得到prototype id列表如下,共有3个proto_id_item。 1) 0006 0000 0005 0000 0000 0000

string_id_list[0x6]代表V,返回类型type_id_list[0x5]代表V,没有参数。 2) 0007 0000 0005 0000 0168 0000

string_id_list[0x7]代表VL,返回类型type_id_list[0x5]代表V,参数从0x168处的值为: 0001 0000 0002 一个参数,索引为0x2,type_id_list[0x2]代表Ljava/lang/String; 3) 0007 0000 0005 0000 0170 0000

string_id_list[0x7]代表VL,返回类型type_id_list[0x5]代表V,参数从0x170处的值为: 0001 0000 0006 一个参数,索引为0x6,type_id_list[0x6]代表[Ljava/lang/String; 注:字段和方法描述符参见附录2。

5. field_id_item

批注16得出field id列表的位置为0xe8,批注15的处field id列表中field_id_item的数量为0x1。Field id的结构为field_id_item: Name Format Description class_idx ushort type_idx name_idx index into the type_ids list for the definer of this field. This must be a class type, and not an array or primitive type. ushort index into the type_ids list for the type of this field uint index into the string_ids list for the name of this field. The string must conform to the syntax for MemberName, defined above. class_idx 为类的类型,即该字段所属的类。 type_idx 为此字段的类型。 name_idx 为此字段的名字。

从文件的0xe8得到filed id列表如下,共有1个field_id_item。

0003 0000 000a 0000

该字段所属的类为:Ljava/lang/System; 此字段的类型为:Ljava/io/PrintStream; 此字段的名字为:out

6. method_id_item

批注18得出method id列表的位置为0xf0,批注17的处method id列表中method_id_item的数量为0x4。Method id的结构为method_id_item: Name Format Description class_idx proto_idx name_idx ushort ushort uint index into the type_ids list for the definer of this method. This must be a class or array type, and not a primitive type. index into the proto_ids list for the prototype of this method index into the string_ids list for the name of this method. The string must conform to the syntax for MemberName, defined above. class_idx 为类的类型,即该方法所属的类。 proto_idx 此方法原型。 name_idx 此方法名字。

从文件的0xf0得到method id列表如下,共有4个method_id_item。

0000 0001 000b 0000 类:Ljava/io/PrintStream; 原型:VL 名字:println 0001 0000 0000 0000 类:Ljava/lang/Object; 原型:V 名字: 0004 0000 0000 0000 类:Ljava/lang/System; 原型:V 名字: 0004 0002 0009 0000 类:Ljava/lang/System; 原型:VL 名字: main

7. class_def_item

批注20得出class definitions列表的位置为0x110,批注19的处class definitions列表中 class_def__item的数量为0x1。class definitions的结构为class_def_item:

Name Format Description class_idx access_flags uint uint index into the type_ids list for this class. This must be a class type, and not an array or primitive type. access flags for the class (public, final, etc.). See \access_flags Definitions\index into the type_ids list for the superclass, or the constant value NO_INDEX if this class has no superclass (i.e., it is a root class such as Object). If present, this must be a class type, and not an array or primitive type. superclass_idx uint interfaces_off uint

source_file_idx uint

annotations_off uint

class_data_off uint

offset from the start of the file to the list of interfaces, or 0 if there are none. This offset should be in the data section, and the data there should be in the format specified by \Each of the elements of the list must be a class type (not an array or primitive type), and there must not be any duplicates.

接口列表的偏移,如果为0表示没有接口。此偏移量应该在数据段中,并且类型详细说明在\中。表中的每一个元素都必须是类类型(而不能是一个数组或基本类型),并且不能有任何重复。

index into the string_ids list for the name of the file containing the original source for (at least most of) this class, or the special value NO_INDEX to represent a lack of this information. The debug_info_item of any given method may override this source file, but the expectation is that most classes will only come from one source file.

类源码所在的文件的名称索引(至少大部分是这样的),此索引对应string_ids数组中的索引。或者是一个特殊值NO_INDEX表示缺少这种文件的信息。

offset from the start of the file to the annotations structure for this class, or 0 if there are no

annotations on this class. This offset, if non-zero, should be in the data section, and the data there should be in the format specified by

\annotations_directory_item\referring to this class as the definer.

注释结构的偏移,如果为0,则表示此类没有注解。如果不为零,应在数据段,该数据应在规定的“

annotations_directory_item”下面的格式,所有项目指的是这个类的定义者。

offset from the start of the file to the associated class data for this item, or 0 if there is no class data for this class. (This may be the case, for example, if this class is a marker interface.) The offset, if non-zero, should be in the data section, and the data there should be in the format specified by

\class_data_item\this class as the definer.

与此类相关的类数据的偏移,如果为0,这说明没有此类的类数据(例如:此类是一个标记接口)。如果不为零,应在数据段,该数据应在规定的“class_data_item”下面的格式,所有项目指的是这个类的定义者。

static_values_off uint

offset from the start of the file to the list of initial values for static fields, or 0 if there are none (and all static fields are to be initialized with 0 or null). This offset should be in the data section, and the data there should be in the format specified by

\encoded_array_item\below. The size of the array must be no larger than the number of static fields declared by this class, and the elements correspond to the static fields in the same order as declared in the

corresponding field_list. The type of each array element must match the declared type of its corresponding field. If there are fewer elements in the array than there are static fields, then the leftover fields are initialized with a type-appropriate 0 or null.

静态字段初始值的偏移,如果为0,则说明没有静态数据(所有的静态数据都初始化为0或null)。这个偏移位置在数据段中,数据保存在encoded_array_item的格式中。数组中元素的个数不能大于类中静态字段的个数,元素的排序对应field_list中的排序。每个数组元素的类型必须匹配与之对应的字段声明的类型。如果有比有静态字段的数组中的元素少,那么剩下的字段都被初始化一个适合不同类型的0或null。

0004 0000 0000 0000 0001 0000 0000 0000 000d 0000 0000 0000 0227 0000 0000 0000

class_idx 类的类型:Ltest; access_flags 访问权限:

superclass_idx 父类:Ljava/lang/Object; interfaces_off 没有接口

source_file_idx 文件名test.java annotations_off 没有注释

class_data_off 指向class_data_item,机构如下。 static_values_off 暂时无

class_data_item Name Format Description the number of static fields defined in static_fields_size uleb128 this item the number of instance fields defined instance_fields_size uleb128 in this item the number of direct methods defined direct_methods_size uleb128 in this item the number of virtual methods defined virtual_methods_size uleb128 in this item static_fields encoded_field[static_fields_size] the defined static fields, represented as a sequence of encoded elements. The fields must be sorted by field_idx in increasing order. the defined instance fields, encoded_field[instancrepresented as a sequence of encoded instance_fields e_fields_size] elements. The fields must be sorted by field_idx in increasing order. the defined direct (any of static, private, or constructor) methods, represented as a sequence of encoded elements. The methods must be sorted encoded_method[directdirect_methods by method_idx in increasing order. _methods_size] 所定义的直接方法(任何静态的,私有的,或构造函数),表示为一个序列编码的元素。该方法必须按method_idx的递增的顺序。 the defined virtual (none of static, private, or constructor) methods, represented as a sequence of encoded elements. This list should not include inherited methods unless overridden by the class that this item encoded_method[virtuavirtual_methods represents. The methods must be sorted l_methods_size] by method_idx in increasing order. 定义的虚拟方法(不是静态的,私有的,或构造函数),表示为一个序列编码的元素。该列表不应包括继承的方法,除非覆盖的类,这个项目代表。方法必须按method_idx的递增的顺序 文件的0x227处为class_data_item结构。从0x227处得来的字节序为: 00 00 02 00 02 80 80 04 b0 02 01 09 c8 02 00 00 00 static_fields_size 为0 instance_fields_size 为0 direct_methods_size 为2 virtual_methods_size 为0

因为前两个为0,所以下一个字节开始就是direct_methods,encoded_method和encoded_field机构如下,两个direct_method为: 1) 02 80 80 04 b0 02

method_idx_diff 为0x2

access_flags 为0x10000 (80 80 04) 代表constructor method code_off 为0x130 (b0 02) 指向 code_item 从0x130解析code_item:

registers_size(u2) 0x1 ins_size(u2) 0x1 outs_size(u2) 0x1 tries_size(u2) 0

debug_info_off(u4) 0x21b insns_size(u4) 0x4

insns ushort[insns_size] 1070 0001 0000 000e ? 0x70的opcode为:invoke-direct 其格式为:

invoke-direct {vD, vE, vF, vG, vA}, meth@CCCC B: argument word count (4 bits) C: method index (16 bits)

D..G, A: argument registers (4 bits each)

分布为:

B|A|op CCCC G|F|E|D [B=5] op {vD, vE, vF, vG, vA}, meth@CCCC

[B=5] op {vD, vE, vF, vG, vA}, type@CCCC [B=4] op {vD, vE, vF, vG}, kind@CCCC [B=3] op {vD, vE, vF}, kind@CCCC [B=2] op {vD, vE}, kind@CCCC [B=1] op {vD}, kind@CCCC [B=0] op {}, kind@CCCC

由于B=1,D=0,CCCC=0x0001,对应得method为Ljava/lang/Object;的,即构造方法。 ? 0x0e的opcode为return-void

经过上述分析,得到指令为:

|0000: invoke-direct {v0}, Ljava/lang/Object;.:()V // method@0001 |0003: return-void

2) 01 09 c8 02

method_idx_diff 为0x1 access_flags 为0x9 (0x8 and 0x1) 代表static and public code_off 为0x148 (c8 02) 指向 code_item 从0x148解析code_item:

registers_size(u2) 0x3 ins_size(u2) 0x1 outs_size(u2) 0x2 tries_size(u2) 0 debug_info_off(u4) 0x220 insns_size(u4) 0x8

insns ushort[insns_size] 0062 0000 011a 000c 206e 0000 0010 000e

? 0x62的opcode为sget-object 其格式为:

sget-object vAA, field@BBBB

A: value register or pair; may be source or dest (8 bits) B: static field reference index (16 bits) 分布为:

AA|op BBBB

由于AA=0,BBBB=0x0000,字段为out

? 0x1a的opcode为const-string 其格式为

const-string vAA, string@BBBB A: destination register (8 bits) B: string index 分布为:

AA|op BBBB

由于AA=1,BBBB=0x000c,对应的字符串为:test!

? 0x6e的opcode为:invoke-virtual 其格式和分布同invoke-direct:

B|A|op CCCC G|F|E|D [B=5] op {vD, vE, vF, vG, vA}, meth@CCCC

[B=5] op {vD, vE, vF, vG, vA}, type@CCCC [B=4] op {vD, vE, vF, vG}, kind@CCCC [B=3] op {vD, vE, vF}, kind@CCCC [B=2] op {vD, vE}, kind@CCCC [B=1] op {vD}, kind@CCCC [B=0] op {}, kind@CCCC

这里B=2,A=0,E=1,D=0,CCCC=0x0000,方法为Ljava/io/PrintStream;的println ? 0x0e的opcode为return-void

经过上述分析,得到指令为:

sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream; // field@0000 const-string v1, \

invoke-virtual {v0, v1}, Ljava/io/PrintStream;.println:(Ljava/lang/String;)V // method@0000 return-void

encoded_method

Name Format Description index into the method_ids list for the identity of this method (includes the name and descriptor), represented as a difference from the index of previous element in the list. The index of the first element in a list is represented directly. access flags for the method (public, final, etc.). See \access_flags Definitions\method_idx_diff uleb128 access_flags uleb128 code_off uleb128 offset from the start of the file to the code structure for this method, or 0 if this method is either abstract or native. The offset should be to a location in the data section. The format of the data is specified by \code_item\below. encoded_field Name Format Description index into the field_ids list for the identity of this field (includes the name and descriptor), represented as a difference from the index of previous element in the list. The index of the first element in a list is represented directly. field_idx_diff uleb128 access_flags code_item Name registers_size ins_size outs_size tries_size uleb128 access flags for the field (public, final, etc.). See \Format ushort ushort ushort ushort debug_info_off uint insns_size uint Description the number of registers used by this code the number of words of incoming arguments to the method that this code is for the number of words of outgoing argument space required by this code for method invocation the number of try_items for this instance. If non-zero, then these appear as the tries array just after the insns in this instance. offset from the start of the file to the debug info (line numbers + local variable info) sequence for this code, or 0 if there simply is no information. The offset, if non-zero, should be to a location in the data section. The format of the data is specified by \below. size of the instructions list, in 16-bit code units actual array of bytecode. The format of code in an insns array is specified by the companion document \Bytecode for the Dalvik VM\that though this is defined as an array of ushort, there are some internal structures that prefer four-byte alignment. Also, if this happens to be in an endian-swapped file, then the swapping is only done on individual ushorts and not on the larger internal structures. insns ushort[insns_size] padding tries handlers two bytes of padding to make tries four-byte ushort (optional) = aligned. This element is only present if 0 tries_size is non-zero and insns_size is odd. array indicating where in the code exceptions may be caught and how to handle them. Elements try_item[tries_sizeof the array must be non-overlapping in range ] (optional) and in order from low to high address. This element is only present if tries_size is non-zero. bytes representing a list of lists of catch types and associated handler addresses. Each encoded_catch_handltry_item has a byte-wise offset into this er_list (optional) structure. This element is only present if tries_size is non-zero.

附录1 LEB128算法 算法如下:

DEX_INLINE int readUnsignedLeb128(const u1** pStream) { const u1* ptr = *pStream; int result = *(ptr++);

if (result > 0x7f) { //如果第一个字节的最高位是1 int cur = *(ptr++); //指向第二个字节

//当前值是第一个字节的7位加上第二个字节的7位

result = (result & 0x7f) | ((cur & 0x7f) << 7);

if (cur > 0x7f) { //如果第二个字节的最高位是1 cur = *(ptr++); //指向第三个字节

result |= (cur & 0x7f) << 14;//当前值加上第三个字节的7位 if (cur > 0x7f) {//如果第三个字节的最高位是1 cur = *(ptr++);

result |= (cur & 0x7f) << 21;//当前值加上第四个字节的7位 if (cur > 0x7f) {//如果第四个字节的最高位是1 /*

* Note: We don't check to see if cur is out of * range here, meaning we tolerate garbage in the * high four-order bits. */

cur = *(ptr++);

result |= cur << 28;//当前值加上第五个字节的7位 } } } }

*pStream = ptr; return result; } /*

* 读取有符号的,符号位取决于最后字节的有效负荷最高位。>>是到符号的。 */

DEX_INLINE int readSignedLeb128(const u1** pStream) { const u1* ptr = *pStream; int result = *(ptr++);

if (result <= 0x7f) {

result = (result << 25) >> 25; } else {

int cur = *(ptr++);

result = (result & 0x7f) | ((cur & 0x7f) << 7); if (cur <= 0x7f) {

result = (result << 18) >> 18; } else {

cur = *(ptr++);

result |= (cur & 0x7f) << 14; if (cur <= 0x7f) {

result = (result << 11) >> 11; } else {

cur = *(ptr++);

result |= (cur & 0x7f) << 21; if (cur <= 0x7f) {

result = (result << 4) >> 4; } else { /*

* Note: We don't check to see if cur is out of * range here, meaning we tolerate garbage in the * high four-order bits. */

cur = *(ptr++);

result |= cur << 28; } } } }

*pStream = ptr; return result; }

附录2 字段和方法描述符 (1) Field Descriptors

The field descriptors for eight primitive types are as follows:

引用类型使用L开头,如下:

(2) Method Descriptors

方法描述符形式为括号内所有参数类型的描述符,后加上返回类型的字段描述符。V表示void方法返回类型,构造函数的返回类型也为V,名字为。例如:

(3) ShortyDescriptor A ShortyDescriptor is the short form representation of a method prototype, including return and parameter types, except that there is no distinction between various reference(class or array)types. Instead, all reference types are represented by a single 'L' character.

ShortyDescriptor Java Language Type String f(); L long f(int i, Class c); JIL String(byte[] bytes); VL

本文来源:https://www.bwwdw.com/article/2vh3.html

Top