Dex 文件格式详解

  • DEX 文件中会出现的数据类型
类型含义
u1等同于 uint8_t,表示 1 字节的无符号 数
u2等同于 uint16_t,表示 2 字节的无符号数
u4等同于 uint32_t,表示 4 字节的无符号数
u8等同于 uint64_t,表示 8 字节的无符号数
sleb128有符号 LEB128,可变长度 1~5 字节
uleb128无符号 LEB128,可变长度 1~5 字节
uleb128p1无符号 LEB128 值加1,可变长 1~5 字节

sleb128、uleb128、uleb128p1:
  • 小端结尾的,第一个字节代表的是整形值的最低 7 比特位的值,第二个字节代表次低 7 位,以此类推。所以代码中每发现要多用一个字节,都要多向左移动 7 位
  • sleb128 需要进行符号位扩展,先左移到最左边,再算术右移同样的位数实现
  • uleb128p1 是将其当做 uleb128 编码的值进行解码,然后再减一。解码时要减一,那么反过来编码时就要加一

  • DEX 文件整体结构

结构体表示:

struct DexFile
{
	DexHeader           Header;
	DexStringId          StringIds[stringIdsSize];
	DexTypeId           TypeIds[typeIdsSize];
	DexProtoId           ProtoIds[protoIdsSize];
	DexFieldId            FieldIds[fieldIdsSize];
	DexMethodId       MethodIds[methodIdsSize];
	DexClassDef         ClassDefs[classDefsSize];
	DexData                Data[];
	DexLink                 LinkData;
};

  • DexHeader
DexHeader 结构的数据分为 “索引结构区” 和 “数据区”,“索引结构区” 中各数据结构的偏移地址都是从 DexHeader 结构的 stringIdsOff~classDefsOff 字段的值指定的,它们并非真正的类数据,而是指向 DEX 文件的 data 数据区相对于 Dex 头的偏移或结构索引。

下面所说的偏移都是指相对于 Dex 头的偏移

结构体表示:
typedef struct _DexHeader
{
	u1	magic[8];						// dex 版本标识,"dex.035"
	u4	checksum;						// adler32 检验
	u1	signature[kSHA1DigestLen];		// SHA-1 哈希值,20个字节
	u4	fileSize;						// 整个 dex 文件大小
	u4	headerSize;						// DexHeader 结构大小,0x70
	u4	endianTag;						// 字节序标记,小端 "0x12345678",大端"0x78563412"
	u4	linkSize;						// 链接段大小
	u4	linkOff;						// 链接段偏移
	u4	mapOff;							// DexMapList 的偏移
	u4	stringIdsSize;					// DexStringId 的个数
	u4	stringIdsOff;					// DexStringId 的偏移		字符串
	u4	typeIdsSize;					// DexTypeId 的个数
	u4	typedeIdsOff;					// 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;						// 数据段的偏移
}DexHeader, *PDexHeader;

magic 标识一个有效的 dex 文件,一般是 "dex.035"
checksumDEX 文件的校验和
signature文件的哈希值,20个字节
fileSize记录包括 DexHeader 在内的整个dex 文件的大小
headerSize记录 DexHeader 结构本身占用的字节数,目前为 0x70
endianTag指定 dex 运行环境的 CPU 字节序,小端:"0x12345678",大端:"0x78563412"
linkSize表示链接段的大小,如果为 0 表示该 DEX 文件不是静态链接
linkOff表示链接段距离 Dex 头的偏移,如果 linkSize 为 0,此值也为 0

  • mapOff 字段
指定 DexMapList 结构距离 Dex 头的偏移

DexMapList 结构体:
struct     DexMapList
{
	u4     size;                                   // DexMapItem 的个数
	DexMapItem     list[1];               // DexMapItem 结构
};
    • size:表示接下来有多少个 DexMapItem 
    • list:是一个 DexMapItem 结构体数组
