Soot对象基础(Fundamental Soot Object)

来源:互联网 发布:ios小游戏源码 编辑:程序博客网 时间:2024/06/01 19:16

Soot对象基础(Fundamental Soot Object)

    Soot有着庞大而复杂的类层次结构。该文档主要给读者介绍一些用于Soot扩展开发中使用的最重要的类。

关于Body类

在教程:Createing a class from scratch中,Body的概念被简要的介绍过。本节将对Body做详细的描述。

Soot使用Body来存储一个方法的代码。在Soot中,有四种不同的Body实现,分别为:BafBody,JimpleBody,ShimpleBody和GrimpBody,每一种都是一种中间表示。

另外,回顾下,一个chain是类似list的数据结构,它提供了常量时间(O(1))的对chain中元素的访问,包括插入与移除。

在Body中三个主要的chain是Units Chain,Locals Chain和Traps Chain。接下来的例子给出了这些Chain扮演的角色。

查看如下代码

public static void main(String[] argv) throws Exception

{

int x = 2, y = 6;

 

System.out.println("Hi!");

System.out.println(x * y + y);

try

{

int z = y * x;

}

catch (Exception e)

{

throw e;

}

}

 

在Jimple化后,我们可以获取到如下缩略后的Jimple代码。

 

public static void main(java.lang.String[]) throws java.lang.Exception

{

java.lang.String[] r0;

int i0, i1, i2, $i3, $i4;

java.io.PrintStream $r1, $r2;

java.lang.Exception $r3, r4;

 

r0 := @parameter0;

i0 = 2;

i1 = 6;

$r1 = java.lang.System.out;

$r1.println(``Hi!'');

$r2 = java.lang.System.out;

$i3 = i0 * i1;

$i4 = $i3 + i1;

$r2.println($i4);

 

label0:

i2 = i1 * i0;

 

label1:

goto label3;

 

label2:

$r3 := @caughtexception;

r4 = $r3;

throw r4;

 

label3:

return;

 

catch java.lang.Exception from label0 to label1 with label2;

}

Local变量

在该方法中的Locals是在方法的顶部:

java.lang.String[] r0;

int i0, i1, i2, $i3, $i4;

java.io.PrintStream $r1, $r2;

java.lang.Exception $r3, r4;

(备注下:带有$符号的是,Java代码中原来没有的变量)

    Local的集合被存储到LocalChain中,并且可以通过body.getLocals()来访问。每个中间表示可能都定义有自己的Local实现。然而,它必须总是针对每个Local r0,可以调用r0.getName(),r0.getType(),r0.setName()和r0.setType()。注意,local变量必须是带类型的。

Traps

    为了支持Java异常处理,Soot的Body定义了traps的概念。这想法来自Java的字节码,异常处理被表示为一个tuple(元组,异常,开始,结束,处理器);在start和stop 的Units(包括Start但不包括Stop),如果抛出了异常,执行将在handler处继续执行。

示例的trap如下:

catch java.lang.Exception from label0 to label1 with label2;

Units

一个Body中最有趣的部分是Units Chain。这是Body中包含的实际代码。Jimple提供了Unit的Stmt实现,而Grimpe提供了Inst实现。这反应了每个IR都有自己的语句概念。

Jimple Stmt的一个例子是AssignStmt,它表示一个Jimple赋值语句。一个AssignStmt如下:

x = y + z;

Value

代码总是作用在数据上。为了表示数据,Soot提供了Value接口。Value的一些类型包括:

  • Locals(本地变量)
  • Constants(常亮)
  • Expressions(表达式)
  • ParameterRefs(参数引用),CaughtExceptionRef(异常引用)和ThisRefs(This指针引用)

Expr接口,有着各式各样的实现,包括NewExpr和AddExpr。一般来说,一个Expr携带有针对一个或多个Value的操作,并返回另一个Value。

这里是一个使用Value的展示:

x = y + 2;

Boxes

    Boxes在Soot中非常普遍。必须牢记在心的是Box指代的是指针。它提供了对Soot对象的间接访问。

    对Box的更具描述性的称谓是Ref,不幸的是,Ref在Soot中有不同的含义。

    在Soot中有两种不同的Box,即ValueBoxUnitBox。无需惊讶的是,一个UnitBox包含Units,而ValueBox中包含Values。在C++中,这些可以简单的用(Unit *)和(value *)来表示。

现在我们描述Box的各个类型

UnitBox

Unit中的一些类型需要包含其它Unit(s)的引用(Reference)。比如,GotoStmt需要知道它的目标在哪里。因此,Soot提供了UnitBox,一个包含Unit的Box。考虑如下Jimple代码:

x = 5;

goto l2;

y = 3;

l2: z = 9;

 

每个Unit必须提供一getUnitBoxes()方法。对于大多数的UnitBox,这返回一个空list。然而,在GotoStmt的场景下,getUnitBoxes()返回了一个元素的list,包含了执行l2的一个Box。

