Android Dex文件数据结构解析

下面以Android4.4.2源码为例,来分析Dex文件的结构,这里分析的方式是将结构定义与实际的Hex字节码进行对照分析。

Dex文件结构图

这里写图片描述

1、查看/dalvik/libdex/DexFile.h,它里面包含了所有结构体定义。
2、我们将一个dex文件使用010Editor打开,并且使用Dex Template进行查看,可以看到Hex字节码和结构的对应关系

一、Dex文件整体结构

1、DexFile结构体定义

/*
 * Structure representing a DEX file.
 *
 * Code should regard DexFile as opaque, using the API calls provided here
 * to access specific structures.
 */
struct DexFile {
    /* directly-mapped "opt" header */
    const DexOptHeader* pOptHeader;

    /* pointers to directly-mapped structs and arrays in base DEX */
    // 下面就是各个结构和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;      // 链接数据区

    /*
     * These are mapped out of the "auxillary" section, and may not be
     * included in the file.
     */
    const DexClassLookup* pClassLookup;
    const void*         pRegisterMapPool;       // RegisterMapClassPool

    /* 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;
};

2、Dex Hex字节码
这里写图片描述

对应关系如下:

DexHeader*    pHeader   ---->struct header_item dex_header
DexStringId*  pStringIds---->struct string_id_list dex_string_ids
DexTypeId*    pTypeIds  ---->struct type_id_list dex_type_ids
DexFieldId*   pFieldIds ---->struct field_id_list dex_field_ids
DexMethodId*  pMethodIds---->struct method_id_list dex_method_ids
DexProtoId*   pProtoIds ---->struct proto_id_list dex_proto_ids
DexClassDef*  pClassDefs---->struct class_def_item_list dex_class_defs
DexLink*      pLinkData ---->struct map_list_type dex_map_list

二、DexHeader结构分析

1、DexHeader结构体定义

/*
 * Direct-mapped "header_item" struct.
 */
struct DexHeader {
    u1  magic[8];                        // dex版本标志
    u4  checksum;                        // alder32校验
    u1  signature[kSHA1DigestLen];       // SHA-1哈希值
    u4  fileSize;                        // 整个文件大小
    u4  headerSize;                      // DexHeader结构大小
    u4  endianTag;                       // 字符序标记
    u4  linkSize;                        // 链接段大小
    u4  linkOff;                         // 链接段偏移
    u4  mapOff;                          // DexMapList的文件偏移
    u4  stringIdsSize;                   // DexStringid的个数
    u4  stringIdsOff;                    // DexString的文件偏移
    u4  typeIdsSize;                     // DexTypeid的个数
    u4  typeIdsOff;                      // DexTypeid的文件偏移
    u4  protoIdsSize;                    // DexProtoid的个数
    u4  protoIdsOff;                     // DexProtoid的文件偏移
    u4  fieldIdsSize;                    // DexFieldid的个数
    u4  fieldIdsOff;                     // DexFieldid的文件偏移
    u4  methodIdsSize;                   // DexMethodid的个数
    u4  methodIdsOff;                    // DexMethodid的文件偏移
    u4  classDefsSize;                   // DexClassDef的个数
    u4  classDefsOff;                    // DexClassDef的文件偏移
    u4  dataSize;                        // 数据段的大小
    u4  dataOff;                         // 数据段的文件偏移
};

2、DexHeader Hex字节码

这里写图片描述

三、DexStringId结构分析

1、DexStringId结构体定义

/*
 * Direct-mapped "string_id_item".
 */
struct DexStringId {
    u4 stringDataOff;      // string_data_item的偏移地址
};
struct string_data_item {
    uleb128 utf16_size;   // 字符串大小
    ubyte data;           // 字符串的值
}

2、DexStringId Hex字节码

这里写图片描述

四、DexTypeId结构分析

1、DexTypeId结构体定义

/*
 * Direct-mapped "type_id_item".
 */
struct DexTypeId {
    u4  descriptorIdx;      // 表示这个类型描述符在string_ids中的索引值
};

2、DexTypeId Hex字节码
这里写图片描述

五、DexFieldId结构分析

1、DexFieldId结构体定义

/*
 * Direct-mapped "field_id_item".
 */
struct DexFieldId {
    u2  classIdx;           // 字段所属所属的 class 类型在type_ids中的索引
    u2  typeIdx;            // 字段本身类型在type_ids中的索引
    u4  nameIdx;            // 字段名称在stringIds中的索引
};

2、DexFieldId Hex字节码
这里写图片描述

六、DexMethodId结构分析

1、DexMethodId结构体定义

/*
 * Direct-mapped "method_id_item".
 */
struct DexMethodId {
    u2  classIdx;           // 方法所属所属的 class 类型在type_ids中的索引
    u2  protoIdx;           // 方法prototype在protoIds中的索引
    u4  nameIdx;            // 方法名称在stringIds中的索引
};

2、DexMethodId Hex字节码

这里写图片描述

七、DexProtoId结构分析

1、DexProtoId结构体定义

/*
 * Direct-mapped "proto_id_item".
 */
struct DexProtoId {
    u4  shortyIdx;          // 表示这个短描述符在string_ids中的索引值
    u4  returnTypeIdx;      // 返回类型在type_ids中的索引
    u4  parametersOff;      // 参数类型列表在文件中的偏移,参数列表结构为DexTypeList
};
/*
 * Direct-mapped "type_list".
 */
struct DexTypeList {
    u4  size;               // DexTypeItem的个数
    DexTypeItem list[1];    // DexTypeItem结构  
};
/*
 * Direct-mapped "type_item".
 */
struct DexTypeItem {
    u2  typeIdx;            // 类型在type_ids中的索引
};

2、DexProtoId Hex字节码
这里写图片描述

八、DexClassDef结构分析

1、DexClassDef结构体定义

/*
 * Direct-mapped "class_def_item".
 */
struct DexClassDef {
    u4  classIdx;           // class 类型在type_ids中的索引
    u4  accessFlags;        // class 的访问类型 ,诸如 public , final , static
    u4  superclassIdx;      // class父类类型在type_ids中的索引
    u4  interfacesOff;      // classinterfaces在文件中的偏移,interfaces的数据结构为DexTypeList
    u4  sourceFileIdx;      // 源文件名称在stringIds中的索引
    u4  annotationsOff;     // class注释的偏移地址,注释数据结构为DexAnnotationsDirectoryItem
    u4  classDataOff;       // class类信息的偏移地址,数据结构DexClassData
    u4  staticValuesOff;    // class静态数据的偏移地址,数据结构DexEncodedArray
};
struct DexClassData {  
    DexClassDataHeader  header;             // 指定字段与方法的个数 
    DexField*           staticFields;       // 静态字段,DexField结构  
    DexField*           instanceFields;    // 实例字段,DexField结构  
    DexMethod*          directMethods;      // 直接方法,DexMethod结构  
    DexMethod*          virtualMethods;     // 虚方法,DexMethod结构  
}
struct DexClassDataHeader {  
    u4 staticFieldsSize;    // 静态字段个数  
    u4 instanceFieldsSize;  // 实例字段个数  
    u4 directMethodsSize;   // 直接方法个数  
    u4 virtualMethodsSize;  // 虚方法个数  
} 
struct DexField {  
    u4 fieldIdx;        // 指向DexFieldId的索引 
    u4 accessFlags;     // 访问标志
}
struct DexMethod {  
    u4 methodIdx;       // 指向DexMethodId的索引  
    u4 accessFlags;     // 访问标志  
    u4 codeOff;         //指向DexCode结构的偏移 
}
struct DexCode { 
    u2 registersSize;   //使用寄存器个数 
    u2 insSize;         //参数个数 
    u2 outsSize;        //调用其他方法时使用的寄存器个数 
    u2 triesSize;       //try/catch个数 
    u4 debugInfoOff;    //指向调试信息的偏移 
    u4 insnsSize;       //指令集个数,以2字节为单位 
    u2 insns[1];        //指令集 
    /* followed by optional u2 padding */ 
    /* followed by try_item[triesSize] */ 
    /* followed by uleb handlersSize */ 
    /* followed by catch_handler_item[handlersSize] */ 
};
/*
 * Direct-mapped "encoded_array".
 *
 * NOTE: this structure is byte-aligned.
 */
struct DexEncodedArray {
    u1  array[1];                   /* data in encoded_array format */
};

2、DexClassDef Hex字节码
这里写图片描述

九、DexLink结构分析

1、DexLink结构体定义

/*
 * Link table.  Currently undefined.
 */
struct DexLink {
    u1  bleargh;
};

2、DexLink Hex字节码

这里写图片描述

整体对照图如下:

这里写图片描述

整体关联图如下:
这里写图片描述

参考文章:

分析一个简单的 .dex 文件 —— Hello.dex

dex文件格式分析

欢迎关注微信公众号:DroidMind
精品内容独家发布平台


呈现与博客不一样的技术干货

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值