[Soot-list] Spark calligraph incomplete

Miguel Velez mvelezce at cs.cmu.edu
Mon Oct 28 19:41:22 EDT 2019


Hi everyone,

I am trying to build a CallGraph with Spark to called information about what methods call other methods. I am trying to replicated how a CallGraph is built using FlowDroid. However, the call graph that I generate for a program is incomplete. I know it is incomplete since I compared the number of ClassNodes using ASM (211) with the number of SootClasses from parsing the src and tat of the edges from callGraph.listener() (80). I have spent several hours trying to debug why some edges are missing, but I cannot understand why.

Here is how I am building a call graph programmatically:

```
public static CallGraph buildCallGraph(String entryPoint, String appPath) {
  long startTime = System.nanoTime();
  initializeSoot(entryPoint, appPath);

  PackManager.v().getPack("wjpp").apply();
  PackManager.v().getPack("cg").apply();

  Scene.v().getOrMakeFastHierarchy();

  CallGraph callGraph = Scene.v().getCallGraph();

  long endTime = System.nanoTime();
  System.out.println("Time to build call graph: " + ((endTime - startTime) / 1E9));

  return callGraph;
}

private static void initializeSoot(String entryPoint, String appPath) {
  soot.G.reset();

  Options.v().set_no_bodies_for_excluded(true);
  Options.v().set_allow_phantom_refs(true);
  Options.v().set_output_format(Options.output_format_none);
  Options.v()
      .set_soot_classpath(
          appPath
              + ":/Library/Java/JavaVirtualMachines/jdk1.8.0_202.jdk/Contents/Home/jre/lib/rt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_202.jdk/Contents/Home/jre/lib/jce.jar");

  setSparkOptions();

  Options.v().set_whole_program(true);
  Options.v().setPhaseOption("cg", "trim-clinit:false");
  Options.v().setPhaseOption("jb.ulp", "off");
  Options.v().set_src_prec(Options.src_prec_java);

  // User options
  Options.v().setPhaseOption("jb", "use-original-names:true");

  // Options needed for instrumentation
  Options.v().set_keep_line_number(true);
  Options.v().set_keep_offset(true);
  Options.v().set_coffi(true);
  Options.v().set_ignore_classpath_errors(true);

  loadClassesAndBodies(entryPoint);
}

private static void loadClassesAndBodies(String entryPoint) {
  Scene.v().addBasicClass(entryPoint, SootClass.BODIES);
  Scene.v().loadNecessaryClasses();

  boolean hasClasses = false;

  SootClass c = Scene.v().forceResolve(entryPoint, SootClass.BODIES);
  if (c != null) {
    c.setApplicationClass();
    if (!c.isPhantomClass() && !c.isPhantom()) hasClasses = true;
  }

  if (!hasClasses) {
    throw new RuntimeException("Only phantom classes loaded, skipping analysis...");
  }
}

private static void setSparkOptions() {
  Options.v().setPhaseOption("cg.spark", "on");
  Options.v().setPhaseOption("cg.spark", "string-constants:true");
}
```

Can anyone help me understand what am I doing wrong? 

For instance, this is a method that is part of the calligraphy:

```
public List<PngPixel> getMergedColors(PngImage image, List<PngPixel> colors, long start) {
    for (PngPixel pa : colors) {
      if (!pa.isDuplicate()) {
      	...
      }
    }	
 }	
```

but the `isDuplicate()` method is not part of the calligraphy (i.e., the `edgesOutOf(getMergedColors)` does not include `isDuplicate`). However, if I change the class method to:

```
public List<PngPixel> getMergedColors(PngImage image, List<PngPixel> colors, long start) {
   PngPixel pa = new PngPixel();
   pa.isDuplicate();
 }	
```

The `isDuplicate()` method is part of the call graph. Why would creating a constructor include the method in the call graph?

Thanks,

Miguel


More information about the Soot-list mailing list