DexMapItem 结构体:
struct     DexMapItem
{
	u2     type;                    // kDexType 开头的类型
	u2     unused;               // 未使用,用于对齐
	u4     size;                     // 指定类型的个数
	u4     offset;                 // 指定类型数据的文件偏移
};
    • type:一个枚举常量
      enum
      {
      	kDexTypeHeaderItem = 0x0000,	// 对应 DexHeader     
      	kDexTypeStringIdItem = 0x0001,	// 对应 stringIdsSize 与 stringIdsOff 字段     
      	kDexTypeTypeIdItem = 0x0002,	// 对应 typeIdsSize 与 typeIdsOff 字段     
      	kDexTypeProtoIdItem = 0x0003,	// 对应 protoIdsSize 与 protoIdsOff 字段     
      	kDexTypeFieldIdItem = 0x0004,	// 对应 fieldIdsSize 与 fieldIdsOff 字段     
      	kDexTypeMethodIdItem = 0x0005,	// 对应 methodIdsSize 与 methodIdsOff 字段     
      	kDexTypeClassDefItem = 0x0006,	// 对应 classDefsSize 与 classDefsOff 字段     
      	kDexTypeMapList = 0x1000,     
      	kDexTypeTypeList = 0x1001,     
      	kDexTypeAnnotationSetRefList = 0x1002,     
      	kDexTypeAnnotationSetItem = 0x1003,     
      	kDexTypeClassDataItem = 0x2000,     
      	kDexTypeCodeItem = 0x2001,     
      	kDexTypeStringDataItem = 0x2002,     
      	kDexTypeDebugInfoItem = 0x2003,     
      	kDexTypeAnnotationItem = 0x2004,    
      	kDexTypeEncodeArrayItem = 0x2005,    
      	kDexTypeAnnotationsDirectoryItem = 0x2006
      };
    • size:指定类型的个数
    • offset:指定类型数据的偏移

  • DexStringId 结构体(stringIdsSize 与 stringIdsOff 字段) 
typedef struct _DexStringId
{
	u4	stringDataOff;					// 指向 MUTF-8 字符串的偏移
}DexStringId, *PDexStringId;

MUTF-8 编码:
1) 使用 1~3 字节编码长度
2) 大于 16 位的 Unicode 编码 U+10000~U+10FFFF 使用 3 字节来编码
3) U+0000 采用 2 字节编码
4) 采用空字符 null 作为结尾
5) 第一个字节存放字节个数(不包含自已)

  • DexTypeId 结构体(typeIdsSize 与 typeIdsOff 字段)
是一个类型结构体
typedef struct _DexTypeId
{
	u4     descriptorIdx;   // 指向 DexStringId 列表的索引
}DexTypeId, *PDexTypeId;
    • descriptorIdx:指向 DexStringId 列表的索引,它对应的字符串代表了具体类的类型

  • DexProtoId 结构体(protoIdsSize 与 protoIdsOff 字段)
是一个方法声明结构体, 方法声明 = 返回类型 + 参数列表
typedef struct _DexProtoId
{
	u4	shortyIdx;			// 方法声明字符串,指向 DexStringId 列表的索引
	u4	returnTypeIdx;		// 方法返回类型字符串,指向 DexStringId 列表的索引
	u4	parametersOff;		// 方法的参数列表,指向 DexTypeList 结构体的偏移
}DexProtoId, *PDexProtoId;
    • shortyIdx:方法声明字符串,方法声明 = 返回类型 + 参数列表
    • returnTypeIdx:方法返回类型字符串
    • parametersOff:指向一个 DexTypeList 结构体,存放了方法的参数列表
DexTypeList 结构体:
typedef struct _DexTypeList
{
	u4	size;				// 接下来 DexTypeItem 的个数
	DexTypeItem* list;		// DexTypeItem 结构
}DexTypeList, *PDexTypeList;
    • size:接下来 DexTypeItem 的个数
    • list:是一个 DexTypeItem 结构体数组

DexTypeItem 结构体:
typedef struct _DexTypeItem
{
	u2	typeIdx;			// 指向 DexTypeId 列表的索引
}DexTypeItem, *PDexTypeItem;
    • typeIdx:DexTypeId 列表的索引

  • DexFieldId 结构体(fieldIdsSize 与 fieldIdsOff 字段)
指明了字段所有的类、字段的类型以及字段名
typedef struct _DexFieldId
{
	u2	classIdx;			// 类的类型,指向 DexTypeId 列表的索引
	u2	typeIdx;			// 字段的类型,指向 DexTypeId 列表的索引
	u4	nameIdx;			// 字段名,指向 DexStringId 列表的索引
}DexFieldId, *PDexFieldId;
    • classIdx:类的类型
    • typeIdx:字段的类型
    • nameIdx:字段名

  • DexMethodId 结构体(methodIdsSize 与 methodIdsOff 字段)
方法结构体
typedef struct _DexMethodId
{
	u2	classIdx;			// 类的类型,指向 DexTypeId 列表的索引
	u2	protoIdx;			// 声明的类型,指向 DexProtoId 列表的索引
	u4	nameIdx;			// 方法名,指向 DexStringId 列表的索引
}DexMethodId, *PDexMethodId;
    • classIdx:类的类型
    • protoIdx:声明的类型
    • nameIdx:方法名

  • DexClassDef 结构体(classDefsSize 和 classDefsOff 字段)
