Skip to content

Analyse a Simple Java Program

QilinPTA edited this page Mar 24, 2022 · 3 revisions

An Example

The following example is taken from our ECOOP'22 paper:

class Main {
  public static void main(String[] args) {
    C c1 = new C(); // C1
    C c2 = c1;
    A a1 = c1.wcreate2(); // c1
    A a2 = c2.wcreate2(); // c2
    Object o1 = new Object(); // O1
    Object o2 = new Object(); // O2
    a1.f = o1;
    a2.f = o2;
    Object v1 = a1.f;
    Object v2 = a2.f; 
  }
}

class A { Object f; }
class B {
  A create() {
    A r1 = new A(); // A1
    return r1; 
  }
  A wcreate() {
    A r2 = this.create(); // c4
    return r2;
  }
}
class C {
  A wcreate2() {
    B b1 = new B(); // B1
    A r3 = b1.wcreate(); // c3
    return r3;
  }
}

Here is its jar file.

Dump the Jimple files

The following command can be used to perform context-insensitive pointer analysis for example.jar and dump the Jimple files (i.e., IRs) of the class files in example.jar.

java -cp /home/hedj/Work/QiLinOfficial/artifact/Qilin-1.0-SNAPSHOT.jar driver.Main 
-pae -pe -clinit=ONFLY -lcs -mh -pta=insens -apppath /home/hedj/example.jar -mainclass Main 
-jre=/home/hedj/Work/QiLinOfficial/artifact/benchmarks/JREs/jre1.8.0_312/ -se -jimple

Please refer to this link to understand the meaning of each option.

The Jimple files will be generated under the same directory containing example.jar. Here is the Jimple code for Class C:

class C extends java.lang.Object {
    void <init>() {
        C this;
        this := @this: C;
        specialinvoke this.<java.lang.Object: void <init>()>();
        return;
    }
    A wcreate2() {
        B $stack3, b1;
        A r3;
        C this;
        this := @this: C;
        $stack3 = new B;
        specialinvoke $stack3.<B: void <init>()>();
        b1 = $stack3;
        r3 = virtualinvoke b1.<B: A wcreate()>();
        return r3;
    }
}

Dump the Callgraph

In QiLin, the callgraph for the program being analysed is built on the fly during the pointer analysis. You can use the following command to generate the callgraph in the dot format.

java -cp /home/hedj/Work/QiLinOfficial/artifact/Qilin-1.0-SNAPSHOT.jar driver.Main 
-pae -pe -clinit=ONFLY -lcs -mh -pta=insens -apppath /home/hedj/example.jar -mainclass Main 
-jre=/home/hedj/Work/QiLinOfficial/artifact/benchmarks/JREs/jre1.8.0_312/ -se -cg

The callgraph looks like this:

cg

A mapping from the nodes in this call graph to the methods in example.jar is given below:

0:<FakeMain: void fakeMain()>
1:<Main: void main(java.lang.String[])>
2:<java.lang.String: void <clinit>()>
3:<java.lang.String$CaseInsensitiveComparator: void <init>(java.lang.String$1)>
4:<java.lang.Object: void <init>()>
5:<java.lang.String$CaseInsensitiveComparator: void <init>()>
6:<C: A wcreate2()>
7:<java.lang.Object: void <clinit>()>
8:<C: void <init>()>
9:<B: A create()>
10:<A: void <init>()>
11:<B: void <init>()>
12:<B: A wcreate()>
13:<java.lang.Object: void registerNatives()>

Dump the PAG

The PAG (pointer assignment graph) is dynamically constructed during the pointer analysis. You can use the following command to dump the PAG of the program being analysed:

java -cp /home/hedj/Work/QiLinOfficial/artifact/Qilin-1.0-SNAPSHOT.jar driver.Main 
-pae -pe -clinit=ONFLY -lcs -mh -pta=insens -apppath /home/hedj/example.jar -mainclass Main 
-jre=/home/hedj/Work/QiLinOfficial/artifact/benchmarks/JREs/jre1.8.0_312/ -se -pag

