Hi! I put together a minimal example to illustrate my confusion:
import java.util.LinkedList;
import java.util.List;
class Foo {
void bar() {
System.out.println("zomg bar");
}
}
public class Test {
public static List<Foo> foos() {
List<Foo> x = new LinkedList<>();
Foo foo = new Foo();
x.add(foo);
foo.bar();
return x;
}
public static void main(String[] args) {
System.out.println("hi!");
System.out.println(foos());
}
}
Ignoring all the usual soot setup machinery (I'm using DefaultBoomerangOptions
and the pretransformer), after compiling the code I end up with the following Jimple:
...
$stack2 = new java.util.LinkedList;
specialinvoke $stack2.<java.util.LinkedList: void <init>()>();
l0 = $stack2;
$stack3 = new Foo;
specialinvoke $stack3.<Foo: void <init>()>();
l1 = $stack3;
interfaceinvoke l0.<java.util.List: boolean add(java.lang.Object)>(l1);
virtualinvoke l1.<Foo: void bar()>();
...
Now, if I point my forward query at $stack2 = new java.util.LinkedList
, pass it to my solver instance, and call getInvokedMethodOnInstance
on the result, I get the following:
{CS: l0.add(l1)=<java.util.List: boolean add(java.lang.Object)>, CS: $stack2.<init>()=<java.util.LinkedList: void <init>()>}
Which is what I'd expect, since I call the constructor on that list and also use .add
on it.
On the other hand, if I do the exact same thing to the $stack3 = new Foo
statement, I get an empty set of invoked methods, even though I call the constructor on it (obviously) and also call .bar
on it.
I'm trying to understand what the fundamental difference is between those two cases and how I can make the latter query on my Foo
instance also return the correct set of invoked methods.