1 | // Check that indirect call hash tables properly register multiple calls, |
2 | // and that calls from different processes don't get mixed up when using |
3 | // --instrumentation-file-append-pid. |
4 | |
5 | #include <stdio.h> |
6 | #include <stdlib.h> |
7 | #include <unistd.h> |
8 | |
9 | __attribute__((noinline)) void funcA(int pid) { printf(format: "funcA %d\n" , pid); } |
10 | __attribute__((noinline)) void funcB(int pid) { printf(format: "funcB %d\n" , pid); } |
11 | __attribute__((noinline)) void funcC(int pid) { printf(format: "funcC %d\n" , pid); } |
12 | __attribute__((noinline)) void funcD(int pid) { printf(format: "funcD %d\n" , pid); } |
13 | __attribute__((noinline)) void funcE(int pid) { printf(format: "funcE %d\n" , pid); } |
14 | __attribute__((noinline)) void funcF(int pid) { printf(format: "funcF %d\n" , pid); } |
15 | __attribute__((noinline)) void funcG(int pid) { printf(format: "funcG %d\n" , pid); } |
16 | __attribute__((noinline)) void funcH(int pid) { printf(format: "funcH %d\n" , pid); } |
17 | __attribute__((noinline)) void funcI(int pid) { printf(format: "funcI %d\n" , pid); } |
18 | __attribute__((noinline)) void funcJ(int pid) { printf(format: "funcJ %d\n" , pid); } |
19 | __attribute__((noinline)) void funcK(int pid) { printf(format: "funcK %d\n" , pid); } |
20 | __attribute__((noinline)) void funcL(int pid) { printf(format: "funcL %d\n" , pid); } |
21 | __attribute__((noinline)) void funcM(int pid) { printf(format: "funcM %d\n" , pid); } |
22 | __attribute__((noinline)) void funcN(int pid) { printf(format: "funcN %d\n" , pid); } |
23 | __attribute__((noinline)) void funcO(int pid) { printf(format: "funcO %d\n" , pid); } |
24 | __attribute__((noinline)) void funcP(int pid) { printf(format: "funcP %d\n" , pid); } |
25 | |
26 | int main() { |
27 | |
28 | void (*funcs[])(int) = {funcA, funcB, funcC, funcD, funcE, funcF, |
29 | funcG, funcH, funcI, funcJ, funcK, funcL, |
30 | funcM, funcN, funcO, funcP}; |
31 | int i; |
32 | |
33 | switch (fork()) { |
34 | case -1: |
35 | printf(format: "Failed to fork!\n" ); |
36 | exit(status: -1); |
37 | break; |
38 | case 0: |
39 | i = 0; |
40 | break; |
41 | default: |
42 | i = 1; |
43 | break; |
44 | } |
45 | int pid = getpid(); |
46 | for (; i < sizeof(funcs) / sizeof(void *); i += 2) { |
47 | funcs[i](pid); |
48 | } |
49 | |
50 | return 0; |
51 | } |
52 | /* |
53 | REQUIRES: system-linux,shell,fuser |
54 | |
55 | RUN: %clang %cflags %s -o %t.exe -Wl,-q -pie -fpie |
56 | |
57 | RUN: llvm-bolt %t.exe --instrument --instrumentation-file=%t.fdata \ |
58 | RUN: --conservative-instrumentation -o %t.instrumented_conservative \ |
59 | RUN: --instrumentation-sleep-time=1 --instrumentation-no-counters-clear \ |
60 | RUN: --instrumentation-wait-forks |
61 | |
62 | # Instrumented program needs to finish returning zero |
63 | # Both output and profile must contain all 16 functions |
64 | RUN: %t.instrumented_conservative > %t.output |
65 | # Wait for profile and output to be fully written |
66 | RUN: bash %S/wait_file.sh %t.output |
67 | RUN: bash %S/wait_file.sh %t.fdata |
68 | RUN: cat %t.output | FileCheck %s --check-prefix=CHECK-OUTPUT |
69 | RUN: cat %t.fdata | FileCheck %s --check-prefix=CHECK-COMMON-PROF |
70 | |
71 | CHECK-OUTPUT-DAG: funcA |
72 | CHECK-OUTPUT-DAG: funcB |
73 | CHECK-OUTPUT-DAG: funcC |
74 | CHECK-OUTPUT-DAG: funcD |
75 | CHECK-OUTPUT-DAG: funcE |
76 | CHECK-OUTPUT-DAG: funcF |
77 | CHECK-OUTPUT-DAG: funcG |
78 | CHECK-OUTPUT-DAG: funcH |
79 | CHECK-OUTPUT-DAG: funcI |
80 | CHECK-OUTPUT-DAG: funcJ |
81 | CHECK-OUTPUT-DAG: funcK |
82 | CHECK-OUTPUT-DAG: funcL |
83 | CHECK-OUTPUT-DAG: funcM |
84 | CHECK-OUTPUT-DAG: funcN |
85 | CHECK-OUTPUT-DAG: funcO |
86 | CHECK-OUTPUT-DAG: funcP |
87 | |
88 | CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcA 0 0 1 |
89 | CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcB 0 0 1 |
90 | CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcC 0 0 1 |
91 | CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcD 0 0 1 |
92 | CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcE 0 0 1 |
93 | CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcF 0 0 1 |
94 | CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcG 0 0 1 |
95 | CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcH 0 0 1 |
96 | CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcI 0 0 1 |
97 | CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcJ 0 0 1 |
98 | CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcK 0 0 1 |
99 | CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcL 0 0 1 |
100 | CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcM 0 0 1 |
101 | CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcN 0 0 1 |
102 | CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcO 0 0 1 |
103 | CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcP 0 0 1 |
104 | |
105 | RUN: llvm-bolt %t.exe --instrument --instrumentation-file=%t \ |
106 | RUN: --instrumentation-file-append-pid \ |
107 | RUN: -o %t.instrumented |
108 | |
109 | RUN: %t.instrumented > %t.output |
110 | # Wait till output is fully written in case child outlives parent |
111 | RUN: bash %S/wait_file.sh %t.output |
112 | # Make sure all functions were called |
113 | RUN: cat %t.output | FileCheck %s --check-prefix=CHECK-OUTPUT |
114 | |
115 | RUN: child_pid=$(cat %t.output | grep funcA | awk '{print $2;}') |
116 | RUN: par_pid=$(cat %t.output | grep funcB | awk '{print $2;}') |
117 | |
118 | RUN: bash %S/wait_file.sh %t.$child_pid.fdata |
119 | RUN: bash %S/wait_file.sh %t.$par_pid.fdata |
120 | |
121 | RUN: mv %t.$child_pid.fdata %t.child.fdata |
122 | RUN: mv %t.$par_pid.fdata %t.parent.fdata |
123 | |
124 | # Instrumented binary must produce two profiles with only local calls |
125 | # recorded. Functions called only in child should not appear in parent's |
126 | # process and vice versa. |
127 | RUN: cat %t.child.fdata | FileCheck %s --check-prefix=CHECK-CHILD |
128 | RUN: cat %t.child.fdata | FileCheck %s --check-prefix=CHECK-NOCHILD |
129 | RUN: cat %t.parent.fdata | FileCheck %s --check-prefix=CHECK-PARENT |
130 | RUN: cat %t.parent.fdata | FileCheck %s --check-prefix=CHECK-NOPARENT |
131 | |
132 | CHECK-CHILD-DAG: 1 main {{[0-9a-f]+}} 1 funcA 0 0 1 |
133 | CHECK-CHILD-DAG: 1 main {{[0-9a-f]+}} 1 funcC 0 0 1 |
134 | CHECK-CHILD-DAG: 1 main {{[0-9a-f]+}} 1 funcE 0 0 1 |
135 | CHECK-CHILD-DAG: 1 main {{[0-9a-f]+}} 1 funcG 0 0 1 |
136 | CHECK-CHILD-DAG: 1 main {{[0-9a-f]+}} 1 funcI 0 0 1 |
137 | CHECK-CHILD-DAG: 1 main {{[0-9a-f]+}} 1 funcK 0 0 1 |
138 | CHECK-CHILD-DAG: 1 main {{[0-9a-f]+}} 1 funcM 0 0 1 |
139 | CHECK-CHILD-DAG: 1 main {{[0-9a-f]+}} 1 funcO 0 0 1 |
140 | |
141 | CHECK-NOCHILD-NOT: funcB |
142 | CHECK-NOCHILD-NOT: funcD |
143 | CHECK-NOCHILD-NOT: funcF |
144 | CHECK-NOCHILD-NOT: funcH |
145 | CHECK-NOCHILD-NOT: funcJ |
146 | CHECK-NOCHILD-NOT: funcL |
147 | CHECK-NOCHILD-NOT: funcN |
148 | CHECK-NOCHILD-NOT: funcP |
149 | |
150 | CHECK-PARENT-DAG: 1 main {{[0-9a-f]+}} 1 funcB 0 0 1 |
151 | CHECK-PARENT-DAG: 1 main {{[0-9a-f]+}} 1 funcD 0 0 1 |
152 | CHECK-PARENT-DAG: 1 main {{[0-9a-f]+}} 1 funcF 0 0 1 |
153 | CHECK-PARENT-DAG: 1 main {{[0-9a-f]+}} 1 funcH 0 0 1 |
154 | CHECK-PARENT-DAG: 1 main {{[0-9a-f]+}} 1 funcJ 0 0 1 |
155 | CHECK-PARENT-DAG: 1 main {{[0-9a-f]+}} 1 funcL 0 0 1 |
156 | CHECK-PARENT-DAG: 1 main {{[0-9a-f]+}} 1 funcN 0 0 1 |
157 | CHECK-PARENT-DAG: 1 main {{[0-9a-f]+}} 1 funcP 0 0 1 |
158 | |
159 | CHECK-NOPARENT-NOT: funcA |
160 | CHECK-NOPARENT-NOT: funcC |
161 | CHECK-NOPARENT-NOT: funcE |
162 | CHECK-NOPARENT-NOT: funcG |
163 | CHECK-NOPARENT-NOT: funcI |
164 | CHECK-NOPARENT-NOT: funcK |
165 | CHECK-NOPARENT-NOT: funcM |
166 | CHECK-NOPARENT-NOT: funcO |
167 | |
168 | */ |
169 | |