原文链接:点击打开链接
在Soot的反馈邮箱中最常问的一个问题就是在Soot中什么时候运行一个特定的分析。Soot的执行被分割在一组不同的包里(packs),每个包包含不同的阶段(phases)。因此上面这个问题也可以表述为:我应该在哪个包里运行我的分析和转换(transformation)?。这篇文章将帮助你回答这个问题。
Phase options(阶段选项)
Soot支持上百种细粒度的选项,这使得你能够直接通过命令行调整你所需要的分析和优化。
这些命令行选项一般格式为 -p PHASE OPT : VAL。关于所有阶段选项(phase options)的完整文档见点击打开链接。比如说,当我们在Soot里进行分析时我们想保存局部变量的名字(如果可以的话)。那么我们可以添加这个命令行选项 -p jb use-original-names:true。一个更快捷的方式是 -p jb use-original-names,此时true为默认值。
jb: Jimple Body Creation
上面这个图表为Soot里面含有的不同的包。首先,Soot对每一个方法体,或者说对每一个含有方法体的方法应用 jb 包。本地方法比如System.currentTimeMillis()没有方法体(body),jb 包是固定的,它与Jimple表示的创建有关,不能被改变。
Whole-program packs(整个程序范围的包)
接着,Soot应用四个整个程序范围的包
1. cg,调用图包
2. wtjp,whole-jimple 转换包
3. wjop,whole-jimple优化包
4. wjap,whole-jimple注释包
所有的这些包都可以被改变,特别地,可以通过添加 [SceneTransformers](http://www.sable.mcgill.ca/soot/doc/soot/SceneTransformer.html)到这些包中从而进行全程序范围的分析(whole-program analysis)。为了分析和转换程序,SceneTransformer通过[Scene](http://www.sable.mcgill.ca/soot/doc/soot/Scene.html)访问整个程序。下面这个代码段往wjtp包中添加了一个伪转换器(dummy transformer)
public static void main(String[] args) {
PackManager.v().getPack("wjtp").add(
new Transform("wjtp.myTransform", new SceneTransformer() {
protected void internalTransform(String phaseName,
Map options) {
System.err.println(Scene.v().getApplicationClasses());
}
}));
soot.Main.main(args);
}
注意:整个程序范围内的包默认不可用,要使用它们需要在Soot的命令行中声明
-w 选项
Jimple包 jtb,jop,jap
类似于Soot的整个程序范围内的包(whole-program packs),Soot对每个body应用下面三个包:
1. jtp ,jimple转换包
2. jop,jimple优化包
3. jap,jimple注释包
jtp默认是可用且是空的。通常在这里进行过程内分析(intra-procedural analyses)。
jop包包含一套Jimple优化操作。它默认未启用,可以通过Soot的命令行 -o 或者 -p jop enabled 来启用。
jap是Jimple的注释(annotation)包。每个Jimple body里都可以加入注释,这样你或者其他人或JVM便可以评估优化的结果。这个包默认是启用的,但该包中所有的阶段(phases)默认未启用,因此,如果你把你的分析添加到这个包里,默认会自动启用。
下面这段代码启用空指针标签并注册一个新的[BodyTransformer](http://www.sable.mcgill.ca/soot/doc/soot/BodyTransformer.html),用来打印每个方法里每条语句的标签:
public static void main(String[] args) {
PackManager.v().getPack("jap").add(
new Transform("jap.myTransform", new BodyTransformer() {
protected void internalTransform(Body body, String phase, Map options) {
for (Unit u : body.getUnits()) {
System.out.println(u.getTags());
}
}
}));
Options.v().set_verbose(true);
PhaseOptions.v().setPhaseOption("jap.npc", "on");
soot.Main.main(args);
}
注意:每一个添加到非整个程序范围内(non-whole)的Jimple包中的Transform必须是
BodyTransformer。
bb 和 tag包
正如上面的表格描述那样,Soot接下来对每个body应用bb和tag包。bb包将优化并打了标签(optimized anf tagger)的Jimple bodies转换成Baf bodies。Baf是Soot里一种基于栈的中间表示,通过Baf,Soot创建字节码。tag包汇聚特定的标签(aggregates certain tags)。比如说,如果有多条Jimple(或者Baf)语句共享同一个行号标签,那么Soot便只会在第一条含有这个标签的语句上保留这个标签,保证唯一性。
Dava body包 db
Soot中有一个额外的包 db,在上面未标明出来,挡使用 -f java 命令行选项反编译代码转换成Java时,db包被单独使用用来启用或关闭特定的转换。它不包含实际的转换,同时不能往这个包中添加任何东西。
什么时候启用哪个包?
另一个困惑的问题是什么时候启用哪个包,下面这个文档介绍了所有的内容:点击打开链接
这个文档同样描述了每个包中的每个阶段和对应的设置。