The PAG graph is quite complex and thus only a small slice is shown below:

pag

The names of the nodes in the PAG are given below:

[L100]ContextVarNode 100(LocalVarNode 91 $stack3 <C: A wcreate2()>, [])
[L101]ContextVarNode 101(LocalVarNode 92 b1 <C: A wcreate2()>, [])
[L102]ContextVarNode 102(LocalVarNode 93 r3 <C: A wcreate2()>, [])
[L110]ContextVarNode 110(LocalVarNode 107 Parm THIS_NODE to <B: void <init>()> <B: void <init>()>, [])
[L111]ContextVarNode 111(LocalVarNode 106 this <B: void <init>()>, [])
[L118]ContextVarNode 118(LocalVarNode 117 Parm RETURN to <B: A wcreate()> <B: A wcreate()>, [])
[L121]ContextVarNode 121(LocalVarNode 115 Parm THIS_NODE to <B: A wcreate()> <B: A wcreate()>, [])
[L122]ContextVarNode 122(LocalVarNode 114 this <B: A wcreate()>, [])
[L123]ContextVarNode 123(LocalVarNode 116 r2 <B: A wcreate()>, [])
[L131]ContextVarNode 131(LocalVarNode 130 Parm RETURN to <B: A create()> <B: A create()>, [])
[L134]ContextVarNode 134(LocalVarNode 127 Parm THIS_NODE to <B: A create()> <B: A create()>, [])
[L135]ContextVarNode 135(LocalVarNode 126 this <B: A create()>, [])
[L136]ContextVarNode 136(LocalVarNode 128 $stack2 <B: A create()>, [])
[L137]ContextVarNode 137(LocalVarNode 129 r1 <B: A create()>, [])
[L144]ContextVarNode 144(LocalVarNode 141 Parm THIS_NODE to <A: void <init>()> <A: void <init>()>, [])
[L145]ContextVarNode 145(LocalVarNode 140 this <A: void <init>()>, [])
[L55]ContextVarNode 55(LocalVarNode 29 $stack9 <Main: void main(java.lang.String[])>, [])
[L56]ContextVarNode 56(LocalVarNode 30 c1 <Main: void main(java.lang.String[])>, [])
[L57]ContextVarNode 57(LocalVarNode 31 c2 <Main: void main(java.lang.String[])>, [])
[L58]ContextVarNode 58(LocalVarNode 34 $stack12 <Main: void main(java.lang.String[])>, [])
[L59]ContextVarNode 59(LocalVarNode 35 o1 <Main: void main(java.lang.String[])>, [])
[L60]ContextVarNode 60(LocalVarNode 36 $stack13 <Main: void main(java.lang.String[])>, [])
[L61]ContextVarNode 61(LocalVarNode 37 o2 <Main: void main(java.lang.String[])>, [])
[L62]ContextVarNode 62(LocalVarNode 32 a1 <Main: void main(java.lang.String[])>, [])
[L63]ContextVarNode 63(LocalVarNode 33 a2 <Main: void main(java.lang.String[])>, [])
[L64]ContextVarNode 64(LocalVarNode 38 v1 <Main: void main(java.lang.String[])>, [])
[L65]ContextVarNode 65(LocalVarNode 39 v2 <Main: void main(java.lang.String[])>, [])
[L84]ContextVarNode 84(LocalVarNode 81 Parm THIS_NODE to <C: void <init>()> <C: void <init>()>, [])
[L85]ContextVarNode 85(LocalVarNode 80 this <C: void <init>()>, [])
[L86]ContextVarNode 86(LocalVarNode 79 specialinvoke this.<java.lang.Object: void <init>()>() <C: void <init>()>, [])
[L95]ContextVarNode 95(LocalVarNode 94 Parm RETURN to <C: A wcreate2()> <C: A wcreate2()>, [])
[L98]ContextVarNode 98(LocalVarNode 90 Parm THIS_NODE to <C: A wcreate2()> <C: A wcreate2()>, [])
[L99]ContextVarNode 99(LocalVarNode 89 this <C: A wcreate2()>, [])
[O14]ContextAllocNode 14(AllocNode 9 new C in method <Main: void main(java.lang.String[])>, [])
[O15]ContextAllocNode 15(AllocNode 10 new java.lang.Object in method <Main: void main(java.lang.String[])>, [])
[O16]ContextAllocNode 16(AllocNode 11 new java.lang.Object in method <Main: void main(java.lang.String[])>, [])
[O18]ContextAllocNode 18(AllocNode 17 new B in method <C: A wcreate2()>, [])
[O20]ContextAllocNode 20(AllocNode 19 new A in method <B: A create()>, [])
[OF147]ContextField 147 AllocNode 19 new A in method <B: A create()>.FieldNode 9336 <A: java.lang.Object f>
[VF5]FieldRefNode 5 ContextVarNode 62(LocalVarNode 32 a1 <Main: void main(java.lang.String[])>, []).FieldNode 9336 <A: java.lang.Object f>
[VF6]FieldRefNode 6 ContextVarNode 63(LocalVarNode 33 a2 <Main: void main(java.lang.String[])>, []).FieldNode 9336 <A: java.lang.Object f>

