Soot学习笔记(2)
来源:互联网 发布:node.js用什么软件 编辑:程序博客网 时间:2024/05/18 17:00
通过soot来分析一个java classfile 对于Sable官网的介绍的文档,我们将使用soot flow analysis framework
学习这个例子的目地在于:
1. how to inspect a class file by using Soot, and // 怎么样去用soot去检测一个class文件
2. how to profile a program by instrumenting the class file. //通过instrumenting class file to 剖析你的程序
任务:计算我们到底进行了多少次静态调用
1.Testinvoke 类 ,该类是我们要进行分析的类的sourcecode。
class TestInvoke {private static int calls = 0;public static void main(String[] args) {for (int i = 0; i < 10; i++) {foo();}System.out.println("I made " + calls + " static calls");}private static void foo() {calls++;bar();}private static void bar() {calls++;}}
为了计算我们到底进行了多少次静态调用,我们需要一个辅助类MyCounter
/* The counter class */public class MyCounter {/* the counter, initialize to zero */private static int c = 0;/** * increases the counter by * * <pre> * howmany * </pre> * * @param howmany * , the increment of the counter. */public static synchronized void increase(int howmany) {c += howmany;}/** * reports the counter content. */public static synchronized void report() {System.err.println("counter : " + c);}}
接下来我们要创建一个wrapper class(封装类)通过加入一个phrase 进入soot来完成我们的任务:剖析TestInvoke需要进行多少staticInvoke?然后在再执行运行soot(通过soot.Main.main()).
wrapper class: MainDriver:
import soot.*;/* import necessary soot packages */public class MainDriver {/** * 这里放入: TestInvoke.java * @param args */ public static void main(String[] args) { /* check the arguments */ if (args.length == 0){ System.err.println("Usage: java MainDriver [options] classname"); System.exit(0); } /* add a phase to transformer pack by call Pack.add */ Pack jtp = PackManager.v().getPack("jtp"); jtp.add(new Transform("jtp.instrumanter", new InvokeStaticInstrumenter())); /* Give control to Soot to process all options, * InvokeStaticInstrumenter.internalTransform will get called. */ soot.Main.main(args); }}我们要如何去统计TestInvoke中staticInvoke调用了多少次呢,我们就要在它每次staticInvoke之前先放入一个类似计数器的语句来统计staticInvoke的运行次数,这个任务就需要InvokeStaticInstrumanters
import soot.*;import soot.jimple.*;import soot.toolkits.graph.ExceptionalUnitGraph;import soot.toolkits.graph.UnitGraph;import soot.util.*;import java.util.*;/** * InvokeStaticInstrumenter inserts count instructions before INVOKESTATIC * bytecode in a program. The instrumented program will report how many static * invocations happen in a run. * * Goal: Insert counter instruction before static invocation instruction. Report * counters before program’s normal exit point. Approach: 1. Create a counter * class which has a counter field, and a reporting method. 2. Take each method * body, go through each instruction, and insert count instructions before * INVOKESTATIC. 3. Make a call of reporting method of the counter class. * * Things to learn from this example: 1. How to use Soot to examine a Java * class. 2. How to insert profiling instructions in a class. * InvokeStaticInstrumenter extends the abstract class BodyTransformer, and * implements * * <pre> * internalTransform * </pre> * * method. */public class InvokeStaticInstrumenter extends BodyTransformer {/* some internal fields */static SootClass counterClass;static SootMethod increaseCounter, reportCounter; //在soot中注册我们的辅助类static {counterClass = Scene.v().loadClassAndSupport("MyCounter");increaseCounter = counterClass.getMethod("void increase(int)");reportCounter = counterClass.getMethod("void report()");}/** internalTransform goes through a method body and inserts * counter instructions before an INVOKESTATIC instruction */@Overrideprotected void internalTransform(Body body, String arg1, Map arg2) { // 得到该方法SootMethod method = body.getMethod();// 调试System.out.println("instrumenting method : " + method.getSignature());System.out.println("MethodName: " + method.getName());// 得到该方法的UnitChainChain units = body.getUnits();//当遍历它的时候,改变它的语句链Iterator stmtIt = units.snapshotIterator(); // 遍历每一条语句while (stmtIt.hasNext()) {// 得到statementStmt stmt = (Stmt) stmtIt.next();if (!stmt.containsInvokeExpr()) {continue;}// take out the invoke expressionInvokeExpr expr = (InvokeExpr) stmt.getInvokeExpr();// 跳过 non-static invocationsif (!(expr instanceof StaticInvokeExpr)) {continue;}// now we reach the real instruction// call Chain.insertBefore() to insert instructions//插入一条Expr,调用我们构造的辅助类的方法,参数为1(显然)InvokeExpr incExpr = Jimple.v().newStaticInvokeExpr(increaseCounter.makeRef(), IntConstant.v(1));Stmt incStmt = Jimple.v().newInvokeStmt(incExpr);// 3. insert new statement into the chain //we are mutating the unit chain)units.insertBefore(incStmt, stmt);}//最后,我们要插入一条语句来输出最后的结果//判断当前是不是main方法String signature = method.getSubSignature();boolean isMain = signature.equals("void main(java.lang.String[])");if (isMain) {stmtIt = units.snapshotIterator();while (stmtIt.hasNext()) {Stmt stmt = (Stmt) stmtIt.next(); // check if the instruction is a return with/without valueif ((stmt instanceof ReturnStmt)|| (stmt instanceof ReturnVoidStmt)) {// 2. then, make a invoke statementInvokeExpr reportExpr = Jimple.v().newStaticInvokeExpr(reportCounter.makeRef());// 3. insert new statement into the chainStmt reportStmt = Jimple.v().newInvokeStmt(reportExpr);units.insertBefore(reportStmt, stmt);}}}}}
下面是
改变后的TestInvoke.class改变后的截图:
6 invokestatic MyCounter.increase(int) : void [36]
50 invokestatic MyCounter.report() : void [17]
可以看到 6,50行的变化~我们插入了我们需要的expr
0 0
- Soot学习笔记(2)
- Soot 学习笔记 2:使用 Eclipse 插件
- Soot学习笔记(1)
- soot 学习笔记 一
- soot 学习笔记 三
- soot 学习笔记 二
- soot 学习笔记 四
- soot学习笔记(一)
- 学习Soot - 2
- [Soot学习笔记][5]Soot依赖的两个框架
- Soot 学习笔记 1:First Step 命令行执行 soot
- Soot 学习笔记 4:Soot 的 pack 和 phase
- Soot 学习笔记 5:使用 Soot 创建 Java class
- Soot 学习笔记 6:一些 Soot 重要的类
- soot学习笔记-2.使用soot解析Android apk.
- Soot学习笔记3.使用soot解析java文件
- Soot 学习笔记 8:More on profiling
- [Soot学习笔记][7]Soot Instrument教程学习(More on profiling)
- mysql触发器
- eclipse hibernate 插件
- 关于Ranorex对象库的使用感受(基于安卓)
- HDOJ 4336 Card Collector (状态压缩DP)
- 第一次来
- Soot学习笔记(2)
- 教你如何快速集成第3方
- 接口测试学习笔记
- COCOS2D-X 换肤
- web app和Native App知识
- Why Custom InfoWindow of google map v2 ,Not load url Image?
- 水晶报表-已达到系统管理员配置的最大报表处理作业数限制
- MTK 安卓支持语种
- 初志科技面试总结