Android开发经验谈Android开发Android技术知识

Android Dex文件

2018-02-10  本文已影响739人  lbtrace

.dex(Dalvik Executable Format)文件用于保存类定义及其关联的辅助数据

文件格式

header文件头

数据结构

  // Raw header_item.
  struct Header {
    uint8_t magic_[8];
    uint32_t checksum_;  // See also location_checksum_
    uint8_t signature_[kSha1DigestSize];
    uint32_t file_size_;  // size of entire file
    uint32_t header_size_;  // offset to start of next section
    uint32_t endian_tag_;
    uint32_t link_size_;  // unused
    uint32_t link_off_;  // unused
    uint32_t map_off_;  // unused
    uint32_t string_ids_size_;  // number of StringIds
    uint32_t string_ids_off_;  // file offset of StringIds array
    uint32_t type_ids_size_;  // number of TypeIds, we don't support more than 65535
    uint32_t type_ids_off_;  // file offset of TypeIds array
    uint32_t proto_ids_size_;  // number of ProtoIds, we don't support more than 65535
    uint32_t proto_ids_off_;  // file offset of ProtoIds array
    uint32_t field_ids_size_;  // number of FieldIds
    uint32_t field_ids_off_;  // file offset of FieldIds array
    uint32_t method_ids_size_;  // number of MethodIds
    uint32_t method_ids_off_;  // file offset of MethodIds array
    uint32_t class_defs_size_;  // number of ClassDefs
    uint32_t class_defs_off_;  // file offset of ClassDef array
    uint32_t data_size_;  // unused
    uint32_t data_off_;  // unused
    ......
  }

例子

DEX file header:
magic               : 'dex\n035\0'
checksum            : 1181417f
signature           : a022...4f7a
file_size           : 2727984
header_size         : 112
link_size           : 0
link_off            : 0 (0x000000)
string_ids_size     : 19080
string_ids_off      : 112 (0x000070)
type_ids_size       : 2332
type_ids_off        : 76432 (0x012a90)
proto_ids_size       : 3091
proto_ids_off        : 85760 (0x014f00)
field_ids_size      : 8477
field_ids_off       : 122852 (0x01dfe4)
method_ids_size     : 17750
method_ids_off      : 190668 (0x02e8cc)
class_defs_size     : 1681
class_defs_off      : 332668 (0x05137c)
data_size           : 2325048
data_off            : 402936 (0x0625f8) ===> 类定义列表与data段有间隙

string_ids字符串列表

文件使用的所有字符串的标识符,用于内部命名(例如类型描述符)或用作代码引用的常量对象。此列表必须使用 UTF-16 代码点值按字符串内容进行排序,且不得包含任何重复条目。

元素数据结构

  // Raw string_id_item.
  struct StringId {
    uint32_t string_data_off_;  // offset in bytes from the base address

   private:
    DISALLOW_COPY_AND_ASSIGN(StringId);
  };

例子

......
00000070  08 5d 18 00 0a 5d 18 00  0d 5d 18 00 22 5d 18 00  |.]...]...].."]..|
00000080  38 5d 18 00 3b 5d 18 00  3f 5d 18 00 44 5d 18 00  |8]..;]..?]..D]..|
......
string_ids => 0x70
第一个StringId(string_id_item)的string_data_off_为0x00185d08
第二个StringId(string_id_item)的string_data_off_为0x00185d0a
第三个StringId(string_id_item)的string_data_off_为0x00185d0d
第四个StringId(string_id_item)的string_data_off_为0x00185d22
......

data段的字符串信息:
00185d00  00 00 00 00 00 00 00 00  00 00 01 0a 00 13 0a 20  |............... |
00185d10  20 43 6c 69 65 6e 74 20  76 65 72 73 69 6f 6e 3a  | Client version:|
00185d20  20 00 14 0a 20 20 53 65  72 76 69 63 65 20 76 65  | ...  Service ve|

