[Soot-list] Callgraph support for lambda expressions

Michael Appel michael.appel at stud.tu-darmstadt.de
Thu Mar 26 12:21:50 EDT 2015


Thanks for your response Eric. Just wanted to let you know that we found the
problem after countless hours of debugging. The solution was to simply add
the Soot option "-p cg.spark pre-jimplify".

-----Ursprüngliche Nachricht-----
Von: Bodden, Eric [mailto:eric.bodden at sit.fraunhofer.de] 
Gesendet: Donnerstag, 19. März 2015 08:07
An: Michael Appel
Cc: soot-list at cs.mcgill.ca
Betreff: Re: [Soot-list] Callgraph support for lambda expressions

Hi Michael.

> 2. In soot.jimple.toolkits.callgraph.OnFlyCallGraphBuilder findReceivers()
is an empty if branch for dynamicinvoke expressions. As mentioned before, we
reduce the invokedynamic to a regular static invoke pointing towards the
factory method of our generated class so we try to apply the same logic as
it is used for static invokes:
> 
> else if (ie instanceof DynamicInvokeExpr) {
>                 SootMethod tgt = ie.getMethod();
>                 if(tgt!=null) {
>                                addEdge(m, s, tgt); }

But this is correct only for those indy calls that actually are created out
of Lambda expressions, right? I think there should be a second case covering
all the other ones.

> 3. In soot.Kind we added dynamic edges to the method isExplicit() like so:
> 
> /** Returns true if the call is due to an explicit invoke statement. 
> */ public boolean isExplicit() {
>                 return isInstance() || isStatic() || isDynamic(); }

I think that change generally makes sense.

> With those extensions we get good results for CHA and we also get the
required edges for very simple cases using SPARK. However, when the variable
on the left side of the dynamicinvoke is passed to another method, the
propagation of the type doesn't seem to work because the points-to set of
the parameter is empty. For example if we have the jimple code:
> 
> [...]
> com.lambda.interprocedural.DataFlowTarget2_lambda$0Proxy $r5; [...]
> $r5 = dynamicinvoke "newInstance" 
> <com.lambda.interprocedural.DataFlowTarget2_lambda$0Proxy 
> (java.lang.String,java.util.concurrent.atomic.LongAdder,java.util.conc
> urrent.atomic.LongAdder)>(r8, r1, r9) 
> <java.lang.invoke.LambdaMetafactory: java.lang.invoke.CallSite 
> metafactory(java.lang.invoke.MethodHandles$Lookup,java.lang.String,jav
> a.lang.invoke.MethodType,java.lang.invoke.MethodType,java.lang.invoke.
> MethodHandle,java.lang.invoke.MethodType)>(class "(Ljava/io/File;)Z", 
> handle: <com.lambda.interprocedural.DataFlowTarget2: boolean 
> lambda$0(java.lang.String,java.util.concurrent.atomic.LongAdder,java.u
> til.concurrent.atomic.LongAdder,java.io.File)>, class 
> "(Ljava/io/File;)Z"); virtualinvoke r0.<java.io.File: java.io.File[] 
> listFiles(java.io.FileFilter)>($r5);
> 
> the points-to set of $r5 holds our generated type. When $r5 is passed to
the method listFiles(), the corresponding parameter's points-to set is empty
and thus we don't get the desired edges in the cg.

Could it be that for some reason the types are incompatible with another? I
seem to remember that Spark employ some filtering based on the declared
types of the variables involved in a flow and the type associated with the
respective allocation node.

Cheers,
Eric



More information about the Soot-list mailing list