WALAではJavaだけでなくJavaScriptの解析もサポートしている

ここでは、ファイルの読込からCallGraphの取得までの簡単な説明を行う

解析手順

ここでは、"test.js"を解析するとして話を進める

基本的にはJavaの解析と同じ流れで行う

ファイルの読込

解析対象コードの指定

Module クラスの配列で解析対象のファイルを列挙する

File f = new FileProvider().getFile("test.js");
Module[] modules = new Module[] {
    JSCallGraphUtil.getPrologueFile("prologue.js"),
    new SourceFileModule(f, "test.js", null)
}

WALAには、JavaScriptの解析をサポートするためのコード(prologue.js等)が含まれている
これらを読み込むためには JSCallGraphUtil.getPrologueFile() を利用する

Important
JavaScriptを解析する際には、"prologue.js"を必ず読み込むこと
(WALAでは、"prologue.js"に含まれるFunctionを用いて関数呼び出しを展開し、解決する)

解析対象コードの読み込み

JavaScriptTranslatorFactory translatorFactory = new CAstRhinoTranslatorFactory();
JavaScriptLoaderFactory loaderFactory = new JavaScriptLoaderFactory(translatorFactory);
AnalysisScope scope = JSCallGraphUtil.makeScope(modules, loaderFactory, JavaScriptLoader.JS);

クラス階層の取得

コードを読み込んだら、次にクラス階層を取得する

IClassHierarchy cha = JSCallGraphUtil.makeHierarchy(scope, loaderFactory);

TIPS: WALAにおけるJavaScriptの"クラス"の扱い

WALAでは、JavaScriptにおける関数1つを1つのクラス(IClass クラスのインスタンス)とみなして解析を行っている

例えば、test.jsが以下のコードであったとする

test.js
function f() {
  function g() {}
}
function h() {}

このコードからクラス階層を取得した場合

  • Ltest

  • Ltest/f

  • Ltest/f/g

  • Ltest/h

の4つの IClass クラスのインスタンスが作られる

解析の設定

解析には AnalysisOptions クラスと AnalysisCache クラスが必要となる

AnalysisOptions クラスは、解析を行う際の設定を記述できるクラスである (今回は設定の記述の説明は省略する)

AnalysisCache クラスは解析中のデータを保持しておくためのクラスである

// コードのエントリーポイント取得
JavaScriptEntryPoints roots = JSCallGraphUtil.makeScriptRoots(cha);

// 解析の設定クラスを生成
JSAnalysisOptions options = JSCallGraphUtil.makeOptions(scope, cha, roots);

// 解析時のキャッシュ用クラスを生成
IRFactory<IMethod> irFactory = AstIRFactory.makeDefaultFactory();
AnalysisCache cache = (AnalysisCache) JSCallGraphUtil.makeCache(irFactory);

解析の実行

// CallGraphを構築するためのクラス
JSCFABuilder builder = new JSZeroOrOneXCFABuilder(
    cha,
    options,
    cache,
    null,
    null,
    ZeroXInstanceKeys.ALLOCATIONS,
    false
);

// CallGraphの取得とポインタ解析結果の取得
CallGraph callGraph = builder.makeCallGraph(options, null);
PointerAnalysis pointerAnalysis = builder.getPointerAnalysis();