Android学习心得(15) --- Dex文件结构解析(1)

我在博客上发表一些我的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)

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-09-29 23:42:32

Android学习心得(15) --- Dex文件结构解析(1)的相关文章

Android学习心得(16) --- Dex文件结构实例解析(2)

我在博客上发表一些我的Android学习心得,希望对大家能有帮助. 这一篇我们讲述一下通过一个实例来分析dex文件结构和组成. 参考Leb128数据类型 Android学习心得(5) --- dex数据类型LEB128 参考实例分析学习理解dex文件结构Android学习心得(15) --- Dex文件结构解析(1) 参考baksmali工具使用Android学习心得(4) --- MAC下smali文件编写与运行 1.编译 我们通过一个例子来分析dex文件的构成 创建一个Hello.java文

Android学习心得(11) --- MAC下Android反编译(3)

我在博客上发表一些我的Android学习心得,希望对大家能有帮助. 在前一章我们学习了反编译. 这一章再次学习一下两个demo. 两个demo下载地址 KeygenMe#1.apk crackme0a.apk 链接: http://pan.baidu.com/s/1kTs11Tt 密码: davk KeygenMe#1.apk 1.首先在模拟器安装测试 由于模拟器检测不到wifi mac地址,所以会报错. 我们首先需要将检测代码跳过 先通过dex2jar和jd-gui查看源代码进行分析 查看了m

Android学习心得(10) --- MAC下Android反编译(2)

我在博客上发表一些我的Android学习心得,希望对大家能有帮助. 在前一章我们学习了基本的ndk-build脚本参数用法. 这一章再次学习一下反编译. 1.简介 这次分析的是一个很简单的程序,算是反编译入门的一个入门教程 主要学习一下工具的使用,下面是从网上下载下来的测试样本 测试样本EX_05_01_.apk 链接: http://pan.baidu.com/s/1sjOIXJn 密码: 5uq4 2.首先,使用dex2jar和jd-gui查看 参考:Android学习心得(8) --- M

[Android学习系列15]下拉刷新列表实现动态加载

使用google官方的SwipeRefreshLayout 参考: http://blog.csdn.net/easyer2012/article/details/22857807 http://stormzhang.github.io/android/2014/03/29/android-swiperefreshlayout/ http://www.eoeandroid.com/thread-330439-1-1.html http://www.oschina.net/translate/sw

Android学习心得(13) --- Android代码混淆(1)

我在博客上发表一些我的Android学习心得,希望对大家能有帮助. 这一篇我们讲述一下最新的ADT环境下如何进行Android混淆 在新版本的ADT创建项目时,混码的文件不再是proguard.cfg, 而是project.properties和proguard-project.txt. 我们把之前配置都配置好了,proguard已经在包含在sdk中了. 环境配置参考Android学习心得(1) --- MAC下Android环境的搭建 新建一个项目的时候,会自动生成project.proper

Android学习心得(14) --- Android代码混淆(2)

我在博客上发表一些我的Android学习心得,希望对大家能有帮助. 这一篇我们讲述一下Android混淆如何自定义proguard参数来实现 环境配置参考 Android学习心得(1) --- MAC下Android环境的搭建 签名参考Android学习心得(12) --- APK签名keystore 代码混淆Android学习心得(13) --- Android代码混淆(1) dex2jar&jd-guiAndroid学习心得(8) --- MAC下dex2jar和jd-gui使用 1.介绍p

Android 学习心得 快速排序

快速排序(Quicksort) 是对冒泡排序的一种改进,它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列. 设要排序的数组是A[0]……A[N-1],首先任意选取一个数据(通常选用数组的第一个数)作为关键数据,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,这个过程称为一趟快速排序. 值得注意的是,快速排序不是一种稳定

Android学习心得(12) --- APK签名keystore

我在博客上发表一些我的Android学习心得,希望对大家能有帮助. 这一篇我们讲述一下Eclipse如何生成keystore并为apk签名 所有的APK必须通过签名才能进行安装,我们在Eclipse中安装的APK 过程是Eclipse先进行打包成APK文件,使用默认的keystore文件进行签名 perferences -> Android -> Build 我们可以看到默认的keystore位置,我们进入.android目录下 我们需要自己创建一个正式的keystore进行签名 右击你需要签

Android 学习心得 TextView 添加垂直滚动条

XMl文件中: 添加android:scrollbars="vertical" 添加android:maxLines="10"  //设置一页最多显示10行 activity文件中: textview = (TextView)findViewById(R.id.httpCLient_textView); textview.setMovementMethod(ScrollingMovementMethod.getInstance());完成!! ^_^!! Andro