I am trying to use Soot to perform data flow analysis on a java file which is called Example.java
.
Here is my Example.java
file, my goal is to know which saySomething
method animal.saySomething()
will call. Here is the code for Example.java I am using:
package a1;
public class Example {
static Animal neverCalled() {
return new Fish();
}
static Animal selectAnimal() {
return new Cat();
}
public static void main(String[] args) {
Animal animal = selectAnimal();
animal.saySomething();
}
}
abstract class Animal {
public abstract void saySomething();
}
class Cat extends Animal {
public void saySomething() {
System.out.println("purr");
}
}
class Dog extends Animal {
public void saySomething() {
System.out.println("woof");
}
}
class Fish extends Animal {
public void saySomething() {
System.out.println("...");
}
}
class Car { // not an Animal
public void saySomething() {
System.out.println("honk!");
}
}
and here is the code I am using to analyze Example.java
using Soot, this code is located in the file: TestSootCallGraph.java
which follows here:
package a1;
import java.io.File;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Map;
import soot.*;
import soot.jimple.Stmt;
import soot.jimple.spark.SparkTransformer;
import soot.jimple.toolkits.callgraph.CHATransformer;
import soot.jimple.toolkits.callgraph.CallGraph;
import soot.jimple.toolkits.callgraph.Targets;
import soot.options.Options;
public class TestSootCallGraph extends SceneTransformer {
static LinkedList<String> excludeList;
public static void main(String[] args) {
String mainclass = "Example";
// //set classpath
String javapath = System.getProperty("java.class.path");
String jredir = System.getProperty("java.home")+"/lib/rt.jar";
String path = javapath+File.pathSeparator+jredir;
Scene.v().setSootClassPath(path);
//add an intra-procedural analysis phase to Soot
TestSootCallGraph analysis = new TestSootCallGraph();
PackManager.v().getPack("wjtp").add(new Transform("wjtp.TestSootCallGraph", analysis));
excludeJDKLibrary();
//whole program analysis
Options.v().set_whole_program(true);
//load and set main class
Options.v().set_app(true);
SootClass appclass = Scene.v().loadClassAndSupport(mainclass);
System.out.println(appclass);
Scene.v().setMainClass(appclass);
Scene.v().loadNecessaryClasses();
//enable call graph
//enableCHACallGraph();
//enableSparkCallGraph();
//start working
PackManager.v().runPacks();
}
private static void excludeJDKLibrary()
{
//exclude jdk classes
Options.v().set_exclude(excludeList());
//this option must be disabled for a sound call graph
Options.v().set_no_bodies_for_excluded(true);
Options.v().set_allow_phantom_refs(true);
}
private static void enableSparkCallGraph() {
//Enable Spark
HashMap<String,String> opt = new HashMap<String,String>();
//opt.put("propagator","worklist");
//opt.put("simple-edges-bidirectional","false");
opt.put("on-fly-cg","true");
//opt.put("set-impl","double");
//opt.put("double-set-old","hybrid");
//opt.put("double-set-new","hybrid");
//opt.put("pre_jimplify", "true");
SparkTransformer.v().transform("",opt);
PhaseOptions.v().setPhaseOption("cg.spark", "enabled:true");
}
private static void enableCHACallGraph() {
CHATransformer.v().transform();
}
private static LinkedList<String> excludeList()
{
if(excludeList==null)
{
excludeList = new LinkedList<String> ();
excludeList.add("java.");
excludeList.add("javax.");
excludeList.add("sun.");
excludeList.add("sunw.");
excludeList.add("com.sun.");
excludeList.add("com.ibm.");
excludeList.add("com.apple.");
excludeList.add("apple.awt.");
}
return excludeList;
}
@Override
protected void internalTransform(String phaseName,
Map options) {
int numOfEdges =0;
CallGraph callGraph = Scene.v().getCallGraph();
for(SootClass sc : Scene.v().getApplicationClasses()){
for(SootMethod m : sc.getMethods()){
Iterator<MethodOrMethodContext> targets = new Targets(
callGraph.edgesOutOf(m));
while (targets.hasNext()) {
numOfEdges++;
SootMethod tgt = (SootMethod) targets.next();
System.out.println(m + " may call " + tgt);
}
}
}
System.err.println("Total Edges:" + numOfEdges);
}
}
I receive the following error when executing TestSootCallGraph.java
which aims at analyzing Example.java
. How can I fix this?
Example
Exception in thread "main" java.lang.RuntimeException: Main-class has no main method!
at soot.Scene.setMainClass(Scene.java:171)
at a1.TestSootCallGraph.main(TestSootCallGraph.java:47)