| // Check that indirect call hash tables properly register multiple calls, |
| // and that calls from different processes don't get mixed up when using |
| // --instrumentation-file-append-pid. |
| |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <unistd.h> |
| |
| __attribute__((noinline)) void funcA(int pid) { printf("funcA %d\n", pid); } |
| __attribute__((noinline)) void funcB(int pid) { printf("funcB %d\n", pid); } |
| __attribute__((noinline)) void funcC(int pid) { printf("funcC %d\n", pid); } |
| __attribute__((noinline)) void funcD(int pid) { printf("funcD %d\n", pid); } |
| __attribute__((noinline)) void funcE(int pid) { printf("funcE %d\n", pid); } |
| __attribute__((noinline)) void funcF(int pid) { printf("funcF %d\n", pid); } |
| __attribute__((noinline)) void funcG(int pid) { printf("funcG %d\n", pid); } |
| __attribute__((noinline)) void funcH(int pid) { printf("funcH %d\n", pid); } |
| __attribute__((noinline)) void funcI(int pid) { printf("funcI %d\n", pid); } |
| __attribute__((noinline)) void funcJ(int pid) { printf("funcJ %d\n", pid); } |
| __attribute__((noinline)) void funcK(int pid) { printf("funcK %d\n", pid); } |
| __attribute__((noinline)) void funcL(int pid) { printf("funcL %d\n", pid); } |
| __attribute__((noinline)) void funcM(int pid) { printf("funcM %d\n", pid); } |
| __attribute__((noinline)) void funcN(int pid) { printf("funcN %d\n", pid); } |
| __attribute__((noinline)) void funcO(int pid) { printf("funcO %d\n", pid); } |
| __attribute__((noinline)) void funcP(int pid) { printf("funcP %d\n", pid); } |
| |
| int main() { |
| |
| void (*funcs[])(int) = {funcA, funcB, funcC, funcD, funcE, funcF, |
| funcG, funcH, funcI, funcJ, funcK, funcL, |
| funcM, funcN, funcO, funcP}; |
| int i; |
| |
| switch (fork()) { |
| case -1: |
| printf("Failed to fork!\n"); |
| exit(-1); |
| break; |
| case 0: |
| i = 0; |
| break; |
| default: |
| i = 1; |
| break; |
| } |
| int pid = getpid(); |
| for (; i < sizeof(funcs) / sizeof(void *); i += 2) { |
| funcs[i](pid); |
| } |
| |
| return 0; |
| } |
| /* |
| REQUIRES: system-linux,shell,fuser |
| |
| RUN: %clang %cflags %s -o %t.exe -Wl,-q -pie -fpie |
| |
| RUN: llvm-bolt %t.exe --instrument --instrumentation-file=%t.fdata \ |
| RUN: --conservative-instrumentation -o %t.instrumented_conservative \ |
| RUN: --instrumentation-sleep-time=1 --instrumentation-no-counters-clear \ |
| RUN: --instrumentation-wait-forks |
| |
| # Instrumented program needs to finish returning zero |
| # Both output and profile must contain all 16 functions |
| RUN: %t.instrumented_conservative > %t.output |
| # Wait for profile and output to be fully written |
| RUN: bash %S/wait_file.sh %t.output |
| RUN: bash %S/wait_file.sh %t.fdata |
| RUN: cat %t.output | FileCheck %s --check-prefix=CHECK-OUTPUT |
| RUN: cat %t.fdata | FileCheck %s --check-prefix=CHECK-COMMON-PROF |
| |
| CHECK-OUTPUT-DAG: funcA |
| CHECK-OUTPUT-DAG: funcB |
| CHECK-OUTPUT-DAG: funcC |
| CHECK-OUTPUT-DAG: funcD |
| CHECK-OUTPUT-DAG: funcE |
| CHECK-OUTPUT-DAG: funcF |
| CHECK-OUTPUT-DAG: funcG |
| CHECK-OUTPUT-DAG: funcH |
| CHECK-OUTPUT-DAG: funcI |
| CHECK-OUTPUT-DAG: funcJ |
| CHECK-OUTPUT-DAG: funcK |
| CHECK-OUTPUT-DAG: funcL |
| CHECK-OUTPUT-DAG: funcM |
| CHECK-OUTPUT-DAG: funcN |
| CHECK-OUTPUT-DAG: funcO |
| CHECK-OUTPUT-DAG: funcP |
| |
| CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcA 0 0 1 |
| CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcB 0 0 1 |
| CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcC 0 0 1 |
| CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcD 0 0 1 |
| CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcE 0 0 1 |
| CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcF 0 0 1 |
| CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcG 0 0 1 |
| CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcH 0 0 1 |
| CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcI 0 0 1 |
| CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcJ 0 0 1 |
| CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcK 0 0 1 |
| CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcL 0 0 1 |
| CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcM 0 0 1 |
| CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcN 0 0 1 |
| CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcO 0 0 1 |
| CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcP 0 0 1 |
| |
| RUN: llvm-bolt %t.exe --instrument --instrumentation-file=%t \ |
| RUN: --instrumentation-file-append-pid \ |
| RUN: -o %t.instrumented |
| |
| RUN: %t.instrumented > %t.output |
| # Wait till output is fully written in case child outlives parent |
| RUN: bash %S/wait_file.sh %t.output |
| # Make sure all functions were called |
| RUN: cat %t.output | FileCheck %s --check-prefix=CHECK-OUTPUT |
| |
| RUN: child_pid=$(cat %t.output | grep funcA | awk '{print $2;}') |
| RUN: par_pid=$(cat %t.output | grep funcB | awk '{print $2;}') |
| |
| RUN: bash %S/wait_file.sh %t.$child_pid.fdata |
| RUN: bash %S/wait_file.sh %t.$par_pid.fdata |
| |
| RUN: mv %t.$child_pid.fdata %t.child.fdata |
| RUN: mv %t.$par_pid.fdata %t.parent.fdata |
| |
| # Instrumented binary must produce two profiles with only local calls |
| # recorded. Functions called only in child should not appear in parent's |
| # process and vice versa. |
| RUN: cat %t.child.fdata | FileCheck %s --check-prefix=CHECK-CHILD |
| RUN: cat %t.child.fdata | FileCheck %s --check-prefix=CHECK-NOCHILD |
| RUN: cat %t.parent.fdata | FileCheck %s --check-prefix=CHECK-PARENT |
| RUN: cat %t.parent.fdata | FileCheck %s --check-prefix=CHECK-NOPARENT |
| |
| CHECK-CHILD-DAG: 1 main {{[0-9a-f]+}} 1 funcA 0 0 1 |
| CHECK-CHILD-DAG: 1 main {{[0-9a-f]+}} 1 funcC 0 0 1 |
| CHECK-CHILD-DAG: 1 main {{[0-9a-f]+}} 1 funcE 0 0 1 |
| CHECK-CHILD-DAG: 1 main {{[0-9a-f]+}} 1 funcG 0 0 1 |
| CHECK-CHILD-DAG: 1 main {{[0-9a-f]+}} 1 funcI 0 0 1 |
| CHECK-CHILD-DAG: 1 main {{[0-9a-f]+}} 1 funcK 0 0 1 |
| CHECK-CHILD-DAG: 1 main {{[0-9a-f]+}} 1 funcM 0 0 1 |
| CHECK-CHILD-DAG: 1 main {{[0-9a-f]+}} 1 funcO 0 0 1 |
| |
| CHECK-NOCHILD-NOT: funcB |
| CHECK-NOCHILD-NOT: funcD |
| CHECK-NOCHILD-NOT: funcF |
| CHECK-NOCHILD-NOT: funcH |
| CHECK-NOCHILD-NOT: funcJ |
| CHECK-NOCHILD-NOT: funcL |
| CHECK-NOCHILD-NOT: funcN |
| CHECK-NOCHILD-NOT: funcP |
| |
| CHECK-PARENT-DAG: 1 main {{[0-9a-f]+}} 1 funcB 0 0 1 |
| CHECK-PARENT-DAG: 1 main {{[0-9a-f]+}} 1 funcD 0 0 1 |
| CHECK-PARENT-DAG: 1 main {{[0-9a-f]+}} 1 funcF 0 0 1 |
| CHECK-PARENT-DAG: 1 main {{[0-9a-f]+}} 1 funcH 0 0 1 |
| CHECK-PARENT-DAG: 1 main {{[0-9a-f]+}} 1 funcJ 0 0 1 |
| CHECK-PARENT-DAG: 1 main {{[0-9a-f]+}} 1 funcL 0 0 1 |
| CHECK-PARENT-DAG: 1 main {{[0-9a-f]+}} 1 funcN 0 0 1 |
| CHECK-PARENT-DAG: 1 main {{[0-9a-f]+}} 1 funcP 0 0 1 |
| |
| CHECK-NOPARENT-NOT: funcA |
| CHECK-NOPARENT-NOT: funcC |
| CHECK-NOPARENT-NOT: funcE |
| CHECK-NOPARENT-NOT: funcG |
| CHECK-NOPARENT-NOT: funcI |
| CHECK-NOPARENT-NOT: funcK |
| CHECK-NOPARENT-NOT: funcM |
| CHECK-NOPARENT-NOT: funcO |
| |
| */ |