GettingStarted:wala.cast.js

From WalaWiki

Jump to: navigation, search

Basic Setup

As described on the Getting Started page, you will need com.ibm.wala.core, com.ibm.wala.shrike, com.ibm.wala.cast, com.ibm.wala.cast.js, com.ibm.wala.cast.js.rhino projects for javascript analysis. To use the wala library, you can add these projects to your build path (Properties > Java Build Path > Projects > Add) or export these projects to a jar and add it to you build path. You might additionally have to include some eclipse plugins to your build path. It is a nice idea to get the test projects too (mainly com.ibm.wala.cast.js.test and com.ibm.wala.cast.js.rhino.test) as the tests will be helpful in learning to use wala.

Make sure you get the dependencies (rhino and xalan jars) and the tests using the com.ibm.wala.cast.js/lib/fetch_libraries.sh and com.ibm.wala.cast.js.test/examples-src/fetch_tests.sh scripts. Once you're setup, you should be able to run the JUnit tests from com.ibm.wala.cast.js.test/harness-src

Getting the IR

You can use the com.ibm.wala.cast.js.test.Util to create the Call graph and iterate over the instructions as follows.

CallGraph CG = Util.makeScriptCG("dir", "file.js");
Iterator<CGNode> iter = CG.iterator();
CGNode tempNode;
while (iter.hasNext()) {
  tempNode = iter.next();

  // Get CGNodes from CG
  Iterator<CGNode> iter = CG.iterator();
  CGNode node;
  while (iter.hasNext()) {
    node = iter.next();

    // Get the IR of a CGNode
    IR ir = node.getIR();

    // Get CFG from IR
    SSACFG cfg = ir.getControlFlowGraph();

    // Iterate over the Basic Blocks of CFG
    Iterator<ISSABasicBlock> cfgIt = cfg.iterator();
    while (cfgIt.hasNext()) {
      ISSABasicBlock ssaBb = cfgIt.next();

      // Iterate over SSA Instructions for a Basic Block
      Iterator<SSAInstruction> ssaIt = ssaBb.iterator();
      while (ssaIt.hasNext()) {
        SSAInstruction ssaInstr = ssaIt.next();
        //Print out the instruction
        System.out.println(ssaInstr);
      }
    }
  }
}

The call graph has a FakeRoot node and it's successors are prologue.js (which contains basic JS function definitions) and your js files. The functions in your_file.js would be successors of the CGNode corresponding to your_file.js. You can filter out your file's CGNode as follows:

private CGNode getFunctionNode(CallGraph CG, String dir, String file) {
  TypeName type = TypeName.findOrCreate("L" + dir + "/" + file);
  if (CG != null) {
    Iterator<CGNode> iter = CG.iterator();
    CGNode node;
    while (iter.hasNext()) {
      node = iter.next();
      TypeName tempType = node.getMethod().getDeclaringClass().getName();
      if (tempType.equals(type)) {
        return node;
      }
    }
  }
  System.err.println("Can't find :" + dir + "/" + file);
  return null;
}

Some Points

  • The IR for inner functions and closures is not generated unless you have a call to them. IRFactory seems to be useful for getting the IR outside a call graph. But since JavaScript has lexical scoping, and the IR outside a call graph has no way to know how lexical scoping is used in called functions. (clarification by Julian on the mailing list)
  • For every property lookup, Wala creates a loop (isDefined) to iterate through the prototype links.
  • To supress Wala's messages, set DEBUG=false in com.ibm.wala.cast.js.translator.RhinoToAstTranslator. You might also need to comment out certain CAstPrinter.printTo() and System.err.println() calls in CAstAbstractModuleLoader and CAstRewriter
project information