1// Check that loading libraries with different modes (RTLD_LOCAL/RTLD_GLOBAL)
2// and dependencies on other DSOs work correctly.
3//
4
5// RUN: split-file %s %t
6//
7// Build shared libs with dependencies b->c and e->f
8// RUN: %clangxx_xray -g -fPIC -fxray-instrument -fxray-shared -shared -std=c++11 %t/testliba.cpp -o %t/testliba.so
9// RUN: %clangxx_xray -g -fPIC -fxray-instrument -fxray-shared -shared -std=c++11 %t/testlibc.cpp -o %t/testlibc.so
10// RUN: %clangxx_xray -g -fPIC -fxray-instrument -fxray-shared -shared -std=c++11 %t/testlibb.cpp %t/testlibc.so -o %t/testlibb.so
11// RUN: %clangxx_xray -g -fPIC -fxray-instrument -fxray-shared -shared -std=c++11 %t/testlibd.cpp -o %t/testlibd.so
12// RUN: %clangxx_xray -g -fPIC -fxray-instrument -fxray-shared -shared -std=c++11 %t/testlibf.cpp -o %t/testlibf.so
13// RUN: %clangxx_xray -g -fPIC -fxray-instrument -fxray-shared -shared -std=c++11 %t/testlibe.cpp %t/testlibf.so -o %t/testlibe.so
14//
15// Executable links with a and b explicitly and loads d and e at runtime.
16// RUN: %clangxx_xray -g -fPIC -rdynamic -fxray-instrument -fxray-shared -std=c++11 %t/main.cpp %t/testliba.so %t/testlibb.so -o %t/main.o
17//
18// RUN: XRAY_OPTIONS="patch_premain=true" %run %t/main.o %t/testlibd.so %t/testlibe.so 2>&1 | FileCheck %s
19
20// REQUIRES: target={{(aarch64|x86_64)-.*}}
21
22//--- main.cpp
23
24#include "xray/xray_interface.h"
25
26#include <cstdio>
27#include <dlfcn.h>
28
29[[clang::xray_never_instrument]] void test_handler(int32_t fid,
30 XRayEntryType type) {
31 printf(format: "called: %d, object=%d, fn=%d, type=%d\n", fid, (fid >> 24) & 0xFF,
32 fid & 0x00FFFFFF, static_cast<int32_t>(type));
33}
34
35[[clang::xray_always_instrument]] void instrumented_in_executable() {
36 printf(format: "instrumented_in_executable called\n");
37}
38
39typedef void (*dso_func_type)();
40
41[[clang::xray_never_instrument]] void *load_dso(const char *path, int mode) {
42 void *dso_handle = dlopen(file: path, mode: mode);
43 if (!dso_handle) {
44 printf(format: "failed to load shared library\n");
45 char *error = dlerror();
46 if (error) {
47 fprintf(stderr, format: "%s\n", error);
48 }
49 return nullptr;
50 }
51 return dso_handle;
52}
53
54[[clang::xray_never_instrument]] void find_and_call(void *dso_handle,
55 const char *fn) {
56 dso_func_type dso_fn = (dso_func_type)dlsym(handle: dso_handle, name: fn);
57 if (!dso_fn) {
58 printf(format: "failed to find symbol\n");
59 char *error = dlerror();
60 if (error) {
61 fprintf(stderr, format: "%s\n", error);
62 }
63 return;
64 }
65 dso_fn();
66}
67
68extern void a();
69extern void b();
70
71int main(int argc, char **argv) {
72
73 if (argc < 3) {
74 printf(format: "Shared library arguments missing\n");
75 // CHECK-NOT: Shared library arguments missing
76 return 1;
77 }
78
79 const char *dso_path_d = argv[1];
80 const char *dso_path_e = argv[2];
81
82 __xray_set_handler(entry: test_handler);
83
84 instrumented_in_executable();
85 // CHECK: called: {{[0-9]+}}, object=0, fn={{[0-9]+}}, type=0
86 // CHECK-NEXT: instrumented_in_executable called
87 // CHECK-NEXT: called: {{[0-9]+}}, object=0, fn={{[0-9]+}}, type=1
88
89 a();
90 // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ1:[0-9]+]], fn=1, type=0
91 // CHECK-NEXT: a called
92 // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ1]], fn=1, type=1
93
94 // Make sure this object ID does not appear again
95 // CHECK-NOT: called: {{[0-9]+}}, object=[[OBJ1]]
96
97 b(); // b calls c
98 // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ2:[0-9]+]], fn=1, type=0
99 // CHECK-NEXT: b called
100 // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ3:[0-9]+]], fn=1, type=0
101 // CHECK-NEXT: c called
102 // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ3]], fn=1, type=1
103 // CHECK-NOT: called: {{[0-9]+}}, object=[[OBJ3]]
104 // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ2]], fn=1, type=1
105 // CHECK-NOT: called: {{[0-9]+}}, object=[[OBJ2]]
106
107 // Now check explicit loading with RTLD_LOCAL
108
109 void *dso_handle_d = load_dso(path: dso_path_d, RTLD_LAZY | RTLD_LOCAL);
110 void *dso_handle_e = load_dso(path: dso_path_e, RTLD_LAZY | RTLD_LOCAL);
111 // CHECK-NOT: failed to load shared library
112
113 find_and_call(dso_handle: dso_handle_d, fn: "_Z1dv");
114 // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ4:[0-9]+]], fn=1, type=0
115 // CHECK-NEXT: d called
116 // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ4]], fn=1, type=1
117 // CHECK-NOT: called: {{[0-9]+}}, object=[[OBJ4]]
118
119 find_and_call(dso_handle: dso_handle_e, fn: "_Z1ev");
120 // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ5:[0-9]+]], fn=1, type=0
121 // CHECK-NEXT: e called
122 // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ6:[0-9]+]], fn=1, type=0
123 // CHECK-NEXT: f called
124 // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ6]], fn=1, type=1
125 // CHECK-NOT: called: {{[0-9]+}}, object=[[OBJ6]]
126 // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ5]], fn=1, type=1
127 // CHECK-NOT: called: {{[0-9]+}}, object=[[OBJ5]]
128
129 // Unload DSOs
130 dlclose(handle: dso_handle_d);
131 dlclose(handle: dso_handle_e);
132
133 // Repeat test with RTLD_GLOBAL
134 dso_handle_d = load_dso(path: dso_path_d, RTLD_LAZY | RTLD_GLOBAL);
135 dso_handle_e = load_dso(path: dso_path_e, RTLD_LAZY | RTLD_GLOBAL);
136 // CHECK-NOT: failed to load shared library
137
138 find_and_call(dso_handle: dso_handle_d, fn: "_Z1dv");
139 // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ7:[0-9]+]], fn=1, type=0
140 // CHECK-NEXT: d called
141 // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ7]], fn=1, type=1
142 // CHECK-NOT: called: {{[0-9]+}}, object=[[OBJ7]]
143
144 find_and_call(dso_handle: dso_handle_e, fn: "_Z1ev");
145 // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ8:[0-9]+]], fn=1, type=0
146 // CHECK-NEXT: e called
147 // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ9:[0-9]+]], fn=1, type=0
148 // CHECK-NEXT: f called
149 // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ9]], fn=1, type=1
150 // CHECK-NOT: called: {{[0-9]+}}, object=[[OBJ9]]
151 // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ8]], fn=1, type=1
152 // CHECK-NOT: called: {{[0-9]+}}, object=[[OBJ8]]
153
154 auto status = __xray_unpatch();
155 printf(format: "unpatching status: %d\n", static_cast<int32_t>(status));
156 // CHECK-NEXT: unpatching status: 1
157
158 dlclose(handle: dso_handle_d);
159 dlclose(handle: dso_handle_e);
160}
161
162//--- libgenmacro.inc
163#include <cstdio>
164// Helper macros to quickly generate libraries containing a single function.
165#define GENERATE_LIB(NAME) \
166 [[clang::xray_always_instrument]] void NAME() { printf(#NAME " called\n"); }
167
168#define GENERATE_LIB_WITH_CALL(NAME, FN) \
169 extern void FN(); \
170 [[clang::xray_always_instrument]] void NAME() { \
171 printf(#NAME " called\n"); \
172 FN(); \
173 }
174
175//--- testliba.cpp
176#include "libgenmacro.inc"
177GENERATE_LIB(a)
178
179//--- testlibb.cpp
180#include "libgenmacro.inc"
181GENERATE_LIB_WITH_CALL(b, c)
182
183//--- testlibc.cpp
184#include "libgenmacro.inc"
185GENERATE_LIB(c)
186
187//--- testlibd.cpp
188#include "libgenmacro.inc"
189GENERATE_LIB(d)
190
191//--- testlibe.cpp
192#include "libgenmacro.inc"
193GENERATE_LIB_WITH_CALL(e, f)
194
195//--- testlibf.cpp
196#include "libgenmacro.inc"
197GENERATE_LIB(f)
198

source code of compiler-rt/test/xray/TestCases/Posix/dso-dep-chains.cpp