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
26int 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/*
53REQUIRES: system-linux,shell,fuser
54
55RUN: %clang %cflags %s -o %t.exe -Wl,-q -pie -fpie
56
57RUN: llvm-bolt %t.exe --instrument --instrumentation-file=%t.fdata \
58RUN: --conservative-instrumentation -o %t.instrumented_conservative \
59RUN: --instrumentation-sleep-time=1 --instrumentation-no-counters-clear \
60RUN: --instrumentation-wait-forks
61
62# Instrumented program needs to finish returning zero
63# Both output and profile must contain all 16 functions
64RUN: %t.instrumented_conservative > %t.output
65# Wait for profile and output to be fully written
66RUN: bash %S/wait_file.sh %t.output
67RUN: bash %S/wait_file.sh %t.fdata
68RUN: cat %t.output | FileCheck %s --check-prefix=CHECK-OUTPUT
69RUN: cat %t.fdata | FileCheck %s --check-prefix=CHECK-COMMON-PROF
70
71CHECK-OUTPUT-DAG: funcA
72CHECK-OUTPUT-DAG: funcB
73CHECK-OUTPUT-DAG: funcC
74CHECK-OUTPUT-DAG: funcD
75CHECK-OUTPUT-DAG: funcE
76CHECK-OUTPUT-DAG: funcF
77CHECK-OUTPUT-DAG: funcG
78CHECK-OUTPUT-DAG: funcH
79CHECK-OUTPUT-DAG: funcI
80CHECK-OUTPUT-DAG: funcJ
81CHECK-OUTPUT-DAG: funcK
82CHECK-OUTPUT-DAG: funcL
83CHECK-OUTPUT-DAG: funcM
84CHECK-OUTPUT-DAG: funcN
85CHECK-OUTPUT-DAG: funcO
86CHECK-OUTPUT-DAG: funcP
87
88CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcA 0 0 1
89CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcB 0 0 1
90CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcC 0 0 1
91CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcD 0 0 1
92CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcE 0 0 1
93CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcF 0 0 1
94CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcG 0 0 1
95CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcH 0 0 1
96CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcI 0 0 1
97CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcJ 0 0 1
98CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcK 0 0 1
99CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcL 0 0 1
100CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcM 0 0 1
101CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcN 0 0 1
102CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcO 0 0 1
103CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcP 0 0 1
104
105RUN: llvm-bolt %t.exe --instrument --instrumentation-file=%t \
106RUN: --instrumentation-file-append-pid \
107RUN: -o %t.instrumented
108
109RUN: %t.instrumented > %t.output
110# Wait till output is fully written in case child outlives parent
111RUN: bash %S/wait_file.sh %t.output
112# Make sure all functions were called
113RUN: cat %t.output | FileCheck %s --check-prefix=CHECK-OUTPUT
114
115RUN: child_pid=$(cat %t.output | grep funcA | awk '{print $2;}')
116RUN: par_pid=$(cat %t.output | grep funcB | awk '{print $2;}')
117
118RUN: bash %S/wait_file.sh %t.$child_pid.fdata
119RUN: bash %S/wait_file.sh %t.$par_pid.fdata
120
121RUN: mv %t.$child_pid.fdata %t.child.fdata
122RUN: 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.
127RUN: cat %t.child.fdata | FileCheck %s --check-prefix=CHECK-CHILD
128RUN: cat %t.child.fdata | FileCheck %s --check-prefix=CHECK-NOCHILD
129RUN: cat %t.parent.fdata | FileCheck %s --check-prefix=CHECK-PARENT
130RUN: cat %t.parent.fdata | FileCheck %s --check-prefix=CHECK-NOPARENT
131
132CHECK-CHILD-DAG: 1 main {{[0-9a-f]+}} 1 funcA 0 0 1
133CHECK-CHILD-DAG: 1 main {{[0-9a-f]+}} 1 funcC 0 0 1
134CHECK-CHILD-DAG: 1 main {{[0-9a-f]+}} 1 funcE 0 0 1
135CHECK-CHILD-DAG: 1 main {{[0-9a-f]+}} 1 funcG 0 0 1
136CHECK-CHILD-DAG: 1 main {{[0-9a-f]+}} 1 funcI 0 0 1
137CHECK-CHILD-DAG: 1 main {{[0-9a-f]+}} 1 funcK 0 0 1
138CHECK-CHILD-DAG: 1 main {{[0-9a-f]+}} 1 funcM 0 0 1
139CHECK-CHILD-DAG: 1 main {{[0-9a-f]+}} 1 funcO 0 0 1
140
141CHECK-NOCHILD-NOT: funcB
142CHECK-NOCHILD-NOT: funcD
143CHECK-NOCHILD-NOT: funcF
144CHECK-NOCHILD-NOT: funcH
145CHECK-NOCHILD-NOT: funcJ
146CHECK-NOCHILD-NOT: funcL
147CHECK-NOCHILD-NOT: funcN
148CHECK-NOCHILD-NOT: funcP
149
150CHECK-PARENT-DAG: 1 main {{[0-9a-f]+}} 1 funcB 0 0 1
151CHECK-PARENT-DAG: 1 main {{[0-9a-f]+}} 1 funcD 0 0 1
152CHECK-PARENT-DAG: 1 main {{[0-9a-f]+}} 1 funcF 0 0 1
153CHECK-PARENT-DAG: 1 main {{[0-9a-f]+}} 1 funcH 0 0 1
154CHECK-PARENT-DAG: 1 main {{[0-9a-f]+}} 1 funcJ 0 0 1
155CHECK-PARENT-DAG: 1 main {{[0-9a-f]+}} 1 funcL 0 0 1
156CHECK-PARENT-DAG: 1 main {{[0-9a-f]+}} 1 funcN 0 0 1
157CHECK-PARENT-DAG: 1 main {{[0-9a-f]+}} 1 funcP 0 0 1
158
159CHECK-NOPARENT-NOT: funcA
160CHECK-NOPARENT-NOT: funcC
161CHECK-NOPARENT-NOT: funcE
162CHECK-NOPARENT-NOT: funcG
163CHECK-NOPARENT-NOT: funcI
164CHECK-NOPARENT-NOT: funcK
165CHECK-NOPARENT-NOT: funcM
166CHECK-NOPARENT-NOT: funcO
167
168 */
169

source code of bolt/test/runtime/instrumentation-indirect-2.c