1 // Check that loading libraries with different modes (RTLD_LOCAL/RTLD_GLOBAL)
2 // and dependencies on other DSOs work correctly.
5 // RUN: split-file %s %t
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
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
18 // RUN: XRAY_OPTIONS="patch_premain=true" %run %t/main.o %t/testlibd.so %t/testlibe.so 2>&1 | FileCheck %s
20 // REQUIRES: target={{(aarch64|x86_64)-.*}}
24 #include "xray/xray_interface.h"
29 [[clang::xray_never_instrument
]] void test_handler(int32_t fid
,
31 printf("called: %d, object=%d, fn=%d, type=%d\n", fid
, (fid
>> 24) & 0xFF,
32 fid
& 0x00FFFFFF, static_cast<int32_t>(type
));
35 [[clang::xray_always_instrument
]] void instrumented_in_executable() {
36 printf("instrumented_in_executable called\n");
39 typedef void (*dso_func_type
)();
41 [[clang::xray_never_instrument
]] void *load_dso(const char *path
, int mode
) {
42 void *dso_handle
= dlopen(path
, mode
);
44 printf("failed to load shared library\n");
45 char *error
= dlerror();
47 fprintf(stderr
, "%s\n", error
);
54 [[clang::xray_never_instrument
]] void find_and_call(void *dso_handle
,
56 dso_func_type dso_fn
= (dso_func_type
)dlsym(dso_handle
, fn
);
58 printf("failed to find symbol\n");
59 char *error
= dlerror();
61 fprintf(stderr
, "%s\n", error
);
71 int main(int argc
, char **argv
) {
74 printf("Shared library arguments missing\n");
75 // CHECK-NOT: Shared library arguments missing
79 const char *dso_path_d
= argv
[1];
80 const char *dso_path_e
= argv
[2];
82 __xray_set_handler(test_handler
);
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
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
94 // Make sure this object ID does not appear again
95 // CHECK-NOT: called: {{[0-9]+}}, object=[[OBJ1]]
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]]
107 // Now check explicit loading with RTLD_LOCAL
109 void *dso_handle_d
= load_dso(dso_path_d
, RTLD_LAZY
| RTLD_LOCAL
);
110 void *dso_handle_e
= load_dso(dso_path_e
, RTLD_LAZY
| RTLD_LOCAL
);
111 // CHECK-NOT: failed to load shared library
113 find_and_call(dso_handle_d
, "_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]]
119 find_and_call(dso_handle_e
, "_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]]
130 dlclose(dso_handle_d
);
131 dlclose(dso_handle_e
);
133 // Repeat test with RTLD_GLOBAL
134 dso_handle_d
= load_dso(dso_path_d
, RTLD_LAZY
| RTLD_GLOBAL
);
135 dso_handle_e
= load_dso(dso_path_e
, RTLD_LAZY
| RTLD_GLOBAL
);
136 // CHECK-NOT: failed to load shared library
138 find_and_call(dso_handle_d
, "_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]]
144 find_and_call(dso_handle_e
, "_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]]
154 auto status
= __xray_unpatch();
155 printf("unpatching status: %d\n", static_cast<int32_t>(status
));
156 // CHECK-NEXT: unpatching status: 1
158 dlclose(dso_handle_d
);
159 dlclose(dso_handle_e
);
162 //--- libgenmacro.inc
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"); }
168 #define GENERATE_LIB_WITH_CALL(NAME, FN) \
170 [[clang::xray_always_instrument]] void NAME() { \
171 printf(#NAME " called\n"); \
176 #include "libgenmacro.inc"
180 #include "libgenmacro.inc"
181 GENERATE_LIB_WITH_CALL(b
, c
)
184 #include "libgenmacro.inc"
188 #include "libgenmacro.inc"
192 #include "libgenmacro.inc"
193 GENERATE_LIB_WITH_CALL(e
, f
)
196 #include "libgenmacro.inc"