簡體   English   中英

異常處理期間的煙灰,身份信息和控制流

[英]soot, identity stmts and the control flow during exception handling

我正在嘗試在soot編寫一個try-catch塊。

讓我們反編譯

public class A {
    public static void main(String[] args) {
        try{
            String a = args[9999];
        }catch(Throwable t){
            t.printStackTrace();
        }
        System.out.println("Hello World");
    }
}

我將在問題末尾添加完整的反編譯。 重要的部分是

     0: aload_0
     1: sipush        9999
     4: aaload
     5: astore_1
     6: goto          14
     9: astore_1
    10: aload_1
    11: invokevirtual #3                  // Method java/lang/Throwable.printStackTrace:()V
    14: getstatic     #4                  // Field java/lang/System.out:Ljava/io/PrintStream;
    17: ldc           #5                  // String Hello World
    19: invokevirtual #6                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
    22: return

  Exception table:
     from    to  target type
         0     6     9   Class java/lang/Throwable

因此,這意味着如果指令0-6中的任何一條拋出異常,控制將被重新路由到9並且執行將像正常情況一樣繼續進行, astore_1對異常對象的引用存儲在本地。變量。

但是,我試圖在soot生成try-catch塊,並且發現了一個實際執行如下操作的示例: CatchWrapInstrumenter.java

根據文檔, newTrap

使用給定的Stmt處理程序為給定的Stmt范圍上的給定異常構造一個新的JTrap

所以當我們看到

b.getTraps().add(Jimple.v().newTrap(thrwCls, sFirstNonId, sGotoLast, sCatch));

我們可以猜測,這實際上是在說:“如果在sFirstNonIdsGotoLast之間的任何thrwCls引發了thrwCls類型異常,請跳轉至sCatch的處理程序。

到目前為止,這符合預期。

現在,令我困擾的是

Stmt sCatch = Jimple.v().newIdentityStmt(lException1, Jimple.v().newCaughtExceptionRef());

是一個身份 stmt。

因為身份stmts

是用特殊值(例如參數或this值)定義要預加載(在方法輸入時)的局部變量的語句。

例如,l0:= @this:A將本地l0定義為方法的this。

此標識是必需的,因為未對局部變量進行編號(通常,此變量是字節碼級別的局部變量插槽0中的變量。)

煙灰紙第31頁[編號23])

所以-再次以class A為例-如果我要生成(簡化)

Sting a;Throwable t;PrintStream out;

a = arg[9990]               //stmt1
goto stmt5                  //stmt2
t := thrownException;       //stmt3
t.printStackTrace();        //stmt4
out = System.out;           //stmt5
out.println("Hello World")  //stmt6

打算注冊

newTrap(exception=java.lang.Throwable, beginStmt=stmt1,endStmt=stmt2,handlerStmt=stmt3)

,就像我將基於反編譯的A.class ,這實際上是非法的,因為應該將t := thrownException預先加載(在方法輸入時)。

但是,與此同時,如果要信任煙灰紙第86頁[編號78]上的示例,這正是我們要做的。

這種“預加載”當時還不存在的概念對我來說意義不大,讓我認為我在控制流程上可能是錯的,盡管我不知道怎么做。

有人可以在這里解釋實際情況嗎?

小try-catch示例的完整反編譯代碼:

public class A
  minor version: 0
  major version: 51
  flags: ACC_PUBLIC, ACC_SUPER
Constant pool:
   #1 = Methodref          #8.#28         // java/lang/Object."<init>":()V
   #2 = Class              #29            // java/lang/Throwable
   #3 = Methodref          #2.#30         // java/lang/Throwable.printStackTrace:()V
   #4 = Fieldref           #31.#32        // java/lang/System.out:Ljava/io/PrintStream;
   #5 = String             #33            // Hello World
   #6 = Methodref          #34.#35        // java/io/PrintStream.println:(Ljava/lang/String;)V
   #7 = Class              #36            // A
   #8 = Class              #37            // java/lang/Object
   #9 = Utf8               <init>
  #10 = Utf8               ()V
  #11 = Utf8               Code
  #12 = Utf8               LineNumberTable
  #13 = Utf8               LocalVariableTable
  #14 = Utf8               this
  #15 = Utf8               LA;
  #16 = Utf8               main
  #17 = Utf8               ([Ljava/lang/String;)V
  #18 = Utf8               a
  #19 = Utf8               Ljava/lang/String;
  #20 = Utf8               t
  #21 = Utf8               Ljava/lang/Throwable;
  #22 = Utf8               args
  #23 = Utf8               [Ljava/lang/String;
  #24 = Utf8               StackMapTable
  #25 = Class              #29            // java/lang/Throwable
  #26 = Utf8               SourceFile
  #27 = Utf8               A.java
  #28 = NameAndType        #9:#10         // "<init>":()V
  #29 = Utf8               java/lang/Throwable
  #30 = NameAndType        #38:#10        // printStackTrace:()V
  #31 = Class              #39            // java/lang/System
  #32 = NameAndType        #40:#41        // out:Ljava/io/PrintStream;
  #33 = Utf8               Hello World
  #34 = Class              #42            // java/io/PrintStream
  #35 = NameAndType        #43:#44        // println:(Ljava/lang/String;)V
  #36 = Utf8               A
  #37 = Utf8               java/lang/Object
  #38 = Utf8               printStackTrace
  #39 = Utf8               java/lang/System
  #40 = Utf8               out
  #41 = Utf8               Ljava/io/PrintStream;
  #42 = Utf8               java/io/PrintStream
  #43 = Utf8               println
  #44 = Utf8               (Ljava/lang/String;)V
{
  public A();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: aload_0
         1: invokespecial #1                  // Method java/lang/Object."<init>":()V
         4: return
      LineNumberTable:
        line 1: 0
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       5     0  this   LA;

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V
    flags: ACC_PUBLIC, ACC_STATIC
    Code:
      stack=2, locals=2, args_size=1
         0: aload_0
         1: sipush        9999
         4: aaload
         5: astore_1
         6: goto          14
         9: astore_1
        10: aload_1
        11: invokevirtual #3                  // Method java/lang/Throwable.printStackTrace:()V
        14: getstatic     #4                  // Field java/lang/System.out:Ljava/io/PrintStream;
        17: ldc           #5                  // String Hello World
        19: invokevirtual #6                  // Method java/io/PrintStream.println:(Ljava/lang/String;)V
        22: return
      Exception table:
         from    to  target type
             0     6     9   Class java/lang/Throwable
      LineNumberTable:
        line 4: 0
        line 7: 6
        line 5: 9
        line 6: 10
        line 8: 14
        line 9: 22
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            6       0     1     a   Ljava/lang/String;
           10       4     1     t   Ljava/lang/Throwable;
            0      23     0  args   [Ljava/lang/String;
      StackMapTable: number_of_entries = 2
        frame_type = 73 /* same_locals_1_stack_item */
          stack = [ class java/lang/Throwable ]
        frame_type = 4 /* same */
}
SourceFile: "A.java"

我認為您對IdentityStmts的概念有誤解。 不同的IdentityStmts的共同點在於,它們分配的值“從天而降”。 在方法入口處,這些是參數和“ this”,在異常處理程序中,它們是引發的異常。 換句話說,這完全沒問題,並且期望在處理程序開始的位置的方法體內具有一個帶有異常引用的IdentityStmt。 Soot唯一的假設是,如果一條語句是Trap的目標,即該處理程序的開始,那么該處理程序中的第一條語句應該是一個帶有適當異常引用的IdentityStmt。

我希望這回答了你的問題。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM