[英]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));
我們可以猜測,這實際上是在說:“如果在sFirstNonId
, sGotoLast
之間的任何thrwCls
引發了thrwCls類型異常,請跳轉至sCatch
的處理程序。
到目前為止,這符合預期。
現在,令我困擾的是
Stmt sCatch = Jimple.v().newIdentityStmt(lException1, Jimple.v().newCaughtExceptionRef());
是一個身份 stmt。
因為身份stmts
是用特殊值(例如參數或this值)定義要預加載(在方法輸入時)的局部變量的語句。
例如,l0:= @this:A將本地l0定義為方法的this。
此標識是必需的,因為未對局部變量進行編號(通常,此變量是字節碼級別的局部變量插槽0中的變量。)
所以-再次以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.