Android[art]-Android dex,odex,oat,vdex,art文件結(jié)構(gòu)學(xué)習(xí)總結(jié)

參考學(xué)習(xí)博客:

Android Dex文件格式(一):https://blog.csdn.net/p312011150/article/details/80501690
dex文件解析(第三篇) :https://blog.csdn.net/tabactivity/article/details/78950379
Android安全–Dex文件格式詳解:https://www.cnblogs.com/kexing/p/8890162.html
Dalvik和Art,JIT ,AOT, oat, dex, odex:https://www.colabug.com/4516410.html
官方文檔:https://source.android.com/devices/tech/dalvik/dex-format

一. Android Dex文件整體結(jié)構(gòu):

當(dāng)java程序編譯成class后,還需要使用dx工具將所有的class文件整合到一個(gè)dex文件,目的是其中各個(gè)類(lèi)能夠共享數(shù)據(jù),在一定程度上降低了冗余,同時(shí)也是文件結(jié)構(gòu)更加經(jīng)湊,實(shí)驗(yàn)表明,dex文件是傳統(tǒng)jar文件大小的50%左右。

1.整體結(jié)構(gòu):

在這里插入圖片描述

2.詳細(xì)描述:

名稱 格式 說(shuō)明
header header_item 標(biāo)頭
string_ids string_id_item[] 字符串標(biāo)識(shí)符列表。這些是此文件使用的所有字符串的標(biāo)識(shí)符,用于內(nèi)部命名(例如類(lèi)型描述符)或用作代碼引用的常量對(duì)象。此列表必須使用 UTF-16 代碼點(diǎn)值按字符串內(nèi)容進(jìn)行排序(不采用語(yǔ)言區(qū)域敏感方式),且不得包含任何重復(fù)條目。
type_ids type_id_item[] 類(lèi)型標(biāo)識(shí)符列表。這些是此文件引用的所有類(lèi)型(類(lèi)、數(shù)組或原始類(lèi)型)的標(biāo)識(shí)符(無(wú)論文件中是否已定義)。此列表必須按 string_id 索引進(jìn)行排序,且不得包含任何重復(fù)條目。
proto_ids proto_id_item[] 方法原型標(biāo)識(shí)符列表。這些是此文件引用的所有原型的標(biāo)識(shí)符。此列表必須按返回類(lèi)型(按 type_id 索引排序)主要順序進(jìn)行排序,然后按參數(shù)列表(按 type_id 索引排序的各個(gè)參數(shù),采用字典排序方法)進(jìn)行排序。該列表不得包含任何重復(fù)條目。
field_ids field_id_item[] 字段標(biāo)識(shí)符列表。這些是此文件引用的所有字段的標(biāo)識(shí)符(無(wú)論文件中是否已定義)。此列表必須進(jìn)行排序,其中定義類(lèi)型(按 type_id 索引排序)是主要順序,字段名稱(按 string_id 索引排序)是中間順序,而類(lèi)型(按 type_id 索引排序)是次要順序。該列表不得包含任何重復(fù)條目。
method_ids method_id_item[] 方法標(biāo)識(shí)符列表。這些是此文件引用的所有方法的標(biāo)識(shí)符(無(wú)論文件中是否已定義)。此列表必須進(jìn)行排序,其中定義類(lèi)型(按 type_id 索引排序)是主要順序,方法名稱(按 string_id 索引排序)是中間順序,而方法原型(按 proto_id 索引排序)是次要順序。該列表不得包含任何重復(fù)條目。
class_defs class_def_item[] 類(lèi)定義列表。這些類(lèi)必須進(jìn)行排序,以便所指定類(lèi)的超類(lèi)和已實(shí)現(xiàn)的接口比引用類(lèi)更早出現(xiàn)在該列表中。此外,對(duì)于在該列表中多次出現(xiàn)的同名類(lèi),其定義是無(wú)效的。
call_site_ids call_site_id_item[] 調(diào)用站點(diǎn)標(biāo)識(shí)符列表。這些是此文件引用的所有調(diào)用站點(diǎn)的標(biāo)識(shí)符(無(wú)論文件中是否已定義)。此列表必須按 call_site_off 的升序進(jìn)行排序。
method_handles method_handle_item[] 方法句柄列表。此文件引用的所有方法句柄的列表(無(wú)論文件中是否已定義)。此列表未進(jìn)行排序,而且可能包含將在邏輯上對(duì)應(yīng)于不同方法句柄實(shí)例的重復(fù)項(xiàng)。
data ubyte[] 數(shù)據(jù)區(qū),包含上面所列表格的所有支持?jǐn)?shù)據(jù)。不同的項(xiàng)有不同的對(duì)齊要求;如有必要,則在每個(gè)項(xiàng)之前插入填充字節(jié),以實(shí)現(xiàn)所需的對(duì)齊效果。
link_data ubyte[] 靜態(tài)鏈接文件中使用的數(shù)據(jù)。本文檔尚未指定本區(qū)段中數(shù)據(jù)的格式。此區(qū)段在未鏈接文件中為空,而運(yùn)行時(shí)實(shí)現(xiàn)可能會(huì)在適當(dāng)?shù)那闆r下使用這些數(shù)據(jù)。