第一个字符串二进制: 00 00
第二个字符串二进制: 01 0a 00
第三个字符串二进制: 13 0a 20 20 43 6c 69 65 6e 74 20  76 65 72 73 69 6f 6e 3a 20 00

type_ids类型列表

类型标识符列表,包含文件引用的所有类型(类、数组或原始类型)的标识符,此列表必须按 string_id 索引进行排序,且不得包含任何重复条目。

元素数据结构

  // Raw type_id_item.
  struct TypeId {
    uint32_t descriptor_idx_;  // index into string_ids

   private:
    DISALLOW_COPY_AND_ASSIGN(TypeId);
  };

例子

type_ids位置:
00012a90  a5 04 00 00 9d 05 00 00  0b 07 00 00 6c 08 00 00  |............l...|
00012aa0  72 09 00 00 21 0a 00 00  06 0b 00 00 07 0b 00 00  |r...!...........|

第一个类描述符在string_ids列表中的索引: 0x000004a5 (位置: 0x70 + 0x4a5 * 4 = 0x1304)

对应的string_ids列表内容:
00001300  65 63 19 00 7a 63 19 00  7d 63 19 00 81 63 19 00  |ec..zc..}c...c..|

(0x0019637a)对应的data段的字符串信息:
00196370  65 44 65 6c 65 67 61 74  65 00 01 42 00 02 42 3a  |eDelegate..B..B:|
对应的类型为B(基本类型byte)

proto_ids方法原型列表

方法原型标识符列表,包含文件引用的所有原型的标识符

元素数据结构

  // Raw proto_id_item.
  struct ProtoId {
    uint32_t shorty_idx_;  // index into string_ids array for shorty descriptor
    uint16_t return_type_idx_;  // index into type_ids array for return type
    uint16_t pad_;             // padding = 0
    uint32_t parameters_off_;  // file offset to type_list for parameter types

   private:
    DISALLOW_COPY_AND_ASSIGN(ProtoId);
  };

field_ids字段列表

元素数据结构

  // Raw field_id_item.
  struct FieldId {
    uint16_t class_idx_;  // index into type_ids_ array for defining class
    uint16_t type_idx_;  // index into type_ids_ array for field type
    uint32_t name_idx_;  // index into string_ids_ array for field name

   private:
    DISALLOW_COPY_AND_ASSIGN(FieldId);
  };

method_ids方法列表

元素数据结构

  // Raw method_id_item.
  struct MethodId {
    uint16_t class_idx_;  // index into type_ids_ array for defining class
    uint16_t proto_idx_;  // index into proto_ids_ array for method prototype
    uint32_t name_idx_;  // index into string_ids_ array for method name

   private:
    DISALLOW_COPY_AND_ASSIGN(MethodId);
  };

class_defs类定义列表

元素数据结构

  // Raw class_def_item.
  struct ClassDef {
    uint16_t class_idx_;  // index into type_ids_ array for this class
    uint16_t pad1_;  // padding = 0
    uint32_t access_flags_;
    uint16_t superclass_idx_;  // index into type_ids_ array for superclass
    uint16_t pad2_;  // padding = 0
    uint32_t interfaces_off_;  // file offset to TypeList
    uint32_t source_file_idx_;  // index into string_ids_ for source file name
    uint32_t annotations_off_;  // file offset to annotations_directory_item
    uint32_t class_data_off_;  // file offset to class_data_item
    uint32_t static_values_off_;  // file offset to EncodedArray
    ......
  }