注意:一个SwitchStmt将,一般返回一个包含许多box的list。

Box的概念对于修改代码非常有用,假设有以下代码:

s: goto l2;

在l2有语句:

l2: goto l3;

 

显然,它可以直接指向l3而不是l2,而不需要理会s的实际类型。我们可以统一的针对所有种类的Unit做处理:

public void readjustJumps(Unit s, Unit oldU, Unit newU)

{

Iterator ubIt = s.getUnitBoxes.iterator();

while (ubIt.hasNext())

{

StmtBox tb = (StmtBox)ubIt.next();

Stmt targ = (Stmt)tb.getUnit();

 

if (targ == oldU)

tb.setUnit(newU);

}

}

 

与这类似的代码在Unit中使用,为了使能PatchingChain,一种Chain的实现,的创建,调整了指针以从Chain中移除Unit(s)。

ValueBox    

    类似于Unit(s),我们需要指向一个Value的指针,这是由ValueBox类来表示的。对一个Unit来说,我们总能获取到一个ValueBox的列表,包含Unit中使用和定义的value。

    我们可以使用这些boxes来进行constant folding:如果一个AssignStmt评估了一个AddExpr添加了2个常量,我们可静态的将其相加,并将结果存入UseBox.

这是一个folding AddExpr的例子:

public void foldAdds(Unit u)

{

Iterator ubIt = u.getUseBoxes().iterator();

while (ubIt.hasNext())

{

ValueBox vb = (ValueBox) ubIt.next();

Value v = vb.getValue();

if (v instanceof AddExpr)

{

AddExpr ae = (AddExpr) v;

Value lo = ae.getOp1(), ro = ae.getOp2();

if (lo instanceof IntConstant && ro instanceof IntConstant)

{

IntConstant l = (IntConstant) lo,

r = (IntConstant) ro;

int sum = l.value + r.value;

vb.setValue(IntConstant.v(sum));

}

}

}

}

 

注意:这对任何Unit都能工作,而不需考虑类型。

Unit温故

    我们现在考虑每个Unit都必须提供不同的方法:

public List getUseBoxes();

public List getDefBoxes();

public List getUseAndDefBoxes();

    

    这些方法返回了针对在Unit中使用的,定义的,以及两者皆有的value的ValueBox的列表。对于getUseBoxes(),所有使用的值被返回;这包含了表达式也包含了它们的组成部分。

 

public List getUnitBoxes();

该方法返回了UnitBox的列表,表示指向的Unit(s)。

 

public List getBoxesPointingToThis();

 

    该方法返回了那些将该Unit视为目标的UnitBox列表。

 

public boolean fallsThrough();

public boolean branches();

    

    这些方法与该Unit的执行流程打交道。前一个方法在执行顺序能够从Unit的下一条语句执行时返回true,而后一条则是当执行可能跳转到其它的某个Unit而不是直接执行紧跟的那条时返回true。

 

public void redirectJumpsToThisTo(Unit newLocation);

 

    该方法使用getBoxesPointToThis来改变使用跳转到该Unit的指针,让它们指向newLocation。(该方法可以在Soot源码中查找到。)

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 练了瑜伽后腰痛怎么办 尿路口长疮疼痛怎么办 来月经吃了辣的怎么办 泳衣打湿后特别难脱怎么办 脚臭怎么办教你除臭方法 袜子没干就穿了进湿气怎么办 狗喜欢往床上跑怎么办 泰迪在床上睡觉怎么办 泰迪睡觉换地方怎么办 猫一定要和人睡怎么办 狗喜欢跳到床上怎么办 幼猫晚上不睡觉怎么办 宝宝不在床上睡觉怎么办呢 瑜伽球表面粘了怎么办 鞋子洗了很臭怎么办 在社区开瑜伽馆怎么办 腿被开水烫伤了怎么办 狗狗的腿脱臼了怎么办 手火辣辣的烧疼怎么办 网贷收到告知函怎么办 收到捷信催收律师函怎么办 快钱贷款不还怎么办 快易花逾期3个月怎么办 欠微粒贷一万多没还找上门了怎么办 装修公司骚扰电话太多了怎么办 总有大便的感觉怎么办 黎明杀机无网络连接怎么办 监控视频电脑播放不了怎么办 绝地手游击倒了怎么办? 绝地求生全军出击倒地后怎么办 黑魂3杀了npc怎么办 菜刀背容易割手怎么办 商铺厨房太热怎么办 农村自建房厨房卫生间怎么办 宾利车门不会开怎么办 两岁的宝宝好动怎么办 被别人坏了名声怎么办 在单位混臭了怎么办 在公司名声臭了怎么办 怀孕三个月吐的厉害怎么办 孕38周轻微贫血怎么办