Dump the Points-to Relations

In general, you can make use of the computed points-to relations online by invoking APIs defined in the interface PointsToAnalysis such as PointsToSet reachingObjects(Local) and PointsToSet reachingObjects(SootField).

In Qilin, you can inspect the points-to relations stored in a file, named pts.txt. There are two options: --dumppts (which dumps pts for the variables in application code only) and --dumpallpts (which dumps pts for the variables in all reachable code (app + lib)).

Below we use the --dumppts option to obtain the points-to relations for the variables in example.jar:

java -cp /home/hedj/Work/QiLinOfficial/artifact/Qilin-1.0-SNAPSHOT.jar driver.Main 
-pae -pe -clinit=ONFLY -lcs -mh -pta=insens -apppath /home/hedj/example.jar -mainclass Main 
-jre=/home/hedj/Work/QiLinOfficial/artifact/benchmarks/JREs/jre1.8.0_312/ -se --dumppts

The content of pts.txt is given below:

Points-to results:
L22 -> { empty }
L23 -> { empty }
L24 -> { empty }
L25 -> { empty }
L26 -> { empty }
L27 -> { O6 }
L28 -> { O6 }
L29 -> { O14 }
L30 -> { O14 }
L31 -> { O14 }
L32 -> { O20 }
L33 -> { O20 }
L34 -> { O15 }
L35 -> { O15 }
L36 -> { O16 }
L37 -> { O16 }
L38 -> { O15 O16 }
L39 -> { O15 O16 }
L40 -> { O6 }
L41 -> { empty }
L42 -> { empty }
L54 -> { O6 }
L55 -> { O14 }
L56 -> { O14 }
L57 -> { O14 }
L58 -> { O15 }
L59 -> { O15 }
L60 -> { O16 }
L61 -> { O16 }
L62 -> { O20 }
L63 -> { O20 }
L64 -> { O15 O16 }
L65 -> { O15 O16 }
L66 -> { empty }
L67 -> { empty }
L68 -> { empty }
L69 -> { empty }
L70 -> { empty }
L79 -> { empty }
L80 -> { O14 }
L81 -> { O14 }
L82 -> { empty }
L83 -> { empty }
L84 -> { O14 }
L85 -> { O14 }
L86 -> { empty }
L87 -> { empty }
L88 -> { empty }
L89 -> { O14 }
L90 -> { O14 }
L91 -> { O18 }
L92 -> { O18 }
L93 -> { O20 }
L94 -> { O20 }
L95 -> { O20 }
L96 -> { empty }
L97 -> { empty }
L98 -> { O14 }
L99 -> { O14 }
L100 -> { O18 }
L101 -> { O18 }
L102 -> { O20 }
L103 -> { empty }
L104 -> { empty }
L105 -> { empty }
L106 -> { O18 }
L107 -> { O18 }
L108 -> { empty }
L109 -> { empty }
L110 -> { O18 }
L111 -> { O18 }
L112 -> { empty }
L113 -> { empty }
L114 -> { O18 }
L115 -> { O18 }
L116 -> { O20 }
L117 -> { O20 }
L118 -> { O20 }
L119 -> { empty }
L120 -> { empty }
L121 -> { O18 }
L122 -> { O18 }
L123 -> { O20 }
L124 -> { empty }
L125 -> { empty }
L126 -> { O18 }
L127 -> { O18 }
L128 -> { O20 }
L129 -> { O20 }
L130 -> { O20 }
L131 -> { O20 }
L132 -> { empty }
L133 -> { empty }
L134 -> { O18 }
L135 -> { O18 }
L136 -> { O20 }
L137 -> { O20 }
L138 -> { empty }
L139 -> { empty }
L140 -> { O20 }
L141 -> { O20 }
L142 -> { empty }
L143 -> { empty }
L144 -> { O20 }
L145 -> { O20 }
L146 -> { empty }
[L100]ContextVarNode 100(LocalVarNode 91 $stack3 <C: A wcreate2()>, [])
[L101]ContextVarNode 101(LocalVarNode 92 b1 <C: A wcreate2()>, [])
[L102]ContextVarNode 102(LocalVarNode 93 r3 <C: A wcreate2()>, [])
[L103]ContextVarNode 103(LocalVarNode 88 r3 = virtualinvoke b1.<B: A wcreate()>() <C: A wcreate2()>, [])
[L104]ContextVarNode 104(LocalVarNode 87 specialinvoke $stack3.<B: void <init>()>() <C: A wcreate2()>, [])
[L105]LocalVarNode 105 specialinvoke this.<java.lang.Object: void <init>()>() <B: void <init>()>
[L106]LocalVarNode 106 this <B: void <init>()>
[L107]LocalVarNode 107 Parm THIS_NODE to <B: void <init>()> <B: void <init>()>
[L108]LocalVarNode 108 Parm -3 to <B: void <init>()> <B: void <init>()>
[L109]ContextVarNode 109(LocalVarNode 108 Parm -3 to <B: void <init>()> <B: void <init>()>, [])
[L110]ContextVarNode 110(LocalVarNode 107 Parm THIS_NODE to <B: void <init>()> <B: void <init>()>, [])
[L111]ContextVarNode 111(LocalVarNode 106 this <B: void <init>()>, [])
[L112]ContextVarNode 112(LocalVarNode 105 specialinvoke this.<java.lang.Object: void <init>()>() <B: void <init>()>, [])
[L113]LocalVarNode 113 r2 = virtualinvoke this.<B: A create()>() <B: A wcreate()>
[L114]LocalVarNode 114 this <B: A wcreate()>
[L115]LocalVarNode 115 Parm THIS_NODE to <B: A wcreate()> <B: A wcreate()>
[L116]LocalVarNode 116 r2 <B: A wcreate()>
[L117]LocalVarNode 117 Parm RETURN to <B: A wcreate()> <B: A wcreate()>
[L118]ContextVarNode 118(LocalVarNode 117 Parm RETURN to <B: A wcreate()> <B: A wcreate()>, [])
[L119]LocalVarNode 119 Parm -3 to <B: A wcreate()> <B: A wcreate()>
[L120]ContextVarNode 120(LocalVarNode 119 Parm -3 to <B: A wcreate()> <B: A wcreate()>, [])
[L121]ContextVarNode 121(LocalVarNode 115 Parm THIS_NODE to <B: A wcreate()> <B: A wcreate()>, [])
[L122]ContextVarNode 122(LocalVarNode 114 this <B: A wcreate()>, [])
[L123]ContextVarNode 123(LocalVarNode 116 r2 <B: A wcreate()>, [])
[L124]ContextVarNode 124(LocalVarNode 113 r2 = virtualinvoke this.<B: A create()>() <B: A wcreate()>, [])
[L125]LocalVarNode 125 specialinvoke $stack2.<A: void <init>()>() <B: A create()>
[L126]LocalVarNode 126 this <B: A create()>
[L127]LocalVarNode 127 Parm THIS_NODE to <B: A create()> <B: A create()>
[L128]LocalVarNode 128 $stack2 <B: A create()>
[L129]LocalVarNode 129 r1 <B: A create()>
[L130]LocalVarNode 130 Parm RETURN to <B: A create()> <B: A create()>
[L131]ContextVarNode 131(LocalVarNode 130 Parm RETURN to <B: A create()> <B: A create()>, [])
[L132]LocalVarNode 132 Parm -3 to <B: A create()> <B: A create()>
[L133]ContextVarNode 133(LocalVarNode 132 Parm -3 to <B: A create()> <B: A create()>, [])
[L134]ContextVarNode 134(LocalVarNode 127 Parm THIS_NODE to <B: A create()> <B: A create()>, [])
[L135]ContextVarNode 135(LocalVarNode 126 this <B: A create()>, [])
[L136]ContextVarNode 136(LocalVarNode 128 $stack2 <B: A create()>, [])
[L137]ContextVarNode 137(LocalVarNode 129 r1 <B: A create()>, [])
[L138]ContextVarNode 138(LocalVarNode 125 specialinvoke $stack2.<A: void <init>()>() <B: A create()>, [])
[L139]LocalVarNode 139 specialinvoke this.<java.lang.Object: void <init>()>() <A: void <init>()>
[L140]LocalVarNode 140 this <A: void <init>()>
[L141]LocalVarNode 141 Parm THIS_NODE to <A: void <init>()> <A: void <init>()>
[L142]LocalVarNode 142 Parm -3 to <A: void <init>()> <A: void <init>()>
[L143]ContextVarNode 143(LocalVarNode 142 Parm -3 to <A: void <init>()> <A: void <init>()>, [])
[L144]ContextVarNode 144(LocalVarNode 141 Parm THIS_NODE to <A: void <init>()> <A: void <init>()>, [])
[L145]ContextVarNode 145(LocalVarNode 140 this <A: void <init>()>, [])
[L146]ContextVarNode 146(LocalVarNode 139 specialinvoke this.<java.lang.Object: void <init>()>() <A: void <init>()>, [])
[L22]LocalVarNode 22 specialinvoke $stack9.<C: void <init>()>() <Main: void main(java.lang.String[])>
[L23]LocalVarNode 23 a1 = virtualinvoke c1.<C: A wcreate2()>() <Main: void main(java.lang.String[])>
[L24]LocalVarNode 24 a2 = virtualinvoke c2.<C: A wcreate2()>() <Main: void main(java.lang.String[])>
[L25]LocalVarNode 25 specialinvoke $stack12.<java.lang.Object: void <init>()>() <Main: void main(java.lang.String[])>
[L26]LocalVarNode 26 specialinvoke $stack13.<java.lang.Object: void <init>()>() <Main: void main(java.lang.String[])>
[L27]LocalVarNode 27 args <Main: void main(java.lang.String[])>
[L28]LocalVarNode 28 Parm 0 to <Main: void main(java.lang.String[])> <Main: void main(java.lang.String[])>
[L29]LocalVarNode 29 $stack9 <Main: void main(java.lang.String[])>
[L30]LocalVarNode 30 c1 <Main: void main(java.lang.String[])>
[L31]LocalVarNode 31 c2 <Main: void main(java.lang.String[])>
[L32]LocalVarNode 32 a1 <Main: void main(java.lang.String[])>
[L33]LocalVarNode 33 a2 <Main: void main(java.lang.String[])>
[L34]LocalVarNode 34 $stack12 <Main: void main(java.lang.String[])>
[L35]LocalVarNode 35 o1 <Main: void main(java.lang.String[])>
[L36]LocalVarNode 36 $stack13 <Main: void main(java.lang.String[])>
[L37]LocalVarNode 37 o2 <Main: void main(java.lang.String[])>
[L38]LocalVarNode 38 v1 <Main: void main(java.lang.String[])>
[L39]LocalVarNode 39 v2 <Main: void main(java.lang.String[])>
[L40]ContextVarNode 40(LocalVarNode 28 Parm 0 to <Main: void main(java.lang.String[])> <Main: void main(java.lang.String[])>, [])
[L41]LocalVarNode 41 Parm -3 to <Main: void main(java.lang.String[])> <Main: void main(java.lang.String[])>
[L42]ContextVarNode 42(LocalVarNode 41 Parm -3 to <Main: void main(java.lang.String[])> <Main: void main(java.lang.String[])>, [])
[L54]ContextVarNode 54(LocalVarNode 27 args <Main: void main(java.lang.String[])>, [])
[L55]ContextVarNode 55(LocalVarNode 29 $stack9 <Main: void main(java.lang.String[])>, [])
[L56]ContextVarNode 56(LocalVarNode 30 c1 <Main: void main(java.lang.String[])>, [])
[L57]ContextVarNode 57(LocalVarNode 31 c2 <Main: void main(java.lang.String[])>, [])
[L58]ContextVarNode 58(LocalVarNode 34 $stack12 <Main: void main(java.lang.String[])>, [])
[L59]ContextVarNode 59(LocalVarNode 35 o1 <Main: void main(java.lang.String[])>, [])
[L60]ContextVarNode 60(LocalVarNode 36 $stack13 <Main: void main(java.lang.String[])>, [])
[L61]ContextVarNode 61(LocalVarNode 37 o2 <Main: void main(java.lang.String[])>, [])
[L62]ContextVarNode 62(LocalVarNode 32 a1 <Main: void main(java.lang.String[])>, [])
[L63]ContextVarNode 63(LocalVarNode 33 a2 <Main: void main(java.lang.String[])>, [])
[L64]ContextVarNode 64(LocalVarNode 38 v1 <Main: void main(java.lang.String[])>, [])
[L65]ContextVarNode 65(LocalVarNode 39 v2 <Main: void main(java.lang.String[])>, [])
[L66]ContextVarNode 66(LocalVarNode 23 a1 = virtualinvoke c1.<C: A wcreate2()>() <Main: void main(java.lang.String[])>, [])
[L67]ContextVarNode 67(LocalVarNode 24 a2 = virtualinvoke c2.<C: A wcreate2()>() <Main: void main(java.lang.String[])>, [])
[L68]ContextVarNode 68(LocalVarNode 26 specialinvoke $stack13.<java.lang.Object: void <init>()>() <Main: void main(java.lang.String[])>, [])
[L69]ContextVarNode 69(LocalVarNode 22 specialinvoke $stack9.<C: void <init>()>() <Main: void main(java.lang.String[])>, [])
[L70]ContextVarNode 70(LocalVarNode 25 specialinvoke $stack12.<java.lang.Object: void <init>()>() <Main: void main(java.lang.String[])>, [])
[L79]LocalVarNode 79 specialinvoke this.<java.lang.Object: void <init>()>() <C: void <init>()>
[L80]LocalVarNode 80 this <C: void <init>()>
[L81]LocalVarNode 81 Parm THIS_NODE to <C: void <init>()> <C: void <init>()>
[L82]LocalVarNode 82 Parm -3 to <C: void <init>()> <C: void <init>()>
[L83]ContextVarNode 83(LocalVarNode 82 Parm -3 to <C: void <init>()> <C: void <init>()>, [])
[L84]ContextVarNode 84(LocalVarNode 81 Parm THIS_NODE to <C: void <init>()> <C: void <init>()>, [])
[L85]ContextVarNode 85(LocalVarNode 80 this <C: void <init>()>, [])
[L86]ContextVarNode 86(LocalVarNode 79 specialinvoke this.<java.lang.Object: void <init>()>() <C: void <init>()>, [])
[L87]LocalVarNode 87 specialinvoke $stack3.<B: void <init>()>() <C: A wcreate2()>
[L88]LocalVarNode 88 r3 = virtualinvoke b1.<B: A wcreate()>() <C: A wcreate2()>
[L89]LocalVarNode 89 this <C: A wcreate2()>
[L90]LocalVarNode 90 Parm THIS_NODE to <C: A wcreate2()> <C: A wcreate2()>
[L91]LocalVarNode 91 $stack3 <C: A wcreate2()>
[L92]LocalVarNode 92 b1 <C: A wcreate2()>
[L93]LocalVarNode 93 r3 <C: A wcreate2()>
[L94]LocalVarNode 94 Parm RETURN to <C: A wcreate2()> <C: A wcreate2()>
[L95]ContextVarNode 95(LocalVarNode 94 Parm RETURN to <C: A wcreate2()> <C: A wcreate2()>, [])
[L96]LocalVarNode 96 Parm -3 to <C: A wcreate2()> <C: A wcreate2()>
[L97]ContextVarNode 97(LocalVarNode 96 Parm -3 to <C: A wcreate2()> <C: A wcreate2()>, [])
[L98]ContextVarNode 98(LocalVarNode 90 Parm THIS_NODE to <C: A wcreate2()> <C: A wcreate2()>, [])
[L99]ContextVarNode 99(LocalVarNode 89 this <C: A wcreate2()>, [])
[O14]ContextAllocNode 14(AllocNode 9 new C in method <Main: void main(java.lang.String[])>, [])
[O15]ContextAllocNode 15(AllocNode 10 new java.lang.Object in method <Main: void main(java.lang.String[])>, [])
[O16]ContextAllocNode 16(AllocNode 11 new java.lang.Object in method <Main: void main(java.lang.String[])>, [])
[O18]ContextAllocNode 18(AllocNode 17 new B in method <C: A wcreate2()>, [])
[O20]ContextAllocNode 20(AllocNode 19 new A in method <B: A create()>, [])
[O6]ContextAllocNode 6(AllocNode 4 newarray (java.lang.String)[1] in method <FakeMain: void fakeMain()>, [])