3. 采用010editor查看dex1文件:

在這里插入圖片描述

具體可以參考https://source.android.com/devices/tech/dalvik/dex-format,查看每項(xiàng)的定義即情況
也可以查看dex相關(guān)的code進(jìn)行結(jié)構(gòu)的梳理:
https://android.googlesource.com/platform/dalvik/+/master/dx/src/com/android/dx/dex/file/DexFile.java
/art/libdexfile/

總之來(lái)說(shuō),dex是將apk中使用到的class文件信息集合在一起的文件,其中也包含了很多jar包中的類(lèi)。
dex文件是對(duì)class文件中的各種函數(shù)表、變量表等進(jìn)行優(yōu)化過(guò)的,整體大小要小于class文件總和。

二. Android Odex,Oat,Vdex , art文件

2.1 odex文件概述( 5.0之前 )

全名Optimized DEX,即優(yōu)化過(guò)的DEX。
Apk在安裝(installer)時(shí),就會(huì)進(jìn)行驗(yàn)證和優(yōu)化,目的是為了校驗(yàn)代碼合法性及優(yōu)化代碼執(zhí)行速度,驗(yàn)證和優(yōu)化后,會(huì)產(chǎn)生ODEX文件,運(yùn)行Apk的時(shí)候,直接加載ODEX,避免重復(fù)驗(yàn)證和優(yōu)化,加快了Apk的響應(yīng)時(shí)間。

注意:優(yōu)化過(guò)程會(huì)根據(jù)不同設(shè)備上Dalvik虛擬機(jī)的版本、Framework庫(kù)的不同等因素而不同。在一臺(tái)設(shè)備上被優(yōu)化過(guò)的ODEX文件,拷貝到另一臺(tái)設(shè)備上不一定能夠運(yùn)行。

ODEX格式及生成過(guò)程:http://www.itdecent.cn/p/242abfb7eb7f

整體結(jié)構(gòu)盜圖如下:

在這里插入圖片描述

2.2. oat文件(5.0及5.0之后)

參考博客:
Android運(yùn)行時(shí)ART加載OAT文件的過(guò)程分析:https://blog.csdn.net/luoshengyang/article/details/39307813
oat格式(1):https://shaomi.github.io/2017/08/18/oat%E6%A0%BC%E5%BC%8F/
從Android運(yùn)行時(shí)出發(fā),打造我們的脫殼神器:
https://www.feiworks.com/wy/drops_html/%E4%BB%8EAndroid%E8%BF%90%E8%A1%8C%E6%97%B6%E5%87%BA%E5%8F%91%EF%BC%8C%E6%89%93%E9%80%A0%E6%88%91%E4%BB%AC%E7%9A%84%E8%84%B1%E5%A3%B3%E7%A5%9E%E5%99%A8.html

2.2.1 oat文件概述