类结构体
typedef struct _DexClassDef
{
	u4     classIdx;                 // 类的类型,指向 DexTypeId 列表的索引
	u4     accessFlags;              // 访问标志
	u4     superclassIdx;            // 父类类型,指向 DexTypeId 列表的索引
	u4     interfacesOff;            // 接口,指向 DexTypeList 的偏移,否则为0
	u4     sourceFileIdx;            // 源文件名,指向 DexStringId 列表的索引
	u4     annotationsOff;           // 注解,指向 DexAnnotationsDirectoryItem 结构,或者为 0
	u4     classDataOff;             // 指向 DexClassData 结构的偏移,类的数据部分
	u4     staticValuesOff;          // 指向 DexEncodedArray 结构的偏移,记录了类中的静态数据,主要是静态方法
}DexClassDef, *PDexClassDef;
    • classIdx:类的类型,指向 DexTypeId 列表的索引
    • accessFlags:访问标志
    • superclassIdx:父类类型,指向 DexTypeId 列表的索引
    • interfacesOff:接口,指向 DexTypeList 的偏移,如果没有,则为 0
    • sourceFileIdx:源文件名,指向 DexStringId 列表的索引
    • annotationsOff:注解,指向 DexAnnotationsDirectoryItem 结构,或者为 0
    • classDataOff:指向 DexClassData 结构的偏移,类的数据部分
    • staticValuesOff:指向 DexEncodeArray 结构的偏移,记录了类中的静态数据,没有则为 0
DexClassData 结构体:
typedef struct _DexClassData
{
	DexClassDataHeader		header;				// 指定字段与方法的个数
	DexField*				staticFields;		// 静态字段,DexField 结构
	DexField*				instanceFields;		// 实例字段,DexField 结构
	DexMethod*				directMethods;		// 直接方法,DexMethod 结构
	DexMethod*				virtualMethods;		// 虚方法,DexMethod 结构
}DexClassData, *PDexClassData;
    • header:DexClassDataHeader 结构体,指定字段与方法的个数
    • staticFields:静态字段,DexField 结构体数组
    • instanceFields:实例字段,DexField 结构体数组
    • directMethods:直接方法,DexMthod 结构体数组
    • virtualMethods:虚方法,DexMethod 结构体数组
DexClassDataHeader 结构体:
typedef struct _DexClassDataHeader
{
	uleb128	staticFieldsSize;					// 静态字段个数
	uleb128	instanceFieldsSize;					// 实例字段个数
	uleb128	directMethodsSize;					// 直接方法个数
	uleb128	virtualMethodsSize;					// 虚方法个数
}DexClassDataHeader, *PDexClassDataHeader;
    • staticFieldsSize:静态字段个数
    • instanceFieldsSize:实例字段个数
    • directMethodsSize:直接方法个数
    • virtualMethodsSize:虚方法个数
DexField 结构体:
typedef struct _DexField
{
	uleb128	fieldIdx;			// 指向 DexFieldId 的索引
	uleb128	accessFlags;		// 访问标志
}DexField, *PDexField;
    • fieldIdx:字段描述,指向 DexFieldId 的索引
    • accessFlags:访问标志
DexMethod 结构体:
typedef struct _DexMethod
{
	uleb128	methodIdx;			// 指向 DexMethodId 的索引
	uleb128	accessFlags;		// 访问标志
	uleb128	codeOff;			// 指向 DexCode 结构的偏移
}DexMethod, *PDexMethod;
    • methodIdx:方法描述,指向 DexMethodId 的索引
    • accessFlags:访问标志
    • codeOff:指向 DexCode 结构的偏移
DexCode 结构体:
typedef struct _DexCode
{
	u2	registersSize;			// 使用的寄存器个数
	u2	insSize;				// 参数个数
	u2	outsSize;				// 调用其他方法时使用的寄存器个数
	u2	triesSize;				// Try/Catch 个数
	u4	debbugInfoOff;			// 指向调试信息的偏移
	u4	insnsSize;				// 指令集个数,以 2 字节为单位
	u2*	insns;					// 指令集
}DexCode, *PDexCode;



还有一些不太常见的结构体,要用的时候再去看看就行了。Dex 文件的整体结构就这样,就是一个多层索引的结构。
为了熟悉 Dex 文件格式,写了一个程序去解析 Dex 文件里的类的信息,程序比较粗糙,学习为主

dex.h
/*
 * Dex 文件中数据结构的声明
 */

