Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Soot: Reload class after source-file changed

I'm writing an IntelliJ-Plugin to analyse java-program code. Thus i use Soot to write static analyses. Every time a user triggers the analyse-action of my plugin, I take the current VirtualFile of the current context like this:

FileEditorManager manager = FileEditorManager.getInstance(e.getProject());
VirtualFile files[] = manager.getSelectedFiles();
toAnalyse = files[0]; [...]

When I check the content of this file all changes are applied. After this I'm loading the class I want to analyse in Soot.

String dir =  toAnalyse.getParent().getPath() ;
Options.v().setPhaseOption("jb", "use-original-names");
Options.v().set_soot_classpath( System.getProperty("java.home")+";"+ dir);
c = Scene.v().loadClassAndSupport(name);
/*no analyse c*/

This works perfectly for me. But now to my issue: If i change sth. in test instance of my plugin and trigger the same analysis again, nothing changes.

What have i tried so far?

I set following options:

Options.v().set_dump_body( Arrays.asList("jb"));
Options.v().set_dump_cfg( Arrays.asList("jb"));
Options.v().set_allow_phantom_refs(true);
Options.v().set_whole_program(true);

I also removed all classes by hand

like this:

Chain<SootClass> classes = Scene.v().getClasses();
Stack<SootClass> stack = new Stack<>();
for(SootClass s : classes)
    stack.push(s);
while(!stack.empty())
    Scene.v().removeClass(stack.pop());

and started the program again.

like image 695
osanger Avatar asked Jun 08 '17 16:06

osanger


1 Answers

I solved this issue.

SootClass c = Scene.v().loadClassAndSupport(name);
// ...
c.setResolvingLevel(0);
G.reset();

G.reset() resets all singleton instances. Therefore all cached results will be overwritten by calling this action again.

public static Scene v() {
    return G.v().soot_Scene();
}

this.instance_soot_Scene is null after calling G.reset().

Therefore the following code:

public Scene soot_Scene() {
    if(this.instance_soot_Scene == null) {
        synchronized(this) {
            if(this.instance_soot_Scene == null) {
                this.instance_soot_Scene = new Scene(this.g);
            }
        }
    }

    return this.instance_soot_Scene;
}

returns a new instance with an empty result cache.

like image 88
osanger Avatar answered Oct 02 '22 22:10

osanger