我在博客上发表一些我的Android学习心得,希望对大家能有帮助。  
这一篇我们讲述一下通过一个实例来分析dex文件结构和组成。
参考Leb128数据类型 Android学习心得(5) --- dex数据类型LEB128 
参考实例分析学习理解dex文件结构Android学习心得(15) --- Dex文件结构解析(1) 
参考baksmali工具使用Android学习心得(4) --- MAC下smali文件编写与运行
我们通过一个例子来分析dex文件的构成
创建一个Hello.java文件,输入下面的值,这个是我们学习的样本
public class Hello {
    public static void main(String[] argc) {
        System.out.println("Hello world");
    }
}通过编译成.class文件之后再编译成.dex文件
 
使用0xED打开进行查看 
我们通过前一张中Dex Header解析 
通过dex文件中前0x70的header数据查询并填入表格
前0x70数据
 
 
在Header中MapOff指向的是MapList结构 
MapList结构第四节中已经定义,我们查询并填写表格
map_off中偏移地址为0x0240,查询相应地址
第一个16位是MapItem的数目:0x000D(14个)
 
首先我们查看MapList中string_id_item,size是14个,从0x70开始 
我们分别从0x176、0x17E等读取出14个字符串,并填入表格
我们查看MapList中type_id_item,个数是7个,从0xA8开始 
由于这个是表示stringids的索引,查string_id_item表得出
查看proto_id_item,个数是3个,从0xC4开始 
通过查看proto_id_item结构,填入表格
我们查看MapList中field_id_item,个数是1个,从0xE8开始 
通过查看field_id_item结构,填入表格
我们查看MapList中method_id_item,个数是4个,从0xF0开始 
通过查看上一节中对method_id_item描述,填入表格
我们查看MapList中class_def_item,个数是1个,从0x110开始 
通过上一节中DexClassDef结构,我们填写表格
我们查看MapList中class_def_item,的确偏移地址和个数都相同。
由于DexClass.h定义的u4是属于Leb128
下面紧跟的是两个直接方法
从0x130开始分析code_item结构
 
 
分析思路整理如下
(1) 《Dalvik VM Instruction Format》 里操作符 op 都是位于首个 16bit 数据的低 8 bit 
起始的是 op = 0x70
(2) 在 《Bytecode for Dalvik VM》 里找到对应的 Syntax 和 format 。
syntax = invoke-direct
format = 0x35c 
(3) 在《Dalvik VM Instruction Format》里查找 35c , 得知 op = 0x70 的指令占据 2 个 16 bit 数据 ,
格式是 B|A|op CCCC G|F|E|D ,其中,B=1,A=0。
我们查询到: [B=1] op {vD}, kind@CCCC
有上述得出CCCC = 3,D = 0;
0E操作码是对应的是return-void
得到指令是:
invoke-direct {v0}, Ljava/lang/Object;.<init>:()V 
return-void
从0x148开始分析code_item结构
 
 
分析思路整理如下
(1) 《Dalvik VM Instruction Format》 里操作符 op 都是位于首个 16bit 数据的低 8 bit 
起始的是 op = 0x62
(2) 在 《Bytecode for Dalvik VM》 里找到对应的 Syntax 和 format 。
syntax = sget-object
format = 0x21c 
(3) 在《Dalvik VM Instruction Format》里查找 21c , 得知 op = 0x62 的指令占据 2 个 16 bit 数据 ,
格式是 AA|op BBBB ,其中,AA=00,BBBB=0。
得到指令是:
sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
继续进行
(1) 《Dalvik VM Instruction Format》 里操作符 op 都是位于首个 16bit 数据的低 8 bit 
起始的是 op = 0x1A
(2) 在 《Bytecode for Dalvik VM》 里找到对应的 Syntax 和 format 。
syntax = const-string vAA, string@BBBB
format = 0x21c 
(3) 在《Dalvik VM Instruction Format》里查找 21c , 得知 op = 0x1A 的指令占据 2 个 16 bit 数据 ,
格式是 onst-string vAA, string@BBBB ,其中,AA=01,BBBB=1。
得到指令是:
const-string v1, "Hello World"
继续进行
(1) 《Dalvik VM Instruction Format》 里操作符 op 都是位于首个 16bit 数据的低 8 bit 
起始的是 op = 0x6E
(2) 在 《Bytecode for Dalvik VM》 里找到对应的 Syntax 和 format 。
syntax = invoke-virtual
format = 0x35c 
(3) 在《Dalvik VM Instruction Format》里查找 21c , 得知 op = 0x6E 的指令占据 2 个 16 bit 数据 ,
格式是 B|A|op CCCC G|F|E|D,其中,B=2, CCCC=2, E=1, D=0。
其格式为:[B=2] op {vD, vE}, kind@CCCC
得到指令是:
invoke-virtual {v0, v1}, Ljava/io/PrintStream; -> println(Ljava/lang/String;)V
return-void
invoke-direct {v0}, Ljava/lang/Object;.<init>:()V 
sget-object v0, Ljava/lang/System;.out:Ljava/io/PrintStream;
const-string v1, "Hello World"
invoke-virtual {v0, v1}, Ljava/io/PrintStream; -> println(Ljava/lang/String;)V
return-void对比baksmali文件生成smali文件
.class public LHello;
.super Ljava/lang/Object;
.source "Hello.java"
# direct methods
.method public constructor <init>()V
    .registers 1
    .prologue
    .line 1
    invoke-direct {p0}, Ljava/lang/Object;-><init>()V
    return-void
.end method
.method public static main([Ljava/lang/String;)V
    .registers 3
    .prologue
    .line 3
    sget-object v0, Ljava/lang/System;->out:Ljava/io/PrintStream;
    const-string v1, "Hello world"
    invoke-virtual {v0, v1}, Ljava/io/PrintStream;->println(Ljava/lang/String;)V
    .line 4
    return-void
.end method
核心代码相同,分析正确。
版权声明:本文为博主原创文章,未经博主允许不得转载。
Android学习心得(16) --- Dex文件结构实例解析(2)
原文:http://blog.csdn.net/qiyu93422/article/details/48027999