例子

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Example of a call to a native method
        final TextView tv = (TextView) findViewById(R.id.sample_text);
        tv.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                tv.setText(stringFromJNI());
                
            }
        });
        testClassLoader();

    }

    private void testClassLoader() {
        try {
            ClassLoader cl = getClassLoader();

            if (cl == null)
                Log.i("wlb", "classload null");

            while (cl != null) {
                Log.i("wlb", cl.toString());
                cl = cl.getParent();
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * A native method that is implemented by the 'native-lib' native library,
     * which is packaged with this application.
     */
    public native String stringFromJNI();

    // Used to load the 'native-lib' library on application startup.
    static {
        System.loadLibrary("native-lib");
    }
}

MainActivity为例说明

MainActivity的class_def_item

class_defs_off      : 332668 (0x05137c)
MainActivity在class_ids中的索引:1665
MainActivity的class_def_item偏移:0x05137c + 1665 * 32 = 0x05E39C
==============================================================================
0005e390  50 10 29 00 78 65 08 00  00 00 00 00 36 08 00 00  |P.).xe......6...|
0005e3a0  01 00 00 00 2b 06 00 00  00 00 00 00 9f 15 00 00  |....+...........|
0005e3b0  00 00 00 00 92 65 08 00  00 00 00 00 1e 02 00 00  |.....e..........|
==============================================================================
类在type_ids中的索引:0x0836 (0x1be74d 'Lcom/tracemaker/nativedynamiclinkdemo/MainActivity;')
类的访问标志: 0x00000001
超类在type_ids中的索引: 0x062b
文件(包含该类)名称在string_ids列表中的索引: 0x0000159f (0x001c25fe 'MainActivity.java')
类数据在文件中的偏移量: 0x00086592

MainActivity的class_data

MainActivitytestClassLoader方法

testClassLoader对应的encoded_method十六进制数据06 02 8c 9a 55

testClassLoader方法的代码数据

154d0c:                                        |[154d0c] com.tracemaker.nativedynamiclinkdemo.MainActivity.testClassLoader:()V
154d1c: 6e10 9a43 0400                         |0000: invoke-virtual {v4}, Lcom/tracemaker/nativedynamiclinkdemo/MainActivity;.getClassLoader:()Ljava/lang/ClassLoader; // method@439a
154d22: 0c00                                   |0003: move-result-object v0
154d24: 3900 0b00                              |0004: if-nez v0, 000f // +000b
154d28: 1b02 244a 0000                         |0006: const-string/jumbo v2, "wlb" // string@00004a24
154d2e: 1b03 e522 0000                         |0009: const-string/jumbo v3, "classload null" // string@000022e5
154d34: 7120 113e 3200                         |000c: invoke-static {v2, v3}, Landroid/util/Log;.i:(Ljava/lang/String;Ljava/lang/String;)I // method@3e11
154d3a: 3800 1500                              |000f: if-eqz v0, 0024 // +0015
154d3e: 1b02 244a 0000                         |0011: const-string/jumbo v2, "wlb" // string@00004a24
154d44: 6e10 4044 0000                         |0014: invoke-virtual {v0}, Ljava/lang/Object;.toString:()Ljava/lang/String; // method@4440
154d4a: 0c03                                   |0017: move-result-object v3
154d4c: 7120 113e 3200                         |0018: invoke-static {v2, v3}, Landroid/util/Log;.i:(Ljava/lang/String;Ljava/lang/String;)I // method@3e11
154d52: 6e10 0444 0000                         |001b: invoke-virtual {v0}, Ljava/lang/ClassLoader;.getParent:()Ljava/lang/ClassLoader; // method@4404
154d58: 0c00                                   |001e: move-result-object v0
154d5a: 28f0                                   |001f: goto 000f // -0010
154d5c: 0d01                                   |0020: move-exception v1
154d5e: 6e10 0844 0100                         |0021: invoke-virtual {v1}, Ljava/lang/Exception;.printStackTrace:()V // method@4408
154d64: 0e00                                   |0024: return-void

testClassLoader方法try_item

异常类型字符串:
001bf410  15 4c 6a 61 76 61 2f 6c  61 6e 67 2f 45 78 63 65  |.Ljava/lang/Exce|
001bf420  70 74 69 6f 6e 3b 00 11  4c 6a 61 76 61 2f 6c 61  |ption;..Ljava/la|

附录OAT文件格式

参考

  1. https://source.android.com/devices/tech/dalvik/dex-format?hl=zh-cn
  2. Hiding Behind ART
上一篇 下一篇

猜你喜欢

热点阅读