大家好,又见面了,我是你们的朋友全栈君。
Android 4.0
源码Dalvik/docs
目录下文档dex-format.html
有详细介绍dex文件格式
dex文件使用到的数据类型
Android
源码dalvik\libdex\Leb128.h
文件中可以找到LEB128的实现,读取无符号LEB128(uleb128)数据的代码:
DEX_INLINE int readUnsignedLeb128(const ul** pStream){
const ul* ptr=*pStream;
int result=*(ptr++);
if(result>0x7f){ //大于0x7f表示第1个字节最高位为1
int cur=*(ptr++); //第2个字节
result=(result&0x7f)|((cur&0x7f)<<7);//前2个字节组合
if(cur>0x7f){ //大于0x7f表示第2个字节最高位为1
cur=*(ptr++); //第3个字节
result|=(cur&0x7f)<<14; //前3个字节的组合
if(cur>0x7f){
cur=*(ptr++); //第4个字节
result|=(cur&0x7f)<<21;//前4个字节的组合
if(cur>0x7f){
cur=*(ptr++); //第5个字节
result|=cur<<28;//前5个字节的组合
}
}
}
}
*pStream=ptr;
return result;
}
对于有符号的LEB128(sleb128)来说,计算方法与无符号的LEB128是一样的,只是对无符号LEB128最后一个字节的最高有效位进行了符号扩展。读取有符号LEB128数据的代码如下:
DEX_INLINE int readSignedLeb128(const ul** pStream){
const ul* ptr=*pStream;
int result=*(ptr++);
if(result<=0x7f){ //小于0x7f表示第1个字节的最高位不为1
result=(result<<25)>>25; //对第1个字节的最高有效位进行符号扩展
}else{
int cur=*(ptr++); //第2个字节
result=(result&0x7f)|((cur&0x7f)<<7);//前2个字节组合
if(cur<=0x7f){
result=(result<<18)>>18;//对结果进行符号位扩展
}else{
cur=*(ptr++); //第3个字节
result|=(cur&0x7f)<<14; //前3个字节的组合
if(cur<=0x7f){
result=(result<<11)>>11;//对结果进行符号位扩展
}else{
cur=*(ptr++); //第4个字节
result|=(cur&0x7f)<<21;//前4个字节的组合
if(cur<=0x7f){
result=(result<<4)>>4;//对结果进行符号位扩展
}else{
cur=*(ptr++); //第5个字节
result|=cur<<28;//前5个字节的组合
}
}
}
}
*pStream=ptr;
return result;
}
uleb128p1类型很简单,值为uleb128的值加1。
c0 83 92 25
计算uleb128值:
第1个字节0xc0大于0x7f,表示需要用到第2个字节。result=0xc0&0x7f
第2个字节0x83大于0x7f,表示需要用到第3个字节。result2 = result1 + (0x83 & 0x7f) << 7
第3个字节0x92大于0x7f,表示需要用到第4个字节。result3 = result2 + (0x92 & 0x7f) << 14
第4个字节0x25小于0x7f,表示到了结尾。result4 = result3 + (0x25 & 0x7f) << 21
最后计算结果为0x40 + 0x180 + 0x48000 + 0x4a00000 = 0x4a481c0
dex文件由多个结构体组合而成。
– dex header:dex文件头,它指定了dex文件的一些属性,并记录了其它6部分数据结构在dex文件中的物理偏移 – string_ids到class_def结构为“索引结构区”,真实的数据存放在data数据区 – link_data:静态链接数据区
未经过优化的dex文件结构:
struct DexFile{
DexHeader Header;
DexStringId StringIds[stringIdsSize];
DexTypeId TypeIds[typeIdsSzie];
DexProtoId ProtoIds[protoIdsSize];
DexFieldId FieldIds[fieldIdsSize];
DexMethodId MethodIds[methodIdsSize];
DexData Data[];
DexLink LinkData;
};
(DexFile结构的声明在Android系统源码dalvik\libdex\DexFile.h
文件中的,是dex文件被映射到内存中的结构,保存的是各个结构的指针,其中还包括了DexOptHeader与DexFile尾部的附加数据)
Dalvik虚拟机解析dex文件的内容,最终将其映射成DexMapList数据结构。
struct DexMapList{
u4 size; //DexMapItem的个数
DexMapItem list[1]; //DexMapItem结构
};
//size字段表示接下来有多少个DexMapItem结构
//DexMapItem的结构如下:
struct DexMapItem{
u2 type; //kDexType开头的类型
u2 unused; //未使用,用于字节对齐
u4 size; //指定类型的个数
u4 offset; //指令类型数据的文件偏移
};
type字段为一个枚举常量,通过类型名称很容易判断具体类型:
分析整体结构:
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/153503.html原文链接:https://javaforall.cn