wala / WALA

T.J. Watson Libraries for Analysis, with frontends for Java, Android, and JavaScript, and may common static program analyses
http://github.com/wala/WALA
Eclipse Public License 2.0
762 stars 223 forks source link

How can I get call graph of multiple js files? #1366

Open SherlockNovitch opened 9 months ago

SherlockNovitch commented 9 months ago

The wiki only has single-file api usage examples. I try to use the public static CallGraph makeScriptCG(SourceModule[] scripts, CGBuilderType builderType, IRFactory<IMethod> irFactory) api for multi-file call graph generation.

The complete code is as follows:

    public static SourceURLModule getSourceURLModule(String path) {
        try {
            return new SourceURLModule(JSCallGraphBuilderUtil.getURLforFile("", String.valueOf(path)
                    , JSCallGraphBuilderUtil.class.getClassLoader()));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static void generateCallGraph(String filePath) throws WalaException, IOException, CancelException {
        Path path = Paths.get(filePath);

        JSCallGraphUtil.setTranslatorFactory(new CAstRhinoTranslatorFactory());

        LinkedList<SourceURLModule> sourceURLModules = new LinkedList<>();
        Files.walk(path).filter(aPath -> aPath.toString().endsWith(".js"))
                .forEach(apath -> sourceURLModules.add(getSourceURLModule(String.valueOf(apath))));

        CallGraph cg = JSCallGraphBuilderUtil.makeScriptCG(sourceURLModules.toArray(new SourceURLModule[0]),
                JSCallGraphBuilderUtil.CGBuilderType.ZERO_ONE_CFA,
                AstIRFactory.makeDefaultFactory());

//        CallGraph cg = JSCallGraphBuilderUtil.makeScriptCG(path.getParent().toString(), path.getFileName().toString());
        System.out.println(CallGraphStats.getStats(cg));
        System.out.println(cg);
    }

The output results only contain the edge between the fake root and the file node under the filePath folder. No other information is output, which is very different from the output of a single file.

Call graph stats:
  Nodes: 14
  Edges: 13
  Methods: 14
  Bytecode Bytes: 0

Node: synthetic < JavaScriptLoader, LFakeRoot, fakeRootMethod()V > Context: Everywhere
 - JSCall@1
     -> Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/apply.js> Context: Everywhere
 - JSCall@3
     -> Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/bind.js> Context: Everywhere
 - JSCall@5
     -> Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/call.js> Context: Everywhere
 - JSCall@7
     -> Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/callback.js> Context: Everywhere
 - JSCall@9
     -> Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/closure.js> Context: Everywhere
 - JSCall@11
     -> Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/dynamic_property.js> Context: Everywhere
 - JSCall@13
     -> Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/eval.js> Context: Everywhere
 - JSCall@15
     -> Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/helloworld.js> Context: Everywhere
 - JSCall@17
     -> Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/iife.js> Context: Everywhere
 - JSCall@19
     -> Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/prototype.js> Context: Everywhere
 - JSCall@21
     -> Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/prototype_chain.js> Context: Everywhere
 - JSCall@23
     -> Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/unknown_property.js> Context: Everywhere
 - JSCall@25
     -> Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/with.js> Context: Everywhere

Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/apply.js> Context: Everywhere

Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/bind.js> Context: Everywhere

Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/call.js> Context: Everywhere

Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/callback.js> Context: Everywhere

Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/closure.js> Context: Everywhere

Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/dynamic_property.js> Context: Everywhere

Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/eval.js> Context: Everywhere

Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/helloworld.js> Context: Everywhere

Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/iife.js> Context: Everywhere

Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/prototype.js> Context: Everywhere

Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/prototype_chain.js> Context: Everywhere

Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/unknown_property.js> Context: Everywhere

Node: <Code body of function L/D:/Project/JavaScriptCGUtil/src/test/js-benchmark1/with.js> Context: Everywhere

How can i get correct call graph of multiplejs files?

msridhar commented 9 months ago

Sorry this is not better documented. I was looking at this code to create Modules when there is a single file:

https://github.com/wala/WALA/blob/130b92c444c206572682f2e007cca64670e3b03e/cast/js/src/main/java/com/ibm/wala/cast/js/util/JSCallGraphBuilderUtil.java#L143-L143

It also adds a Module for the prologue by calling this function:

https://github.com/wala/WALA/blob/130b92c444c206572682f2e007cca64670e3b03e/cast/js/src/main/java/com/ibm/wala/cast/js/ipa/callgraph/JSCallGraphUtil.java#L347-L347

Does that help to fix your case?