oat 文件是 ART 運(yùn)行的文件,是一種ELF格式的二進(jìn)制可運(yùn)行文件,包含 DEX 文件和編譯出的本地機(jī)器指令文件。因?yàn)?oat 文件包含 DEX 文件,因此比 ODEX 文件占用空間更大。

由于其在安裝時(shí)打包在里面的classes.dex文件會(huì)被工具dex2oat翻譯成本地機(jī)器指令,最終得到一個(gè)ELF格式的OAT文件,ART 加載 OAT 文件后不需要經(jīng)過(guò)處理就可以直接運(yùn)行,它沒(méi)有了從字節(jié)碼裝換成機(jī)器碼的過(guò)程,因此運(yùn)行速度更快。

查看三方應(yīng)用如微信的安裝包如下:


在這里插入圖片描述

怎么還是odex,這個(gè)art文件是啥,這個(gè)vdex又是啥,==
官方回答:https://source.android.com/devices/tech/dalvik/configure
.vdex:其中包含 APK 的未壓縮 DEX 代碼,另外還有一些旨在加快驗(yàn)證速度的元數(shù)據(jù)。
.odex:其中包含 APK 中已經(jīng)過(guò) AOT 編譯的方法代碼。
.art (optional):其中包含 APK 中列出的某些字符串和類(lèi)的 ART 內(nèi)部表示,用于加快應(yīng)用啟動(dòng)速度。

使用file命令查看這個(gè)base.odex

在這里插入圖片描述

看到這個(gè)base.odex文件是ELF格式封裝的,所以這里的odex其實(shí)就是oat文件,只是還是叫odex后綴。

查看系統(tǒng)自帶應(yīng)用,比如system/priv-app/,system/app/中的apk,最終oat文件存放在/data/dalvik-cache/ 中:


在這里插入圖片描述

這里的dex文件也是oat文件,只是以dex為后綴命名,/data/dalvik-cache/ 下也有以oat為后綴命名的oat文件,通過(guò)如上的file命令就可以看出來(lái)。

2.2.2 readelf 查看oat文件結(jié)構(gòu)

微信的安裝包中的oat文件由于是elf格式封裝,可以使用readelf命令查看文件信息如下:

chengang@mi:~$ readelf -a '/home/chengang/Documents/apk_dex_structure/com.tencent.mm-GzKZdK2dYHRkCVqs-p_ZVA==/oat/arm/base.odex' 
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 03 00 00 00 00 00 00 00 00 
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - GNU
  ABI Version:                       0
  Type:                              DYN (Shared object file)
  Machine:                           ARM
  Version:                           0x1
  Entry point address:               0x0
  Start of program headers:          52 (bytes into file)
  Start of section headers:          4261112 (bytes into file)
  Flags:                             0x5000000, Version5 EABI
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         8
  Size of section headers:           40 (bytes)
  Number of section headers:         11
  Section header string table index: 10

Section Headers:
  [Nr] Name              Type            Addr     Off    Size   ES Flg Lk Inf Al
  [ 0]                   NULL            00000000 000000 000000 00      0   0  0
  [ 1] .rodata           PROGBITS        00001000 001000 1c9000 00   A  0   0 4096
  [ 2] .text             PROGBITS        001ca000 1ca000 22f98c 00  AX  0   0 4096
  [ 3] .bss              NOBITS          003fa000 000000 0079b8 00   A  0   0 4096
  [ 4] .dex              NOBITS          00402000 000000 40dacf4 00   A  0   0 4096
  [ 5] .dynstr           STRTAB          044dd000 3fa000 00006d 00   A  0   0 4096
  [ 6] .dynsym           DYNSYM          044dd070 3fa070 0000a0 10   A  5   1  4
  [ 7] .hash             HASH            044dd110 3fa110 000034 04   A  6   0  4
  [ 8] .dynamic          DYNAMIC         044de000 3fb000 000038 08   A  5   0 4096
  [ 9] .gnu_debugdata    PROGBITS        00000000 3fc000 0144a4 00      0   0 4096
  [10] .shstrtab         STRTAB          00000000 4104a4 000051 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings)
  I (info), L (link order), G (group), T (TLS), E (exclude), x (unknown)
  O (extra OS processing required) o (OS specific), p (processor specific)