#pragma once
#include  <string>
typedef unsigned char uint8_t;
typedef unsigned short int uint16_t;
typedef unsigned int uint32_t;
typedef unsigned long long uint64_t;

typedef uint8_t	 u1;
typedef uint16_t u2;
typedef uint32_t u4;
typedef uint64_t u8;

typedef unsigned int uleb128;
typedef unsigned int uleb128p1;
typedef int sleb128;

#define kSHA1DigestLen	20

enum {
	ACC_PUBLIC = 0x00000001,       // class, field, method, ic
	ACC_PRIVATE = 0x00000002,       // field, method, ic
	ACC_PROTECTED = 0x00000004,       // field, method, ic
	ACC_STATIC = 0x00000008,       // field, method, ic
	ACC_FINAL = 0x00000010,       // class, field, method, ic
	ACC_SYNCHRONIZED = 0x00000020,       // method (only allowed on natives)
	ACC_SUPER = 0x00000020,       // class (not used in Dalvik)
	ACC_VOLATILE = 0x00000040,       // field
	ACC_BRIDGE = 0x00000040,       // method (1.5)
	ACC_TRANSIENT = 0x00000080,       // field
	ACC_VARARGS = 0x00000080,       // method (1.5)
	ACC_NATIVE = 0x00000100,       // method
	ACC_INTERFACE = 0x00000200,       // class, ic
	ACC_ABSTRACT = 0x00000400,       // class, method, ic
	ACC_STRICT = 0x00000800,       // method
	ACC_SYNTHETIC = 0x00001000,       // field, method, ic
	ACC_ANNOTATION = 0x00002000,       // class, ic (1.5)
	ACC_ENUM = 0x00004000,       // class, field, ic (1.5)
	ACC_CONSTRUCTOR = 0x00010000,       // method (Dalvik only)
	ACC_DECLARED_SYNCHRONIZED =
	0x00020000,       // method (Dalvik only)
	ACC_CLASS_MASK =
	(ACC_PUBLIC | ACC_FINAL | ACC_INTERFACE | ACC_ABSTRACT
	| ACC_SYNTHETIC | ACC_ANNOTATION | ACC_ENUM),
	ACC_INNER_CLASS_MASK =
	(ACC_CLASS_MASK | ACC_PRIVATE | ACC_PROTECTED | ACC_STATIC),
	ACC_FIELD_MASK =
	(ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED | ACC_STATIC | ACC_FINAL
	| ACC_VOLATILE | ACC_TRANSIENT | ACC_SYNTHETIC | ACC_ENUM),
	ACC_METHOD_MASK =
	(ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED | ACC_STATIC | ACC_FINAL
	| ACC_SYNCHRONIZED | ACC_BRIDGE | ACC_VARARGS | ACC_NATIVE
	| ACC_ABSTRACT | ACC_STRICT | ACC_SYNTHETIC | ACC_CONSTRUCTOR
	| ACC_DECLARED_SYNCHRONIZED),
};


/*
 * DexHeader
 */
typedef struct _DexHeader
{
	u1	magic[8];						// dex 版本标识,"dex.035"
	u4	checksum;						// adler32 检验
	u1	signature[kSHA1DigestLen];		// SHA-1 哈希值,20个字节
	u4	fileSize;						// 整个 dex 文件大小
	u4	headerSize;						// DexHeader 结构大小,0x70
	u4	endianTag;						// 字节序标记,小端 "0x12345678",大端"0x78563412"
	u4	linkSize;						// 链接段大小
	u4	linkOff;						// 链接段偏移
	u4	mapOff;							// DexMapList 的偏移
	u4	stringIdsSize;					// DexStringId 的个数
	u4	stringIdsOff;					// DexStringId 的偏移		字符串
	u4	typeIdsSize;					// DexTypeId 的个数
	u4	typedeIdsOff;					// 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;						// 数据段的偏移
}DexHeader, *PDexHeader;

/*
 * DexStringId
 */
typedef struct _DexStringId
{
	u4	stringDataOff;					// 指向 MUTF-8 字符串的偏移
}DexStringId, *PDexStringId;


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


/*
 * DexProtoId
 */
typedef struct _DexProtoId
{
	u4	shortyIdx;			// 方法声明字符串,指向 DexStringId 列表的索引,方法声明 = 返回类型+参数列表
	u4	returnTypeIdx;		// 方法返回类型字符串,指向 DexStringId 列表的索引
	u4	parametersOff;		// 方法的参数列表,指向 DexTypeList 结构体的偏移
}DexProtoId, *PDexProtoId;


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


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


