Search code examples
javacode-analysisstatic-analysiscall-graphsoot

How to analyze .class files using soot?


I'm trying to build a call-graph(CG) for spotbugs-4.0.2 with soot. The code is shown as follows.

public static void main(String[] args) {

    String analyzed_classes_dir = "C:\\Users\\lyu\\lll\\src\\test\\java\\com\\demo\\dir3\\spotbugs"; //contains all structured class files
    String mainclass = "edu.umd.cs.findbugs.LaunchAppropriateUI";

    //set classpath
    String javapath = System.getProperty("java.class.path");
    String jredir = System.getProperty("java.home") + "\\lib\\rt.jar";
    String libs = "C:\\Users\\liuyu\\lll\\src\\test\\java\\com\\demo\\libs\\spotbugs-4.0.2\\";
    String path = javapath + File.pathSeparator + jredir + File.pathSeparator + libs;

    Scene.v().setSootClassPath(path);

    //add an intra-procedural analysis phase to Soot
    TestCallGraphSootJar_3 analysis = new TestCallGraphSootJar_3();
    PackManager.v().getPack("wjtp").add(new Transform("wjtp.TestSootCallGraph", analysis));

    excludeJDKLibrary();

    Options.v().set_process_dir(Arrays.asList(analyzed_classes_dir));
    Options.v().set_whole_program(true);
    Options.v().set_no_bodies_for_excluded(true);
    Options.v().set_allow_phantom_refs(true);

    Scene.v().loadNecessaryClasses();
    SootClass appclass = Scene.v().getSootClass(mainclass);
    Scene.v().setMainClass(appclass); // exception here.

    enableSparkCallGraph();

    PackManager.v().runPacks();
}

Then the exception:

Exception in thread "main" java.lang.RuntimeException: Main-class has no main method!
at soot.Scene.setMainClass(Scene.java:187)
at com.ouc.TestCallGraphSootJar_3.main(TestCallGraphSootJar_3.java:65)

The statement "Scene.v().setMainClass(appclass);" throws the above exception. I debugged it and found that the methodlst in the appclass is null. And appclass is phantom. As shown in the picture. fig. the debug information of appclass

The mainclass does exist in the specified path, and it does contain the main method.

I've submitted an issue in GitHub (https://github.com/Sable/soot/issues/1346#issuecomment-627551137) but didn't solve it. And the options manual also didn't help with this problem.

Btw, could I only analyze the call relationships in a given class? For example, I only want to get the call information inside the class C1.

Class C1{
  main(){
    m1(parm);
  }

  m1(args){
    m2(xxx);
  }

  m2(args){
    m3(xxx);
  }

  m3(args){
    ...  
  }
}

Then I only want to get the follow call relationship:

main——>m1()——>m2()——m3()

If main or m1 or m2 or m3 calls a method in another class C2, I will ignore it, only focus on the methods in C1.


Solution

  • I'm the asker, and I've solved it. If you are interested in this question, you can read it in this issue post.