[Soot-list] Callgraph support for lambda expressions

Michael Appel michael.appel at stud.tu-darmstadt.de
Wed Mar 18 10:16:02 EDT 2015


Hello,

 

We want to extend the soot framework such that callgraph construction
considers lambda expressions.

Since lambda expressions are compiled to invokedynamic instructions and
these aren't handled in the framework yet we made the following changes:

 

1. Initially, in soot.asm.AsmMethodSource convertInvokeDynamicInsn() there
was a SootMethodRef created to a dummy class like that:

 

SootClass bclass =
Scene.v().getSootClass(SootClass.INVOKEDYNAMIC_DUMMY_CLASS_NAME);

[...]

SootMethodRef methodRef = Scene.v().makeMethodRef(bclass, insn.name,
parameterTypes, returnType, true);


DynamicInvokeExpr indy = Jimple.v().newDynamicInvokeExpr(bsmMethodRef,
bsmMethodArgs, methodRef, methodArgs);

 

We replaced that by:

 

SootMethodRef methodRef =
LambdaProxyBuilder.v().generateProxy(insn,toSootMethodRef((Handle)insn.bsmAr
gs[1]));                 

DynamicInvokeExpr indy = Jimple.v().newDynamicInvokeExpr(bsmMethodRef,
bsmMethodArgs, methodRef, methodArgs);

 

LambdaProxyBuilder is a class written by us which creates a jimple class
file implementing the required interface from the lambda expression.

The generated class from LambdaProxyBuilder provides a static factory method
newInstance(), so the idea is to let the dynamicinvoke point to the
newInstance() method of our generated class such that the variable on the
left side of the dynamicinvoke holds an object of that new type.

 

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);

} 

 

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();

}

 

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.concurrent
.atomic.LongAdder)>(r8, r1, r9) <java.lang.invoke.LambdaMetafactory:
java.lang.invoke.CallSite
metafactory(java.lang.invoke.MethodHandles$Lookup,java.lang.String,java.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.util.co
ncurrent.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.

 

Any help would be appreciated.

 

- Michael

-------------- next part --------------
An HTML attachment was scrubbed...
URL: https://mailman.CS.McGill.CA/pipermail/soot-list/attachments/20150318/fb35aecc/attachment.html 


More information about the Soot-list mailing list