smali文件解析

来源:互联网 发布:最新通达信软件 编辑:程序博客网 时间:2024/06/05 03:10
Smali,Baksmali分别是指安卓系统里的Java虚拟机(Dalvik)所使用的一种.dex格式文件的汇编器,反汇编器。
其语法是一种宽松式的Jasmin/dedexer语法,而且它实现了.dex格式所有功能(注解,调试信息,线路信息等)。

Android平台上使用了google自己的Dalvik虚拟机,这种虚拟机直接执行的并非Java字节码,
而是另一种字节码:dex格式的字节码。
Android应用开发所使用的编程语言是Java语言,
和Java SE一样,编译时使用Sun JDK将Java源程序编程成标准的Java字节码文件(.class文件)。
而后通过Android平台上的工具(dx)可以将Java字节码(.class文件)转换成Dex字节码(classes.dex)。
最后使用Android打包工具(aapt)将DEX文件,资源文件以及AndroidManifest.xml文件(二进制格式)组合成一个应用程序包(APK)。
Dex文件的指令码就是Dalvik虚拟机专有的一套指令集,专门为嵌入式系统优化过,相比标准java的.class文件,它体积小,运行效率高。
Smali是dalvik所使用的字节码文件.dex的汇编器。
通过反汇编器Baksmali可以由.dex文件得到.smali文件。
Smali文件是dalvik虚拟机运行的dex字节码文件对应的汇编文件。
1、smali-1.2.6.jar(dex 打包工具)
用途:.smali文件 转成 classes.dex文件
说明:.smali文件,类似于.class文件,dex是dalvik直接执行的字节码文件。
用法: java -jar smali.jar classout/ -o classes.dex
2、baksmali-1.2.6.jar(dex 解包工具)
用途:classes.dex文件 转成 .smali文件
说明:smali文件是classes.dex的汇编文件,由dalvik专有的基于寄存器的指令组成。
用法:java -jar baksmali.jar -o classout/ classes.dex

Dalvik和标准Java虚拟机(JVM)之间的首要差别之一,就是Dalvik基于寄存器,而JVM基于栈。
dalvik opcode 语法:
http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html
官网:
https://code.google.com/p/smali/wiki/TypesMethodsAndFields
类型
dalvik字节码分为两个主要类型:基本类型和引用类型。对象和数组是引用类型,其余都是基本类型。
基本类型用一个单独的字母表示:
类型图片
对象的表示方式为:Lpackage/name/ObjectName;
开头的L表示这是个对象类型;
package/name是对象所在的包名;
ObjectName是对象的名字;
;标明对象名字的结束;
这与java中的package.name.ObjectName是等价的。举个具体的例子:Ljava/lang/String; 等价于 java.lang.String.
数组的表示形式为:[objectType
[I表示一维int数组。例如,java中的int[].多维数组只需要增加[字符的个数.例如,[[I=int[][];[[[I=int[][][].数组的最多维数为255.
同样可以表示对象数组,[Ljava/lang/String;表示一维String数组;

方法
方法的表示方式很复杂,包括:方法所在的类型,方法名,参数类型,和返回值类型。
虚拟机需要这些信息来找到正确的方法,并对字节码进行静态分析(出于验证/优化的目的).
方法的表示形式:
Lpackage/name/ObjectName;->MethodName(III)Z
在这个例子中,你应该认出Lpackage/name/ObjectName;是对象类型(包含该方法的对象)。
MethodName 很明显是方法的名字;(III)Z是方法的签名,III是参数(这个例子中,是3个int类型),Z是返回类型(bool).
方法参数一个接一个按顺序列出来,中间没有分隔符。
一个比较复杂的例子:
method(I[[IILjava/lang/String;[Ljava/lang/Object;)Ljava/lang/String;
java中的对应方法是:
String method(int, int[][], int, String, Object[])


域也有一个复杂的表示形式,包括:域所在的对象类型,域名,域的类型。
同样的,这些信息是为了使虚拟机能够找到合适的域,并对字节码进行镜头分析。
域的表示形式:
Lpackage/name/ObjectName;->FieldName:Ljava/lang/String;
这个形式是自解释的---分别是包名,域名,域的类型。

smali文件中的函数
smali文件中的每条指令都是通过寄存器完成的。函数中使用的寄存器总数会再函数一开始就明确指定。
指定寄存器个数的语法:
   .locals n
方法的参数也要放在函数的寄存器中,并且是放在最后几个寄存器中。
寄存器有两种命名方案:标准的V命名方案和对于参数寄存器的P命名方案。
比如一个动态函数指定用到6个寄存器,它有两个参数。那么放函数参数的寄存器如果采用标准命名方案就是v4,v5.
参与参数寄存器的p命名方案就是p1,p2.
v4,v5,和p1,p2不过是同一个寄存器的两种叫法。
动态函数的p0永远指向调用该函数的对象的this指针。
静态函数没有this指针,p0指向函数的第一个参数。
默认baksmali对于参数寄存器使用p命名模式来命名。
smali文件中用到的指令在http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html中都可以查到。
原创粉丝点击