soot学习历程---(1)


今天看了soot生成手册的部分内容,简单摘录一下

Scene 表示分析所处的完整环境,可以借此设置application class(用sootclass),主类(main),point-to和call graph

SootClass 一个单独的类,被载入soot或用soot产生

SootMethod 指class的一个方法

SootField 指class的一个成员字段

 

Body 中间码,有四种表示

Body表示一个方法体,可以从中获得一系列Collection(soot将其称为Chain),包括本地变量声明getLocals(),构成body的statement即getUnits(),body中处理的exception即getTraps()

 

以下是一段 Java 代码以及其对应的 Jimple 代码:

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;
    }
}

 

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;
    }

在 Jimple 文件的最开始是 Local 的声明,它们存在 localChain 中,可以使用 body.getLocals() 获得。对于一个 local r0,可以对其 r0.getName(), r0.setName(), r0.getType(), r0.setType()。

 

Traps 是为了支持 Java 异常处理,由一个四元组 (exception, start, stop, handler) 来描述,其中范围包含 start 不包含 stop,在这之间的unit如果触发了异常,就跳转到handler。

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

 

Unit 是表示 Body 代码的,Unit 在 Jimple 中的实现是 Stmt,在 Grimp 中的实现是 Inst

通过Unit(Jimple实现为Stmt),可以检索value的使用(getUseBoxes())和定义(getDefBoxes()),或者同时实现(getUseAndDefBoxes())

此外,还可以获得跳转到这个Unit的Unit(getBoxesPointingToThis()),以及这个Unit要跳转去的Unit--(getUnitBoxes()),借此分析控制流

Unit还提供了一些方法查询分支行为,例如fallsThrough() 和 branches()

 

一个单一的datum表示为Value

Value 接口是为了描述 data。Value 主要包括:Local; Constants; Expressions (Expr); ParameterRefs, CaughtExceptionRefs, ThisRefs。Expr 接口既是表达式,它接受若干个 Value 同时返回另一个 Value。例如对于 AssignStmt :

x = y + 2;

y + 2 是 AddExpr,y 是 Local, 2 是Constant。对于 Jimple,强制最多有 1 个expression,Grimp 则没有此限制。

一个表达式具有多种实现,但一般可以认为是在一个或多个值上执行某些操作,并返回另一个值。

 

引用在soot中称作boxes,分为ValueBox and UnitBox,提供对soot对象的间接访问,不理解的话可以当做指针

对于 UnitBox,每个 Unit 必须提供 getUnitBoxes() 方法,当然对于大多数的 Unit 这个方法返回空,但是对于跳转语句,例如 GotoStmt,该方法返回目标的 lable 的 box,而对于 SwitchStmt 则返回很多 Box。Box 的概念对于用 soot 修改代码提供了很大的便利。例如有两条指令

s: goto l2;
  ...
  ...
l2:  goto l3;

显然这里多用了一条指令,可以用如下程序优化

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);
    }
}

 

对于 ValueBox,我们可以取出一个 Unit 的 ValueBox 列表,包含这个 Unit 引用、定值了哪些 Value。我们可以用 box 实现 constant folding:如果一个 AssignStmt 计算一个 AddExpr,把两个常量相加,我们可以静态的计算结果,并把结果放入 UseBox。代码如下:

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 的方法:

public List getUseBoxes();
public List getDefBoxes();
public List getUseAndDefBoxes();
这3个是或得引用定值相关box
public List getUnitBoxes();
这是获得被这个unit 跳转到的 UnitBox 的 List
public List getBoxesPointingToThis();
这是获得该 unit 被作为跳转对象时,所有跳转本身的 UnitBox 
public boolean fallsThrough();
public boolean branches();
对于前一个方法,如果接下来会执行后面挨着的 Unit,则返回 true。后一个方法是,如果运行时会跳转到其他别的 unit,则返回 true。
public void redirectJumpsToThisTo(Unit newLocation);

该方法把所有跳转到该 unit 重定向到 newLocation。

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM