一篇文章带你搞懂DEX文件的结构

Dex结构图:

DexHeader:

checksum 是对去除 magic 、 checksum 以外的文件部分作 alder32 算法得到的校验值,用于判断 DEX 文件是否被篡改。
signature 是对除去 magic 、 checksum 、 signature 以外的文件部分作 sha1 得到的文件哈希值。

示例代码:

public class HelloWorld {  
    int a = 0;  
    static String b = "HelloDalvik";  
  
    public int getNumber(int i, int j) {  
        int e = 3;  
        return e + i + j;  
    }  
  
    public static void main(String[] args) {  
        int c = 1;  
        int d = 2;  
        HelloWorld helloWorld = new HelloWorld();  
        String sayNumber = String.valueOf(helloWorld.getNumber(c, d));  
        System.out.println("HelloDex!" + sayNumber);  
    }  
}  

DexStringId:

struct DexStringId {
    u4 stringDataOff;
};

string_ids 是一个偏移量数组,stringDataOff 表示每个字符串在 data 区的偏移量。根据偏移量在 data 区拿到的数据中.

DexTypeId:

struct DexTypeId{
    u4 descriptorIdx;    /*指向DexStringId列表的索引*/
}

DexProtoId:

struct DexProtoId{
    u4 shortyIdx;            /*指向DexStringId列表的索引*/
    u4 returnTypeIdx;        /*指向DexTypeId列表的索引*/
    u4 parametersOff;        /*指向DexTypeList的位置偏移*/
}

struct DexTypeList{
    u4 size;                /*DexTypeItem的个数*/
    DexTypeItem list[1];    /*DexTypeItem结构*/
}

struct DexTypeItem{
    u2 typeIdx;             /*指向DexTypeId列表的索引*/
}

DexFieldId:

struct DexFieldId{
    u2 classIdx;        /*类的类型,指向DexTypeId列表的索引*/
    u2 typeIdx;        /*字段类型,指向DexTypeId列表的索引*/
    u4 nameIdx;        /*字段名,指向DexStringId列表的索引*/
}

注意不包括static属性。 
〇int HelloWorld.a , ①java.lang.String HelloWorld.b ,②java.io.PrintStream java.lang.System.out

DexMethodId:

struct DexMethodId{
    u2 classIdx;        /*类的类型,指向DexTypeId列表的索引*/
    u2 protoIdx;        /*声明类型,指向DexProtoId列表的索引*/
    u4 nameIdx;        /*方法名,指向DexStringId列表的索引*/
}


注意也不包括static属性。 

DexClassDef:

struct DexClassDef{
    u4 classIdx;        /*类的类型,指向DexTypeId列表的索引*/
    u4 accessFlags;        /*访问标志*/
    u4 superclassIdx;    /*父类类型,指向DexTypeId列表的索引*/
    u4 interfacesOff;    /*接口,指向DexTypeList的偏移*/
    u4 sourceFileIdx;    /*源文件名,指向DexStringId列表的索引*/
    u4 annotationsOff;    /*注解,指向DexAnnotationsDirectoryItem结构*/
    u4 classDataOff;    /*指向DexClassData结构的偏移*/
    u4 staticValuesOff;    /*指向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{
    uleb128 fieldIdx;            /*指向DexFieldId的索引*/
    uleb128 accessFlags;         /*访问标志*/
}

struct DexMethod{
    uleb128 methodIdx;          /*指向DexMethodId的索引*/
    uleb128 accessFlags;        /*访问标志*/
    uleb128 codeOff;            /*指向DexCode结构的偏移*/
}

struct DexCode {
    u2 registersSize;    /* 使用的寄存器个数 */
    u2 insSize;          /* 参数个数 */
    u2 outsSize;         /* 调用其他方法时使用的寄存器个数 */
    u2 triesSize;        /* Try/Catch个数 */
    u4 debugInfoOff;     /* 指向调试信息的偏移 */
    u4 insnsSize;        /* 指令集个数,以2字节为单位 */
    u2 insns[insnsSize]; /* 指令集 */
};

accessFlags:    ACC_PUBLIC,ACC_STATIC,ACC_,ACC_CONSTRUCTOR
staticFields:    static java.lang.String HelloWorld.b
instanceFields:    int HelloWorld.a
directMethods:    void HelloWorld.<clinit>(),void HelloWorld.<init>(),void HelloWorld.main(java.lang.String[])
virtualMethods:   int HelloWorld.getNumber(int, int)

DexMapList:

struct DexMapList {
    u4 size;                  /* 条目个数 */
    DexMapItem list[size];    /* 条目列表 */
};

struct DexMapItem {   
    u2 type;      /* 结构类型,kDexType 开头 */
    u2 unused;    /* 未使用,用于字节对齐 */
    u4 size;      /* 连续存放的结构个数 */
    u4 offset;    /* 结构的偏移 */
};

/* 结构类型代码 */
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,
};

总结图:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值