There are no section groups in this file.

Program Headers:
  Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
  PHDR           0x000034 0x00000034 0x00000034 0x00100 0x00100 R   0x4
  LOAD           0x000000 0x00000000 0x00000000 0x1ca000 0x1ca000 R   0x1000
  LOAD           0x1ca000 0x001ca000 0x001ca000 0x22f98c 0x22f98c R E 0x1000
  LOAD           0x000000 0x003fa000 0x003fa000 0x00000 0x079b8 RW  0x1000
  LOAD           0x000000 0x00402000 0x00402000 0x00000 0x40dacf4 R   0x1000
  LOAD           0x3fa000 0x044dd000 0x044dd000 0x00144 0x00144 R   0x1000
  LOAD           0x3fb000 0x044de000 0x044de000 0x00038 0x00038 RW  0x1000
  DYNAMIC        0x3fb000 0x044de000 0x044de000 0x00038 0x00038 RW  0x1000

 Section to Segment mapping:
  Segment Sections...
   00     
   01     .rodata 
   02     .text 
   03     .bss 
   04     .dex 
   05     .dynstr .dynsym .hash 
   06     .dynamic 
   07     .dynamic 

Dynamic section at offset 0x3fb000 contains 7 entries:
  Tag        Type                         Name/Value
 0x00000004 (HASH)                       0x44dd110
 0x00000005 (STRTAB)                     0x44dd000
 0x00000006 (SYMTAB)                     0x44dd070
 0x0000000b (SYMENT)                     16 (bytes)
 0x0000000a (STRSZ)                      109 (bytes)
 0x0000000e (SONAME)                     Library soname: [base.odex]
 0x00000000 (NULL)                       0x0

There are no relocations in this file.

There are no unwind sections in this file.

Symbol table '.dynsym' contains 10 entries:
   Num:    Value  Size Type    Bind   Vis      Ndx Name
     0: 00000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 00001000 0x1c9000 OBJECT  GLOBAL DEFAULT    1 oatdata
     2: 001ca000     0 OBJECT  GLOBAL DEFAULT    2 oatexec
     3: 003f9988     4 OBJECT  GLOBAL DEFAULT    2 oatlastword
     4: 003fa000  8456 OBJECT  GLOBAL DEFAULT    3 oatbss
     5: 003fa000  8456 OBJECT  GLOBAL DEFAULT    3 oatbssmethods
     6: 003fc108 22704 OBJECT  GLOBAL DEFAULT    3 oatbssroots
     7: 004019b4     4 OBJECT  GLOBAL DEFAULT    3 oatbsslastword
     8: 00402000     0 OBJECT  GLOBAL DEFAULT    4 oatdex
     9: 044dccf0     4 OBJECT  GLOBAL DEFAULT    4 oatdexlastword

Histogram for bucket list length (total of 1 buckets):
 Length  Number     % of total  Coverage
      0  1          (100.0%)

No version information found in this file.

2.2.3 oat文件結(jié)構(gòu)大致如圖:
在這里插入圖片描述

如上圖應(yīng)知:

1.oat文件中有完整的dex文件,oat data section 中對(duì)應(yīng)著真正的oat文件,即 外層是elf 包含著 oat,oat 包含著dex
2.符號(hào)oatdata和oatlastword分別指定了oat文件在elf文件中的頭和尾的位置,符號(hào)oatexec指向可執(zhí)行段的位置;
3.oat文件有自己的頭和格式,并且其內(nèi)部包含了一個(gè)完整的dex文件。
4.oat其實(shí)就是一個(gè)Elf格式的二進(jìn)制文件,跟Elf文件不同的是它內(nèi)部多了oatdata、oatexec、oatlastword幾個(gè)符號(hào)。其中oatdata的起始位置相對(duì)文件頭固定為0x1000字節(jié),而我們通過(guò)oatdump反編譯的時(shí)候出來(lái)的地址是從0x1000開(kāi)始的,所以這也是為什么我們?cè)赽acktrace中計(jì)算地址的時(shí)候最后要減去0x1000,才能去dump里面找對(duì)應(yīng)的地址。