typedef struct _DexClassDataHeader
{
	uleb128	staticFieldsSize;					// 静态字段个数
	uleb128	instanceFieldsSize;					// 实例字段个数
	uleb128	directMethodsSize;					// 直接方法个数
	uleb128	virtualMethodsSize;					// 虚方法个数
}DexClassDataHeader, *PDexClassDataHeader;

typedef struct _DexField
{
	uleb128	fieldIdx;			// 指向 DexFieldId 的索引
	uleb128	accessFlags;		// 访问标志
}DexField, *PDexField;

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


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


/*
 * DexClassDef
 */
typedef struct _DexClassDef
{
	u4     classIdx;                 // 类的类型,指向 DexTypeId 列表的索引
	u4     accessFlags;              // 访问标志
	u4     superclassIdx;            // 父类类型,指向 DexTypeId 列表的索引
	u4     interfacesOff;            // 接口,指向 DexTypeList 的偏移,否则为0
	u4     sourceFileIdx;            // 源文件名,指向 DexStringId 列表的索引
	u4     annotationsOff;           // 注解,指向 DexAnnotationsDirectoryItem 结构,或者为 0
	u4     classDataOff;             // 指向 DexClassData 结构的偏移,类的数据部分
	u4     staticValuesOff;          // 指向 DexEncodedArray 结构的偏移,记录了类中的静态数据
}DexClassDef, *PDexClassDef;


/*
 * DexClassData
 */
typedef struct _DexClassData
{
	DexClassDataHeader		header;				// 指定字段与方法的个数
	DexField*				staticFields;		// 静态字段,DexField 结构
	DexField*				instanceFields;		// 实例字段,DexField 结构
	DexMethod*				directMethods;		// 直接方法,DexMethod 结构
	DexMethod*				virtualMethods;		// 虚方法,DexMethod 结构
}DexClassData, *PDexClassData;






/*
 * DexData
 */
typedef struct _DexData
{

}DexData, *PDexData;


/*
 * DexLink
 */
typedef struct _DexLink
{

}DexLink, *PDexLink;

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


/*
* DexTypeList
*/
typedef struct _DexTypeList
{
	u4	size;				// 接下来 DexTypeItem 的个数
	DexTypeItem* list;		// DexTypeItem 结构
}DexTypeList, *PDexTypeList;


/*
 * DexFile
 */
class DexFile
{
	// Dex 文件结构
private:
	PDexHeader		dexHeader;			// dex 头
	PDexStringId	stringIds;			// 字符串
	PDexTypeId		typeIds;			// 类型
	PDexProtoId		protoIds;			// 声明
	PDexFieldId		fieldIds;			// 字段
	PDexMethodId	methodIds;			// 方法
	PDexClassDef	classDefs;			// 类
	PDexData		data;				// 数据
	PDexLink		linkData;			// 静态链接数据区,对于未优化的 Dex 文件始终为空

public:
	DexFile(char* file);

	void parseAllClass();
private:
	std::string parseStringId(u4 index);
	std::string parseTypeId(u4 index);
	std::string parseProtoId(u4 index);
	std::string parseFieldId(u4 index);
	std::string parseMethodId(u4 index);
	std::string parseClassDef(u4 index);

	std::string parseDataTypeList(PDexTypeList);
	std::string parseClassData(PDexClassData);
private:
	/*
	 * MUTF8 转换成 ASCII
	 */
	inline char* MUTF8ToASCII(char *stream)
	{
		char* ptr = stream + 1;
		return ptr;
	}

	/*
	 * int to string
	 */
	std::string IntToString(int num);
	int uleb128ToInt(u1**);
	int sleb128ToInt(u1**);
};


dex.cpp
/*
 * 解析 Dex 文件
 */

#include "dex.h"
#include <sstream>
#include <string>
#include <iostream>

void DexFile::parseAllClass()
{
	for (u4 i = 0; i < dexHeader->classDefsSize; ++i)
	{
		std::cout << parseClassDef(i) << std::endl;
		std::cout << std::endl;
	}
}