Gather analysis statistics

Qilin also provides an option, '-stats', for generating some analysis data with respect to several metrics of interest, such as Reachable methods, Polymorphic calls, and May fail casts.

java -cp /home/hedj/Work/QiLinOfficial/artifact/Qilin-1.0-SNAPSHOT.jar driver.Main 
-pae -pe -clinit=ONFLY -lcs -mh -pta=insens -apppath /home/hedj/example.jar -mainclass Main 
-jre=/home/hedj/Work/QiLinOfficial/artifact/benchmarks/JREs/jre1.8.0_312/ -se -stats

You will get a list of the following output files:

sootOutput/Main/insensitive/SingleCallMethods.csv
sootOutput/Main/insensitive/SingleReceiverMethods.csv
sootOutput/Main/insensitive/SingleCallSingleReceiverMethods.csv
sootOutput/Main/insensitive/Reachable.csv
sootOutput/Main/insensitive/AppReachable.csv
sootOutput/Main/insensitive/PolyCalls.csv
sootOutput/Main/insensitive/MayFailCasts.csv
sootOutput/Main/insensitive/InsensReachVars.csv
sootOutput/Main/insensitive/InsensReachVarsNoNatives.csv
sootOutput/Main/insensitive/ClassType.csv
sootOutput/Main/insensitive/Statistics.txt

Below we list the content of Reachable.csv:

<java.lang.String$CaseInsensitiveComparator: void <init>()>
<java.lang.String: void <clinit>()>
<Main: void main(java.lang.String[])>
<C: A wcreate2()>
<A: void <init>()>
<C: void <init>()>
<java.lang.Object: void <init>()>
<FakeMain: void fakeMain()>
<B: A create()>
<B: A wcreate()>
<java.lang.Object: void <clinit>()>
<B: void <init>()>
<java.lang.String$CaseInsensitiveComparator: void <init>(java.lang.String$1)>
<java.lang.Object: void registerNatives()>