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