標籤:android dex分析 dex 結構 android應用
我在部落格上發表一些我的Android學習心得,希望對大家能有協助。
這一篇我們講述一下Android可執行檔dex的結構解析。
參考Leb128資料類型 Android學習心得(5) --- dex資料類型LEB128
參考執行個體分析學習理解dex檔案結構Android學習心得(15) --- Dex檔案結構解析(1)
1、Dex背景
Android應用開發和Dalvik虛擬機器Android應用所使用的程式設計語言是Java語言,在編譯時間使用JDK將Java來源程式編程成標準的Java位元組碼檔案。 而後通過工具軟體DX把所有的位元組碼檔案轉成Android DEX檔案(classes.dex)。 最後使用Android打包工具(aapt)將DEX檔案,資源檔以及AndroidManifest.xml檔案(二進位格式)組合成一個應用程式套件組合(APK)。 應用程式套件組合可以被發布到手機上運行。
2、Dex檔案整體結構
從中我們可以看到,dex檔案是由多個結構體組成。Dex Header是dex標頭檔,定義了一些屬性,記錄了其他資料結構的位移地址。從String table ~ Class Def table是位移索引的地區。Data Section則是真實資料存放地方。
首先我們通過/dalvik/libdex/DexFile.h查看DexFile結構
/* * Structure representing a DEX file. * * Code should regard DexFile as opaque, using the API calls provided here * to access specific structures. */typedef struct DexFile { /* directly-mapped "opt" header */ const DexOptHeader* pOptHeader; /* pointers to directly-mapped structs and arrays 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; /* mapped in "auxillary" section */ const DexClassLookup* pClassLookup; /* points to start of DEX file data */ const u1* baseAddr; /* track memory overhead for auxillary structures */ int overhead; /* additional app-specific data structures associated with the DEX */ void* auxData;} DexFile;
3、Dex Header解析
我們通過/dalvik/libdex/DexFile.h查看header_item
/* * Direct-mapped "header_item" struct. */typedef struct DexHeader { u1 magic[8]; /* includes version number */ u4 checksum; /* adler32 checksum */ u1 signature[kSHA1DigestLen]; /* SHA-1 hash */ u4 fileSize; /* length of entire file */ u4 headerSize; /* offset to start 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;} DexHeader;
4、Mapoff指向MapList
DexHeader結構中MapList資料結構
/* * Direct-mapped "map_item". */typedef struct DexMapItem { u2 type; /* type code (see kDexType* above) */ u2 unused; u4 size; /* count of items of the indicated type */ u4 offset; /* file offset to the start of data */} DexMapItem;/* * Direct-mapped "map_list". */typedef struct DexMapList { u4 size; /* #of entries in list */ DexMapItem list[1]; /* entries */} DexMapList;
在DexMapItem結構中,type是一個枚舉常量
/* map item type codes */ enum { kDexTypeHeaderItem = 0x0000, kDexTypeStringIdItem = 0x0001, kDexTypeTypeIdItem = 0x0002, kDexTypeProtoIdItem = 0x0003, kDexTypeFieldIdItem = 0x0004, kDexTypeMethodIdItem = 0x0005, kDexTypeClassDefItem = 0x0006, kDexTypeMapList = 0x1000, kDexTypeTypeList = 0x1001, kDexTypeAnnotationSetRefList = 0x1002, kDexTypeAnnotationSetItem = 0x1003, kDexTypeClassDataItem = 0x2000, kDexTypeCodeItem = 0x2001, kDexTypeStringDataItem = 0x2002, kDexTypeDebugInfoItem = 0x2003, kDexTypeAnnotationItem = 0x2004, kDexTypeEncodedArrayItem = 0x2005, kDexTypeAnnotationsDirectoryItem = 0x2006, };
5、部分結構
通過DexMapList結構產生的表格,來分別找出其中DexMapItem中的結構
由於class_def_item比較複雜,單獨敘述
/* * Direct-mapped "string_id_item". */ typedef struct DexStringId { u4 stringDataOff; /* file offset to string_data_item */ } DexStringId; /* * Direct-mapped "type_id_item". */ typedef struct DexTypeId { u4 descriptorIdx; /* index into stringIds list for type descriptor */ } DexTypeId; /* * Direct-mapped "field_id_item". */ typedef struct DexFieldId { u2 classIdx; /* index into typeIds list for defining class */ u2 typeIdx; /* index into typeIds for field type */ u4 nameIdx; /* index into stringIds for field name */ } DexFieldId; /* * Direct-mapped "method_id_item". */ typedef struct DexMethodId { u2 classIdx; /* index into typeIds list for defining class */ u2 protoIdx; /* index into protoIds for method prototype */ u4 nameIdx; /* index into stringIds for method name */ } DexMethodId; /* * Direct-mapped "proto_id_item". */ typedef struct DexProtoId { u4 shortyIdx; /* index into stringIds for shorty descriptor */ u4 returnTypeIdx; /* index into typeIds list for return type */ u4 parametersOff; /* file offset to type_list for parameter types */ } DexProtoId;
在DexProtoId結構中,parameterOff是type_list的位移
/* * Direct-mapped "type_item". */ typedef struct DexTypeItem { u2 typeIdx; /* index into typeIds */ } DexTypeItem; /* * Direct-mapped "type_list". */ typedef struct DexTypeList { u4 size; /* #of entries in list */ DexTypeItem list[1]; /* entries */ } DexTypeList;
6、DexClassDef結構
/* * Direct-mapped "class_def_item". */ typedef struct DexClassDef { u4 classIdx; /* index into typeIds for this class */ u4 accessFlags; u4 superclassIdx; /* index into typeIds for superclass */ u4 interfacesOff; /* file offset to DexTypeList */ u4 sourceFileIdx; /* index into stringIds for source file name */ u4 annotationsOff; /* file offset to annotations_directory_item */ u4 classDataOff; /* file offset to class_data_item */ u4 staticValuesOff; /* file offset to DexEncodedArray */ } DexClassDef;
annotationsOff是註解目錄結構位移,目前暫不詳細說明,如果沒有註解,其值為0。
classDataOff是指向class_data_item位移,下面介紹其結構
路徑為/dalvik/libdex/DexClass.h
/* expanded form of class_data_item. Note: If a particular item is * absent (e.g., no static fields), then the corresponding pointer * is set to NULL. */ typedef struct DexClassData { DexClassDataHeader header; DexField* staticFields; DexField* instanceFields; DexMethod* directMethods; DexMethod* virtualMethods; } DexClassData;/* expanded form of a class_data_item header */ typedef struct DexClassDataHeader { u4 staticFieldsSize; u4 instanceFieldsSize; u4 directMethodsSize; u4 virtualMethodsSize; } DexClassDataHeader;
DexField & DexMethod
/* expanded form of encoded_field */ typedef struct DexField { u4 fieldIdx; /* index to a field_id_item */ u4 accessFlags; } DexField; /* expanded form of encoded_method */ typedef struct DexMethod { u4 methodIdx; /* index to a method_id_item */ u4 accessFlags; u4 codeOff; /* file offset to a code_item */ } DexMethod;
code_item位於/dalvik/libdex/DexFile.h中定義
/* * Direct-mapped "code_item". * * The "catches" table is used when throwing an exception, * "debugInfo" is used when displaying an exception stack trace or * debugging. An offset of zero indicates that there are no entries. */ typedef struct DexCode { u2 registersSize; u2 insSize; u2 outsSize; u2 triesSize; u4 debugInfoOff; /* file offset to debug info stream */ u4 insnsSize; /* size of the insns array, in u2 units */ u2 insns[1]; /* followed by optional u2 padding */ /* followed by try_item[triesSize] */ /* followed by uleb128 handlersSize */ /* followed by catch_handler_item[handlersSize] */ } DexCode;
到目前為止,基本上我們把dex檔案組成結構給大家展示了出來。
下面要進行的就是對dex檔案執行個體結合這篇來進行分析
Android學習心得(16) --- Dex檔案結構解析(2)
著作權聲明:本文為博主原創文章,未經博主允許不得轉載。
Android學習心得(15) --- Dex檔案結構解析(1)