DexFile::DexFile(char* file)
{
	// dex 头
	dexHeader = reinterpret_cast<PDexHeader>(file);
	if (dexHeader == nullptr)
	{
		return;
	}
	else
	{
		// 字符串
		if (dexHeader->stringIdsOff != 0)
		{
			stringIds = reinterpret_cast<PDexStringId>((dexHeader->stringIdsOff) + reinterpret_cast<char*>(dexHeader));
		}
		else
		{
			stringIds = nullptr;
		}

		// 类型
		if (dexHeader->typedeIdsOff == 0)
		{
			typeIds = nullptr;
		}
		else
		{
			typeIds = reinterpret_cast<PDexTypeId>((dexHeader->typedeIdsOff) + reinterpret_cast<char*>(dexHeader));
		}

		// 声明
		if (dexHeader->protoIdsOff == 0)
		{
			protoIds = nullptr;
		}
		else
		{
			protoIds = reinterpret_cast<PDexProtoId>((dexHeader->protoIdsOff) + reinterpret_cast<char*>(dexHeader));
		}

		// 字段
		if (dexHeader->fieldIdsOff == 0)
		{
			fieldIds = nullptr;
		}
		else
		{
			fieldIds = reinterpret_cast<PDexFieldId>((dexHeader->fieldIdsOff) + reinterpret_cast<char*>(dexHeader));
		}

		// 方法
		if (dexHeader->methodIdsOff == 0)
		{
			methodIds = nullptr;
		}
		else
		{
			methodIds = reinterpret_cast<PDexMethodId>((dexHeader->methodIdsOff) + reinterpret_cast<char*>(dexHeader));
		}

		// 类
		if (dexHeader->classDefsOff == 0)
		{
			classDefs = nullptr;
		}
		else
		{
			classDefs = reinterpret_cast<PDexClassDef>((dexHeader->classDefsOff) + reinterpret_cast<char*>(dexHeader));
		}

		// 数据
		if (dexHeader->dataOff == 0)
		{
			data = nullptr;
		}
		else
		{
			data = reinterpret_cast<PDexData>((dexHeader->dataOff) + reinterpret_cast<char*>(dexHeader));
		}

		// 静态链接数据区
		if (dexHeader->linkOff == 0)
		{
			linkData = nullptr;
		}
		else
		{
			linkData = reinterpret_cast<PDexLink>((dexHeader->linkOff) + reinterpret_cast<char*>(dexHeader));
		}
	}
	return;
}

/* 
 * 根据索引获取字符串
 *	DexStringId 结构体
 *	typedef struct _DexStringId
 *	{
 *		u4	stringDataOff;			// 指向 MUTF-8 字符串的偏移
 *	}DexStringId, *PDexStringId;
 */
std::string DexFile::parseStringId(u4 index)
{
	return std::string(MUTF8ToASCII(reinterpret_cast<char *>(stringIds[index].stringDataOff + reinterpret_cast<char*>(dexHeader))));
}

/*
 * 根据索引获取类型
 * DexTypeId 结构体
 * typedef struct _DexTypeId
 * {
 *		u4	descriptorIdx;		// 指向 DexStringId 列表的索引
 * }DexTypeId, *PDexTypeId;
 */
std::string DexFile::parseTypeId(u4 index)
{
	return parseStringId(typeIds[index].descriptorIdx);
}


/*
 * 根据索引解析方法声明
 * DexProtoId 结构体
 * typedef struct _DexProtoId
 * {
 *		u4	shortyIdx;				// 方法声明字符串,指向 DexStringId 列表的索引,方法声明 = 返回类型+参数列表
 *		u4	returnTypeIdx;			// 方法返回类型字符串,指向 DexStringId 列表的索引
 *		u4	parametersOff;			// 方法的参数列表,指向 DexTypeList 结构的偏移
 * }DexProtoId, *PDexProtoId;
 */
std::string DexFile::parseProtoId(u4 index)
{
	// 方法声明 = 返回类型+参数列表
	std::string funcString = parseStringId(protoIds[index].shortyIdx);

	// 参数
	if (protoIds[index].parametersOff != 0)
	{
		funcString.append(parseDataTypeList(reinterpret_cast<PDexTypeList>((protoIds[index].parametersOff) + reinterpret_cast<char*>(dexHeader))));
	}
	
	// 返回值
	funcString.append(parseTypeId(protoIds[index].returnTypeIdx));

	return funcString;
}


/*
 * 根据索引解析字段
 * DexFieldId 结构体
 * typedef struct _DexFieldId
 * {
 *		u2	classIdx;			// 类的类型,指向 DexTypeId 列表的索引
 *		u2	typeIdx;			// 字段的类型,指向 DexTypeId 列表的索引
 *		u4	nameIdx;			// 字段名,指向 DexStringId 列表的索引
 * }DexFieldId, *PDexFieldId;
 */
std::string DexFile::parseFieldId(u4 index)
{
	std::string  fieldString = parseTypeId(fieldIds[index].classIdx);
	fieldString.append(parseTypeId(fieldIds[index].typeIdx));
	fieldString.append(parseStringId(fieldIds[index].nameIdx));

	return fieldString;
}

