167 lines · c
1// Check that indirect call hash tables properly register multiple calls,2// and that calls from different processes don't get mixed up when using3// --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("funcA %d\n", pid); }10__attribute__((noinline)) void funcB(int pid) { printf("funcB %d\n", pid); }11__attribute__((noinline)) void funcC(int pid) { printf("funcC %d\n", pid); }12__attribute__((noinline)) void funcD(int pid) { printf("funcD %d\n", pid); }13__attribute__((noinline)) void funcE(int pid) { printf("funcE %d\n", pid); }14__attribute__((noinline)) void funcF(int pid) { printf("funcF %d\n", pid); }15__attribute__((noinline)) void funcG(int pid) { printf("funcG %d\n", pid); }16__attribute__((noinline)) void funcH(int pid) { printf("funcH %d\n", pid); }17__attribute__((noinline)) void funcI(int pid) { printf("funcI %d\n", pid); }18__attribute__((noinline)) void funcJ(int pid) { printf("funcJ %d\n", pid); }19__attribute__((noinline)) void funcK(int pid) { printf("funcK %d\n", pid); }20__attribute__((noinline)) void funcL(int pid) { printf("funcL %d\n", pid); }21__attribute__((noinline)) void funcM(int pid) { printf("funcM %d\n", pid); }22__attribute__((noinline)) void funcN(int pid) { printf("funcN %d\n", pid); }23__attribute__((noinline)) void funcO(int pid) { printf("funcO %d\n", pid); }24__attribute__((noinline)) void funcP(int pid) { printf("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("Failed to fork!\n");36 exit(-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,fuser54 55RUN: %clang %cflags %s -o %t.exe -Wl,-q -pie -fpie56 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-forks61 62# Instrumented program needs to finish returning zero63# Both output and profile must contain all 16 functions64# We need to use bash to invoke this as otherwise we hang inside a65# popen.communicate call in lit's internal shell. Eventually we should not66# need this.67# TODO(boomanaiden154): Remove once68# https://github.com/llvm/llvm-project/issues/156484 is fixed.69RUN: bash -c "%t.instrumented_conservative; wait" > %t.output70# We can just read because we ensure the profile will be fully written by71# calling wait inside the bash invocation.72RUN: cat %t.output | FileCheck %s --check-prefix=CHECK-OUTPUT73RUN: cat %t.fdata | FileCheck %s --check-prefix=CHECK-COMMON-PROF74 75CHECK-OUTPUT-DAG: funcA76CHECK-OUTPUT-DAG: funcB77CHECK-OUTPUT-DAG: funcC78CHECK-OUTPUT-DAG: funcD79CHECK-OUTPUT-DAG: funcE80CHECK-OUTPUT-DAG: funcF81CHECK-OUTPUT-DAG: funcG82CHECK-OUTPUT-DAG: funcH83CHECK-OUTPUT-DAG: funcI84CHECK-OUTPUT-DAG: funcJ85CHECK-OUTPUT-DAG: funcK86CHECK-OUTPUT-DAG: funcL87CHECK-OUTPUT-DAG: funcM88CHECK-OUTPUT-DAG: funcN89CHECK-OUTPUT-DAG: funcO90CHECK-OUTPUT-DAG: funcP91 92CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcA 0 0 193CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcB 0 0 194CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcC 0 0 195CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcD 0 0 196CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcE 0 0 197CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcF 0 0 198CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcG 0 0 199CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcH 0 0 1100CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcI 0 0 1101CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcJ 0 0 1102CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcK 0 0 1103CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcL 0 0 1104CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcM 0 0 1105CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcN 0 0 1106CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcO 0 0 1107CHECK-COMMON-PROF-DAG: 1 main {{[0-9a-f]+}} 1 funcP 0 0 1108 109RUN: llvm-bolt %t.exe --instrument --instrumentation-file=%t \110RUN: --instrumentation-file-append-pid \111RUN: -o %t.instrumented112 113RUN: %t.instrumented > %t.output114# Wait till output is fully written in case child outlives parent115RUN: bash %S/wait_file.sh %t.output116# Make sure all functions were called117RUN: cat %t.output | FileCheck %s --check-prefix=CHECK-OUTPUT118 119RUN: %python %S/copy_file.py %t funcA child120RUN: %python %S/copy_file.py %t funcB parent121 122# Instrumented binary must produce two profiles with only local calls123# recorded. Functions called only in child should not appear in parent's124# process and vice versa.125RUN: cat %t.child.fdata | FileCheck %s --check-prefix=CHECK-CHILD126RUN: cat %t.child.fdata | FileCheck %s --check-prefix=CHECK-NOCHILD127RUN: cat %t.parent.fdata | FileCheck %s --check-prefix=CHECK-PARENT128RUN: cat %t.parent.fdata | FileCheck %s --check-prefix=CHECK-NOPARENT129 130CHECK-CHILD-DAG: 1 main {{[0-9a-f]+}} 1 funcA 0 0 1131CHECK-CHILD-DAG: 1 main {{[0-9a-f]+}} 1 funcC 0 0 1132CHECK-CHILD-DAG: 1 main {{[0-9a-f]+}} 1 funcE 0 0 1133CHECK-CHILD-DAG: 1 main {{[0-9a-f]+}} 1 funcG 0 0 1134CHECK-CHILD-DAG: 1 main {{[0-9a-f]+}} 1 funcI 0 0 1135CHECK-CHILD-DAG: 1 main {{[0-9a-f]+}} 1 funcK 0 0 1136CHECK-CHILD-DAG: 1 main {{[0-9a-f]+}} 1 funcM 0 0 1137CHECK-CHILD-DAG: 1 main {{[0-9a-f]+}} 1 funcO 0 0 1138 139CHECK-NOCHILD-NOT: funcB140CHECK-NOCHILD-NOT: funcD141CHECK-NOCHILD-NOT: funcF142CHECK-NOCHILD-NOT: funcH143CHECK-NOCHILD-NOT: funcJ144CHECK-NOCHILD-NOT: funcL145CHECK-NOCHILD-NOT: funcN146CHECK-NOCHILD-NOT: funcP147 148CHECK-PARENT-DAG: 1 main {{[0-9a-f]+}} 1 funcB 0 0 1149CHECK-PARENT-DAG: 1 main {{[0-9a-f]+}} 1 funcD 0 0 1150CHECK-PARENT-DAG: 1 main {{[0-9a-f]+}} 1 funcF 0 0 1151CHECK-PARENT-DAG: 1 main {{[0-9a-f]+}} 1 funcH 0 0 1152CHECK-PARENT-DAG: 1 main {{[0-9a-f]+}} 1 funcJ 0 0 1153CHECK-PARENT-DAG: 1 main {{[0-9a-f]+}} 1 funcL 0 0 1154CHECK-PARENT-DAG: 1 main {{[0-9a-f]+}} 1 funcN 0 0 1155CHECK-PARENT-DAG: 1 main {{[0-9a-f]+}} 1 funcP 0 0 1156 157CHECK-NOPARENT-NOT: funcA158CHECK-NOPARENT-NOT: funcC159CHECK-NOPARENT-NOT: funcE160CHECK-NOPARENT-NOT: funcG161CHECK-NOPARENT-NOT: funcI162CHECK-NOPARENT-NOT: funcK163CHECK-NOPARENT-NOT: funcM164CHECK-NOPARENT-NOT: funcO165 166 */167