在這里插入圖片描述

oat文件格式如圖所示,這里0x1000是oatdata相對(duì)于文件頭的偏移,接著就是oatdata的大小,也就是oatdump中的executable_offset,這個(gè)值保存在Oat文件的OatHeader里面。然后就是oatexec段,也就是機(jī)器碼。而進(jìn)程運(yùn)行過(guò)程中異常如果掛在oat文件中,那么其pc一定是在oatexec段內(nèi)。

2.3. art文件

看到上面有art文件,.art是一些類(lèi)/filed/方法,app啟動(dòng)直接map到內(nèi)存,從odex中拆分出來(lái)的,art文件主要為了加快應(yīng)用的對(duì)“熱代碼”的加載與緩存

2.4. vdex文件

google在android8.0新增加了vdex文件,其中包含 APK 的未壓縮 DEX 代碼,另外還有一些旨在加快驗(yàn)證速度的元數(shù)據(jù)。

VDEX 文件有助于提升軟件更新的性能和用戶體驗(yàn)。VDEX 文件會(huì)存儲(chǔ)包含驗(yàn)證程序依賴項(xiàng)且經(jīng)過(guò)預(yù)驗(yàn)證的 DEX 文件,以便 ART 在系統(tǒng)更新期間無(wú)需再次解壓和驗(yàn)證 DEX 文件。無(wú)需執(zhí)行任何操作,即可實(shí)現(xiàn)該功能。該功能默認(rèn)處于啟用狀態(tài)。要停用該功能,請(qǐng)將 ART_ENABLE_VDEX 環(huán)境變量設(shè)為 false。

定義結(jié)構(gòu):art/runtime/vdex_file.h

34// VDEX files contain extracted DEX files. The VdexFile class maps the file to
35// memory and provides tools for accessing its individual sections.
36//
37// File format:
38//   VdexFile::VerifierDepsHeader    fixed-length header
39//      Dex file checksums
40//
41//   Optionally:
42//      VdexFile::DexSectionHeader   fixed-length header
43//
44//      quicken_table_off[0]  offset into QuickeningInfo section for offset table for DEX[0].
45//      DEX[0]                array of the input DEX files, the bytecode may have been quickened.
46//      quicken_table_off[1]
47//      DEX[1]
48//      ...
49//      DEX[D]
50//
51//   VerifierDeps
52//      uint8[D][]                 verification dependencies
53//
54//   Optionally:
55//      QuickeningInfo
56//        uint8[D][]                  quickening data
57//        uint32[D][]                 quickening data offset tables

三. 概括總結(jié):
在這里插入圖片描述

四.工具使用:

4.1.dx 和 dexdump工具:

在sdk目錄:~/Android/Sdk/build-tools/ 下有dex 打包工具:dx 解析dex的工具:dexdump;

源碼目錄下prebuilts下也有該工具;

手機(jī)中也有該工具: system/bin/dexdump

4.2. oatdump工具:

在手機(jī)中有該工具: /system/bin/oatdump,可以解析oat文件。

4.3.objdump工具

對(duì)于android開(kāi)發(fā)是源碼下對(duì)應(yīng)的arm-linux-androideabi-objdump而非電腦系統(tǒng)的objdump:

./prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.9/bin/arm-linux-androideabi-objdump -S ~/Documents/f3b/symbol/out/target/product/pyxis/symbols/vendor/lib/hw/camera.qcom.so | tee camera.qcom.asm
用來(lái)反編譯symbol文件為匯編指令用于問(wèn)題定位。

4.4. Vdex Extractor工具:

Vdex Extractor:從Vdex文件反編譯和提取Android Dex字節(jié)碼的工具:https://www.freebuf.com/sectool/185881.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容