WALAではJavaのバイトコードの解析ができる
ここでは、ファイルの読込からCallGraphの取得までの簡単な説明を行う
解析手順
バイトコードの解析にはJavaバイトコード(jar)が必要なので、コンパイルしておく
jarファイルは例えば以下のようにコンパイルできる
$ javac Test.java
$ jar cfe Test.jar Test Test.class
ここでは、"Test.jar"を解析するとして話を進める
ファイルの読込
初めに解析対象のバイトコードを読み込む
FileProvider provider = new FileProvider();
AnalysisScope scope = AnalysisScopeReader.makeJavaBinaryAnalysisScope(
"Test.jar",
provider.getFile("Exclusions.txt")
);
解析ファイルのデータは AnalysisScope クラスとして保持される
ここで指定している"Exclusions.txt"には解析対象から省くパッケージ名を記述する (これである程度解析対象を減らさないと解析が長くなる)
Exclusions.txt (一例)
java\/awt\/.*
java\/applet\/.*
java\/beans\/.*
java\/nio\/.*
java\/rmi\/.*
java\/security\/.*
java\/sql\/.*
java\/util\/.*
java\/text\/.*
java\/math\/.*
java\/net\/.*
javax\/.*
javafx\/.*
oracle\/.*
apple\/.*
com\/sun\/.*
sun\/.*
org\/.*
jdk\/.*
sunw\/.*
java\/io\/.*
java\/lang\/annotation\/.*
java\/lang\/reflect\/.*
java\/lang\/management\/.*
java\/lang\/instrument\/.*
java\/lang\/ref\/.*
netscape\/.*
クラス階層の取得
ファイルを読み込んだら、次にクラス階層を取得する
IClassHierarchy cha = ClassHierarchyFactory.make(scope);
ClassHierarchy クラス内には複数の IClass クラスが含まれ、 1つのクラスに1つの IClass クラスのインスタンスが存在する
読み込まれたクラスデータの名前は IClass#getName() で取得できる
for(IClass klass : cha) {
System.out.println(klass.getName());
}
解析の設定
解析には AnalysisOptions クラスと AnalysisCache クラスが必要となる
AnalysisOptions クラスは、解析を行う際の設定を記述できるクラスである (今回は設定の記述の説明は省略する)
AnalysisCache クラスは解析中のデータを保持しておくためのクラスである
// "Test.jar"のエントリーポイント取得
Iterable<Entrypoint> entries = Util.makeMainEntrypoints(scope, cha);
// 解析の設定クラスを生成
AnalysisOptions options = new AnalysisOptions(scope, entries);
// 解析時のキャッシュ用のクラスを生成
IRFactory<IMethod> factory = AstIRFactory.makeDefaultFactory();
AuxiliaryCache irCache = new AuxiliaryCache(), duCache = new AuxiliaryCache();
SSACache ssaCache = new SSACache(factory, irCache, duCache);
SSAOptions ssaOptions = new SSAOptions();
AnalysisCache cache = new AnalysisCache(factory, ssaOptions, ssaCache);
解析の実行
最後に、ここまでで用意してきたクラスらを用いて解析を実行する
// CallGraphを構築するためのクラス
CallGraphBuilder builder = Util.makeZeroCFABuilder(options, cache, cha, scope);
// CallGraphの取得とポインタ解析結果の取得
CallGraph callGraph = builder.makeCallGraph(options, null);
PointerAnalysis pointerAnalysis = builder.getPointerAnalysis();