一、Jimple总述
jimple是一种中间代码
1.jimple设计的目的:
用来简化分析,以及简化向java字节码的过渡。
2.不同中间代码之间的转化图。
(下图有些旧,但思想很好。)
(1)与java代码相关:
- 图中可以看出,我们可以进行编译以及反编译。【针对java】
- 我们可以将java通过一种编译方式(javac),将其转换为 .class文件。【针对java】
- 对于java并不一定要有一种编译方式,比如说,可以将java编译成Gimp。
(2)与Soot中间代码相关:
- 【soot擅长的中间代码】 Baf,Gimp,Jimple(soot最擅长处理jimple)。
- 所以通过Jimple中间代码的形式来让soot进行处理是个不错的选择。
- 【Gimp】一旦通过java编译方式到Gimp格式,接下来就由Soot来控制了,进入了soot控制的世界了。
- 【Baf】通过 .class文件也可以经过转换进入Baf格式,又进入soot的世界了。
- 任何一种中间代码形式都可以进行输出。
- java,或者.class文件,经过转化后,变为soot可以处理的形式,然后读者就可以在soot中进行分析 或者优化了。
配图:
摘自:《Jimple : Simplifying Java Bytecode for Analyses and Transformations》(1998)
再配上一张最新的官方图:
摘自: soot生存手册
二、jimple特点
- 有类型的
- 3地址的
- 基于语句的
有类型的
在java中是有类型的,当我们定义一个变量的时候,是需要声明其类型的。
(反例是:javascript,在运行的时候才能确定其类型)
int i;
将上面代码转化为jimple之后,类型依旧保留,并没有丢失。
int i;
三地址
java代码:
int i ,j;
i = 2;
j = 2*i + 8;
Jimple中间代码:
- 可以看出在3地址表示中出现了很多临时变量temp.
- 将上面的java代码拆解的十分细致。
- 赋值需要借助于临时变量。
- 3地址,这一特点使得java代码中很多高级的特性,被分解成很多细小的单位。
- 一般而言,三地址代码将包含大部分低级操作,即目标机所支持的指令。
- 关于3地址的一些简答介绍(中间代码)
int i, j, temp$0, temp$1, temp$2, temp$3;
temp$0 = 2;
i = temp$0;
temp$1 = 2 * i;
temp$2 = temp$1;
temp$3 = temp$2 + 8;
j = temp$3;
基于语句的
根据下面对于jimple语句介绍(第三节)就能发现其基于语句的特性。
1. 基于语句说明jimple中代码,基本组成单位,抽象程度还是比较高的。【java字节码等相比】
2. jimple一条语句能够封装进java字节码中很多的指令。
三、Jimple中的语句
Jimple的一些基本语法
摘自《Jimple : Simplifying Java Bytecode for Analyses and Transformations》(1998)
Soot对于jimple中语句的对象化
soot在简化语句方面的作用,java字节码规定的操作语句是十分复杂的,这对于语句的分析而言,无疑会造成一定的复杂性。中间的jimple的引入了,将一些复杂的细节进行了屏蔽,从而有利于在此基础上进行分析。(jimple有15种语句(简化))
soot中Jimple语句类型
- 负责过程内控制流的语句:IfStmt , GotoStmt , TableSwitchStmt , LookupSwitchStmt
- 负责过程间的控制流语句:InvokeStmt , ReturnStmt , ReturnVoidStmt.
- 监控语句:EnterMonitorStmt , ExitMonitorStmt.
- ThrowStmt , RetStmt
摘自:soot生存手册
stmt语句
stmt继承自Unit , 是jimple语句的一个基础,体现了jimple语句的一些基本特征。
用途:在进行数据流分析的时候,需要模拟stmt的执行,这时候就会用到这些提到下面的这些特征。
stmt是位于方法体(SootMethod)中的,而SootMethod又位于一定的类(SootClass)中的。 —-> 这里想说的是,Stmt操作的不仅有SootMethod中的内容(局部变量等),同时又可以操作SootClass中的一些内容。见下面的代码:
- 【引用】是否有成员变量的引用。 (containsFieldRef () )
public interface Stmt extends Unit
{
public void toString(UnitPrinter up);
public boolean containsInvokeExpr();//是否包含函数调用
public InvokeExpr getInvokeExpr();
public ValueBox getInvokeExprBox();
public boolean containsArrayRef();//是否含有数组引用
public ArrayRef getArrayRef();
public ValueBox getArrayRefBox();
public boolean containsFieldRef();//是否使用了【类】的成员变量
public FieldRef getFieldRef();
public ValueBox getFieldRefBox();
}
而我们查看Unit,会发现:
- 【使用】哪些变量,值被使用。
- 【定义】哪些变量被定义。
- 【关联】与其他Unit有何关联。
- 【分支】是否是分支结构。
- fallsThrough 暂时不知道 …
待续…