/*
 * 根据索引解析方法
 * DexMethodId 结构体
 * typedef struct _DexMethodId
 * {
 *		u2	classIdx;			// 类的类型,指向 DexTypeId 列表的索引
 *		u2	protoIdx;			// 声明的类型,指向 DexProtoId 列表的索引
 *		u4	nameIdx;			// 方法名,指向 DexStringId 列表的索引
 * }DexMethodId, *PDexMethodId;
 */
std::string DexFile::parseMethodId(u4 index)
{
	std::string methodString = parseTypeId(methodIds[index].classIdx);
	methodString.append(parseProtoId(methodIds[index].protoIdx));
	methodString.append(parseStringId(methodIds[index].nameIdx));

	return methodString;
}



/*
 * 根据索引解析类
 * DexClassDef 结构
 * typedef struct _DexClassDef
 * {
 *		u4	classIdx;				// 类的类型,指向 DexTypeId 列表的索引
 *		u4	accessFlags;			// 类的访问标志
 *		u4	superclassIdx;			// 父类类型索引值,指向 DexTypeId 列表的索引,如果没有父类?
 *		u4	interfacesOff;			// 接口,如果有指向 DexTypeList 结构,否则为0
 *		u4	sourceFileIdx;			// 源文件名,指向 DexStringId 列表的索引
 *		u4	annotationsOff;			// 注解,指向 DexAnnotationsDirectoryItem,或者为0
 *		u4	classDataOff;			// 指向 DexClassData 结构的偏移,类的数据部分
 *		u4	staticValuesOff;		// 指向 DexEncodeArray 结构的偏移,记录了类中的静态数据
 */
std::string DexFile::parseClassDef(u4 index)
{
	std::string classString = "类类型:";
	// 类类型
	classString.append(parseTypeId(classDefs[index].classIdx));
	
	// 类的访问标志

	// 父类
	classString.append("\n父类:");
	classString.append(parseTypeId(classDefs[index].superclassIdx));

	// 接口
	if (classDefs[index].interfacesOff != 0)
	{
		classString.append("\n接口:");
		classString.append(parseDataTypeList(reinterpret_cast<PDexTypeList>((classDefs[index].interfacesOff) + reinterpret_cast<char*>(dexHeader))));
	}

	// 源文件名
	classString.append("\n源文件名:");
	classString.append(parseStringId(classDefs[index].sourceFileIdx));

	// 注解
	// 暂时不处理

	// 类的数据
	if (classDefs[index].classDataOff != 0)
	{
		classString.append(parseClassData(reinterpret_cast<PDexClassData>((classDefs[index].classDataOff) + reinterpret_cast<char*>(dexHeader))));
	}

	// 类的静态数据
	if (classDefs[index].staticValuesOff != 0)
	{
		// do something
	}
	return classString;
}


/*
 * DexClassData 结构体
 * typedef struct _DexClassData
 * {
 *		DexClassDataHeader	header;				// 指定字段与方法的个数
 *		DexField*			staticFields;		// 静态字段
 *		DexField*			instanceFields;		// 实例字段
 *		DexMethod*			directMethods;		// 直接方法
 *		DexMethod*			virtualMethods;		// 虚方法
 * }DexClassData, *PDexClassData;
 *
 * DexClassDataHeader 结构体
 * typedef struct _DexClassDataHeader
 * {
 *		uleb128	staticFieldsSize;		// 静态字段个数
 *		uleb128	instanceFieldsSize;		// 实例字段个数
 *		uleb128	directMethodsSize;		// 直接方法个数
 *		uleb128	virtualMethodsSize;		// 虚方法个数
 * }DexClassDataHeader, *PDexClassDataHeader;
 */
