[Soot-list] Why Spark can't obtain the call graph on this snippet? But CHA can work.

liuyuan at fastmail.com liuyuan at fastmail.com
Fri Jun 19 12:32:29 EDT 2020


Hi Eric,

Thank you for your prompt reply. 

According to you, I created a class (i.e., com.beust.jcommander.Main) and inserted a main method which calls the parseWithoutValidation method. But the call graph is also enpty.  Could you help me with it?

The code is as follows:
Scene.v().loadNecessaryClasses();
// creat the Main class
Scene.v().loadClassAndSupport("java.lang.Object");
Scene.v().loadClassAndSupport("java.lang.System");
SootClass sClass = new SootClass("com.beust.jcommander.Main", Modifier.PUBLIC);
sClass.setSuperclass(Scene.v().getSootClass("java.lang.Object"));
Scene.v().addClass(sClass);
// insert a main method
SootMethod method = new SootMethod("main",
        Arrays.asList(new Type[] {ArrayType.v(RefType.v("java.lang.String"), 1)}),
        VoidType.v(), Modifier.PUBLIC | Modifier.STATIC);
sClass.addMethod(method);
{
    JimpleBody body = Jimple.v().newBody(method);

    method.setActiveBody(body);
    Chain units = body.getUnits();
    Local tmpRef;
    tmpRef = Jimple.v().newLocal("jCommander", RefType.v("com.beust.jcommander.JCommander"));
    body.getLocals().add(tmpRef);
        {
            SootMethod toCall = Scene.v().getMethod("<com.beust.jcommander.JCommander: void parseWithoutValidation(java.lang.String[])>");
            units.add(Jimple.v().newInvokeStmt(Jimple.v().newVirtualInvokeExpr(tmpRef, toCall.makeRef(), StringConstant.v("Hello world!"))));
        }
        units.add(Jimple.v().newReturnVoidStmt());
}
//custom entry point
SootClass c = Scene.v().forceResolve("com.beust.jcommander.Main", SootClass.BODIES);
c.setApplicationClass();
List entryPoints = new ArrayList();
entryPoints.add(method);
Scene.v().setEntryPoints(entryPoints);


I print the main method:
public static void main(java.lang.String[])
{
    com.beust.jcommander.JCommander jCommander;

    virtualinvoke jCommander.<com.beust.jcommander.JCommander: void parseWithoutValidation(java.lang.String[])>("Hello world!");

    return;
}


The parseWithoutValidationis as follows:
/**
* Parse the command line parameters without validating them.
*/
public void parseWithoutValidation(String... args) {
    parse(false /* no validation */, args);
}


Best regards,
Yuan
From: Eric Bodden
Date: 2020-06-19 04:07
To: liuyuan at fastmail.com
CC: soot-list
Subject: Re: [Soot-list] Why Spark can't obtain the call graph on this snippet? But CHA can work.
Hi Yuan.
 
I am afraid things are not that simple. The problem is likely the following: Soot will use the method you configured as entry point, but thus is a non-static instance method, which calls other instance methods on “this”. That “this”-object however, has never been initialized by your entry point, thus Spark assumes it to be null - leading to an empty call graph.
 
Thus, what we and many others have done in the past is the following: manually create a static mock-up method that properly initializes the object in question (and required helper objects) and then calls parseWithoutValidation. As entry point you then choose this new static mock-up method.
 
Sometimes it may make sense to generate such methods automatically. FlowDroid, for instance, does this for Android apps.
 
Cheers
Eric
 
> On 19. Jun 2020, at 00:16, liuyuan at fastmail.com wrote:
> 
> Hi all,
> 
> I customizd an entry point for a library (i.e. JCommander, a command interface tool for java) and used the Spark to build its CG. But The callgraph is empty. If I use the CHA, it works. 
> 
> The code snippet is as follows and the parseWithoutValidation is selected as the entry point.
> public void parseWithoutValidation(String... args) { // the customized entry point
>      parse(false /* no validation */, args); // I think this method could be found easily by Spark~
> }
> 
> private void parse(boolean validate, String... args) {
>     StringBuilder sb = new StringBuilder("Parsing \"");
>     sb.append(join(args).append("\"\n  with:").append(join(objects.toArray())));
>     p(sb.toString());
> 
>     if (descriptions == null) createDescriptions();
>     initializeDefaultValues();
>     parseValues(expandArgs(args), validate);
>     if (validate) validateOptions();
> }
> 
> private StringBuilder join(Object[] args) {
>     StringBuilder result = new StringBuilder();
>     for (int i = 0; i < args.length; i++) {
>         if (i > 0) result.append(" ");
>         result.append(args[i]);
>     }
>     return result;
> }
> ...
> 
> My core code is as follows.
> Options.v().set_process_dir(Arrays.asList(classesDir));
> Options.v().set_whole_program(true);
> Options.v().set_no_bodies_for_excluded(true);
> Options.v().set_allow_phantom_refs(true);
> 
> // set an entry point
> SootClass c = Scene.v().forceResolve(entryClass, SootClass.BODIES);
> c.setApplicationClass();
> Scene.v().loadNecessaryClasses();
> SootMethod method = c.getMethodByName(entryMethod);
> List entryPoints = new ArrayList();
> entryPoints.add(method);
> Scene.v().setEntryPoints(entryPoints);
> 
> //set Spark 
> HashMap<String, String> opt = new HashMap<String, String>();
> opt.put("on-fly-cg", "true");
> SparkTransformer.v().transform("", opt);
> PhaseOptions.v().setPhaseOption("cg.spark", "enabled:true");
> 
> PackManager.v().runPacks();
> 
> The target java file is attached.
> 
> Any suggestions are welcome.
> 
> Best regards,
> Yuan
> <JCommander.java>_______________________________________________
> Soot-list mailing list
> Soot-list at CS.McGill.CA
> https://mailman.CS.McGill.CA/mailman/listinfo/soot-list
 
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mailman.CS.McGill.CA/pipermail/soot-list/attachments/20200619/94c4e19b/attachment-0001.html>


More information about the Soot-list mailing list