[英]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.