好久沒寫技術部落格了,之前寫的都是關於linux環境下資源監測方面的內容,比賽做完以後改做Android移動平台的研究,主要關注能耗這部分,有興趣的童鞋可以多交流。
最近因為工作需要我需要分析JAVA程式,師兄師姐們首推SOOT,看過入門文檔後也覺得SOOT功能很強大,上次去PLDI會議的workshop還看到了現在SOOT的負責人Eric Bodden,很帥的一個小夥子,言歸正傳~
Soot的安裝和使用參考官網http://www.sable.mcgill.ca/soot/ 的supervisor guide就可以,跑通裡面的例子就能對soot的功能有大體的瞭解。下面是我在後期使用遇到的問題及解決辦法。
1. Error: class com.ByteCodeStyle read in from a classfile in which ByteCodeStyle was expected.
這個問題是在程式內部設定了 -soot-classpath, -process-path參數後出現的。
-soot-classpath:C:\*****\workspace\SeeByteCode\bin\com
-process-path:C:\*****\workspace\SeeByteCode\bin\com
從邏輯上考慮我已經將要處理的類ByteCodeStyle的路徑告訴了soot,它應該可以找到類。我們再看一下錯誤資訊soot在類檔案讀到的類名是com.ByteCodeStyle,但是它需要的類名卻是ByteCodeStyle。這兩個名稱的差別就在於前者多了一個包名。下一步跟蹤到最底層錯誤產生的代碼(Util.java):
往上找調用這個方法的代碼可以發現name是從類檔案中讀出的類名,bclass.getName()是從使用者指定的路徑中讀出來的類名,所以我們設定的路徑下的類名就是ByteCodeStyle,再看一下這個類檔案的位元組碼
讀出的com.ByteCodeStyle和路徑下的ByteCodeStyle不匹配,對應的解決方案就是修改-process-path和-soot-classpath,把它們都改成C:\*****\workspace\SeeByteCode\bin,比上面的路徑少了一個\com,soot預設把這個子目錄名當做包名,這樣路徑下的類檔案名稱就是com.ByteCodeStyle,與類檔案讀出來的就一致了。DONE~
2. 在執行文檔中控制流程例子的時候遇到的問題,代碼
SootClass c=Scene.v().loadClassAndSupport("com.ByteCodeStyle"); c.setApplicationClass(); SootMethod m=c.getMethodByName("add"); Body b=m.retrieveActiveBody(); UnitGraph g= new ExceptionalUnitGraph(b); Iterator i=g.iterator(); while(i.hasNext()) { Unit u=(Unit)i.next();//........ }
錯誤資訊: Exception in thread "main" java.lang.NullPointerException,跟蹤錯誤定位在Body b=m.retrieveActiveBody();m為null所以產生了null 指標異常,說明之前才,c.getMethodByName("add");出現問題,也可以判定soot並沒有成功載入方法,之前在網上查了一些資料都沒有找到合適的解決辦法,最後向soot-list裡面的大牛發郵件詢問,很快就收到了Phil Pratt-Szeliga的回複,他發給我一個代碼檔案,建議我通過Transformer去載入類和方法,一試果然有效,現附上大牛的代碼檔案,希望能有所協助。
import java.util.Iterator;import java.util.Map;import soot.*;import soot.toolkits.graph.BriefUnitGraph;import soot.toolkits.graph.UnitGraph;//wrote by Phil Pratt-Szeligaclass Example { public void run(String dir){ Printer printer = new Printer(); Transform t1 = new Transform("jtp.Printer", printer); PackManager.v().getPack("jtp").add(t1); int size = 4; String[] soot_args = new String[size]; soot_args[0] = "-process-dir"; soot_args[1] = dir; soot_args[2] = "-pp"; soot_args[3] = "-allow-phantom-refs"; soot.Main.main(soot_args); } public static void main(String[] args){ Example example = new Example(); example.run("build/classes/"); } class Printer extends BodyTransformer { @Override protected void internalTransform(Body body, String string, Map map) { SootMethod method = body.getMethod(); if(method.getName().equals("main") == false){ return; } UnitGraph g=new BriefUnitGraph(body); Iterator it=g.iterator(); while(it.hasNext()){ Unit u=(Unit)it.next(); } } }}
目前還遇到一個問題,等找到解決方案後再寫出來。