std::string DexFile::parseClassData(PDexClassData classData)
{
	u1* ptr = reinterpret_cast<u1*>(classData);
	std::string str = "";

	u4 staticFieldsSize = uleb128ToInt(&ptr);
	u4 instanceFieldsSize = uleb128ToInt(&ptr);
	u4 directMethodsSize = uleb128ToInt(&ptr);
	u4 virtualMethodsSize = uleb128ToInt(&ptr);

	// 静态字段
	if (staticFieldsSize != 0)
	{
		str.append("\n静态字段个数:");
		str.append(IntToString(staticFieldsSize));

		// 解析 DexField
		for (u4 i = 0; i < staticFieldsSize; ++i)
		{
			str.append("\n静态字段:");
			str.append(parseFieldId(uleb128ToInt(&ptr)));
			str.append("\n访问标志:");
			str.append(IntToString(uleb128ToInt(&ptr)));
		}
	}

	// 实例字段
	if (instanceFieldsSize != 0)
	{
		str.append("\n实例字段个数:");
		str.append(IntToString(instanceFieldsSize));

		// 解析 DexField
		for (u4 i = 0; i < instanceFieldsSize; ++i)
		{
			str.append("\n实例字段:");
			str.append(parseFieldId(uleb128ToInt(&ptr)));
			str.append("\n访问标志");
			str.append(IntToString(uleb128ToInt(&ptr)));
		}
	}

	// 直接方法
	if (directMethodsSize != 0)
	{
		str.append("\n直接方法个数:");
		str.append(IntToString(directMethodsSize));

		// 解析 DexMethod
		for (u4 i = 0; i < directMethodsSize; ++i)
		{
			str.append("\n直接方法:");
			str.append(parseMethodId(uleb128ToInt(&ptr)));
			str.append("\n访问标志:");
			str.append(IntToString(uleb128ToInt(&ptr)));
			str.append("\nDexCode的偏移:");
			str.append(IntToString(uleb128ToInt(&ptr)));
		}
	}

	// 虚方法
	if (virtualMethodsSize != 0)
	{
		str.append("\n虚方法个数:");
		str.append(IntToString(virtualMethodsSize));

		// 解析 DexMethod
		for (u4 i = 0; i < virtualMethodsSize; ++i)
		{
			str.append("\n虚方法:");
			str.append(parseMethodId(uleb128ToInt(&ptr)));
			str.append("\n访问标志:");
			str.append(IntToString(uleb128ToInt(&ptr)));
			str.append("\nDexCode的偏移:");
			str.append(IntToString(uleb128ToInt(&ptr)));
		}
	}

	return str;
}


/************************************************
* DexTypeList 结构体
* typedef struct _DexTypeList
* {
*		u4	size;				// 接下来 DexTypeItem 的个数
*		PDexTypeItem	list;	// DexTypeItem 结构
* }DexTypeList, *PDexTypeList;
*
* DexTypeItem 结构体
* typedef struct _DexTypeItem
* {
*		u2	typeIdx;			// 指向 DexTypeId 列表的索引
* }DexTypeItem, *PDexTypeItem;
************************************************/
std::string DexFile::parseDataTypeList(PDexTypeList typeList)
{
	std::string str = "";
	PDexTypeItem ptr = reinterpret_cast<PDexTypeItem>((reinterpret_cast<char*>(typeList)) + sizeof(u4));
	for (u4 i = 0; i < typeList->size; ++i)
	{
		str.append(parseTypeId(ptr[i].typeIdx));
	}

	return str;
}



int DexFile::uleb128ToInt(u1** pStream) 
{
	u1* ptr = *pStream;
	int result = *(ptr++);

	if (result > 0x7f) {
		int cur = *(ptr++);
		result = (result & 0x7f) | ((cur & 0x7f) << 7);
		if (cur > 0x7f) {
			cur = *(ptr++);
			result |= (cur & 0x7f) << 14;
			if (cur > 0x7f) {
				cur = *(ptr++);
				result |= (cur & 0x7f) << 21;
				if (cur > 0x7f) {
					/*
					* Note: We don't check to see if cur is out of
					* range here, meaning we tolerate garbage in the
					* high four-order bits.
					*/
					cur = *(ptr++);
					result |= cur << 28;
				}
			}
		}
	}
	*pStream = ptr;
	return result;
}

int DexFile::sleb128ToInt(u1** pStream) 
{
	u1* ptr = *pStream;
	int result = *(ptr++);

	if (result <= 0x7f) {
		result = (result << 25) >> 25;
	}
	else {
		int cur = *(ptr++);
		result = (result & 0x7f) | ((cur & 0x7f) << 7);
		if (cur <= 0x7f) {
			result = (result << 18) >> 18;
		}
		else {
			cur = *(ptr++);
			result |= (cur & 0x7f) << 14;
			if (cur <= 0x7f) {
				result = (result << 11) >> 11;
			}
			else {
				cur = *(ptr++);
				result |= (cur & 0x7f) << 21;
				if (cur <= 0x7f) {
					result = (result << 4) >> 4;
				}
				else {
					/*
					* Note: We don't check to see if cur is out of
					* range here, meaning we tolerate garbage in the
					* high four-order bits.
					*/
					cur = *(ptr++);
					result |= cur << 28;
				}
			}
		}
	}
	*pStream = ptr;
	return result;
}


std::string DexFile::IntToString(int num)
{
	std::stringstream strStream;
	std::string	str;
	strStream << num;
	strStream >> str;
	return str;
}















  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值