xref: /llvm-project/compiler-rt/test/profile/Posix/instrprof-dlopen-norpath.test (revision d084bc291a21895fa2ecc74e2d1c9d1818ba4fd7)
1XFAIL: target={{.*haiku.*}}
2RUN: rm -rf %t && split-file %s %t && cd %t
3RUN: %clang_pgogen -fprofile-update=atomic -fPIC foo.c -c -Xclang -fprofile-instrument-path="default_foo_%m.profraw"
4RUN: %clang_pgogen -fprofile-update=atomic -fPIC foo2.c -c -Xclang -fprofile-instrument-path="default_foo2_%m.profraw"
5RUN: %clang_pgogen -fprofile-update=atomic -shared foo.o -o shr_foo.o %if target={{.*aix.*}} %{ -bcdtors:mbr %}
6RUN: %clang_pgogen -fprofile-update=atomic -shared foo2.o -o shr_foo2.o
7
8RUN: %clang_pgogen common.c -c
9
10RUN: %clang_pgogen test1.c common.o -Xclang -fprofile-instrument-path="default_test1_%m.profraw"
11RUN: ./a.out 2>&1 | FileCheck %s -check-prefix=CHECK-FOO
12RUN: llvm-profdata show default_test1_*.profraw --counts --all-functions 2>&1 | \
13RUN:   FileCheck %s -check-prefix=CHECK-TEST1
14RUN: rm -f default*
15
16RUN: %clang_pgogen test2.c common.o -Xclang -fprofile-instrument-path="default_test2_%m.profraw"
17RUN: ./a.out 2>&1 | FileCheck %s -check-prefix=CHECK-FOO
18RUN: llvm-profdata show default_test2_*.profraw --counts --all-functions 2>&1 | \
19RUN:   FileCheck %s -check-prefix=CHECK-TEST2
20RUN: rm -f default*
21
22RUN: %clangxx_pgogen -lpthread test3.cpp common.o -Xclang -fprofile-instrument-path="default_test3_%m.profraw"
23RUN: ./a.out 2>&1 | FileCheck %s -check-prefix=CHECK-FOO-FOUR-THREADS
24
25CHECK-FOO:  foo:
26CHECK-FOO:    Block counts: [1]
27CHECK-FOO:  foo2:
28CHECK-FOO:    Block counts: [1]
29CHECK-FOO:  foo:
30CHECK-FOO:    Block counts: [2]
31
32CHECK-FOO-FOUR-THREADS:  foo:
33CHECK-FOO-FOUR-THREADS:    Block counts: [8]
34CHECK-FOO-FOUR-THREADS:  foo2:
35CHECK-FOO-FOUR-THREADS:    Block counts: [4]
36
37CHECK-TEST1:  main:
38CHECK-TEST1:    Block counts: [1, 0, 1, 0, 1, 1, 0]
39
40CHECK-TEST2: func1:
41CHECK-TEST2: Block counts: [4]
42CHECK-TEST2:  func2:
43CHECK-TEST2: Block counts: [1]
44
45
46//--- foo.c
47void foo() {}
48
49//--- foo2.c
50void foo2() {}
51
52//--- common.c
53#include <dlfcn.h>
54#include <stdio.h>
55#include <stdlib.h>
56typedef void (*FN_PTR)();
57int perform_check = 1;
58
59/* This function dlopen/dlclose shr_foo.a twice and shr_foo2.a once. Each time it
60 * dlopens a library, it runs the singleton function from that library. So the
61 * final counter value for foo and foo2 in each profile file is 2 and 1, resp.
62 */
63int open_close_libs() {
64  void *handle, *handle2;
65  FN_PTR foo, foo2;
66
67#define OPEN_AND_RUN(HANDLE, SUF)                                            \
68  HANDLE = dlopen("./shr_" #SUF ".o", RTLD_NOW);                             \
69  SUF = (void (*)())dlsym(HANDLE, #SUF);                                     \
70  if (SUF == NULL) {                                                         \
71    fprintf(stderr, "unable to lookup symbol '%s': %s\n", #SUF, dlerror());  \
72    return EXIT_FAILURE;                                                     \
73  }                                                                          \
74  SUF();
75
76#define CHECK_ONLY(SUF)                                                      \
77  system("llvm-profdata show default_" #SUF "_*.profraw --counts --all-functions");
78
79#define CLOSE_AND_CHECK(HANDLE, SUF)                                         \
80  dlclose(HANDLE);                                                           \
81  if (perform_check) { CHECK_ONLY(SUF) }
82
83  OPEN_AND_RUN(handle, foo)
84  CLOSE_AND_CHECK(handle, foo)
85
86  OPEN_AND_RUN(handle2, foo2)
87  OPEN_AND_RUN(handle, foo)
88  CLOSE_AND_CHECK(handle2, foo2)
89  CLOSE_AND_CHECK(handle, foo)
90  return EXIT_SUCCESS;
91}
92void check_prof_files() {
93  CHECK_ONLY(foo)
94  CHECK_ONLY(foo2)
95}
96
97//--- test1.c
98int open_close_libs();
99int main() {
100  open_close_libs();
101}
102
103//--- test2.c
104#include <dlfcn.h>
105#include <stdio.h>
106#include <stdlib.h>
107#include <sys/wait.h>
108#include <unistd.h>
109
110__attribute__((noinline)) void func1() {}
111__attribute__((noinline)) void func2() {}
112void open_close_libs();
113
114int main(void) {
115  int status;
116  func1();
117  pid_t pid = fork();
118  if (pid == -1)
119    return 1;
120  if (pid == 0) { // child
121    open_close_libs();
122    func2();
123  }
124  func1();
125  if (pid)
126    wait(&status);
127  return 0;
128}
129
130//--- test3.cpp
131#include <sys/types.h>
132#include <thread>
133#include <unistd.h>
134
135extern "C" void check_prof_files();
136extern "C" void open_close_libs();
137extern int perform_check;
138
139template <typename T>
140void launcher(T func) {
141  auto t1 = std::thread(func);
142  auto t2 = std::thread(func);
143  auto t3 = std::thread(func);
144  auto t4 = std::thread(func);
145
146  t1.join();
147  t2.join();
148  t3.join();
149  t4.join();
150}
151
152int main() {
153  // don't check profiles generate inside open_close_libs because
154  // you'll get non-deterministic output due to threading.
155  perform_check = 0;
156  launcher<>(open_close_libs);
157
158  // instead, check the profiles manually here in the main thread.
159  check_prof_files();
160  return 0;
161}
162