1 | // Check that we can patch and un-patch DSOs loaded with dlopen. |
2 | // |
3 | |
4 | // RUN: split-file %s %t |
5 | // RUN: %clangxx_xray -g -fPIC -fxray-instrument -fxray-shared -shared -std=c++11 %t/testlib.cpp -o %t/testlib.so |
6 | // RUN: %clangxx_xray -g -fPIC -rdynamic -fxray-instrument -fxray-shared -std=c++11 %t/main.cpp -o %t/main.o |
7 | // |
8 | // RUN: XRAY_OPTIONS="patch_premain=true" %run %t/main.o %t/testlib.so 2>&1 | FileCheck %s |
9 | |
10 | // REQUIRES: target={{(aarch64|x86_64)-.*}} |
11 | |
12 | //--- main.cpp |
13 | |
14 | #include "xray/xray_interface.h" |
15 | |
16 | #include <cstdio> |
17 | #include <dlfcn.h> |
18 | |
19 | void test_handler(int32_t fid, XRayEntryType type) { |
20 | printf(format: "called: %d, type=%d\n" , fid, static_cast<int32_t>(type)); |
21 | } |
22 | |
23 | [[clang::xray_always_instrument]] void instrumented_in_executable() { |
24 | printf(format: "instrumented_in_executable called\n" ); |
25 | } |
26 | |
27 | typedef void (*dso_func_type)(); |
28 | |
29 | int main(int argc, char **argv) { |
30 | if (argc < 2) { |
31 | printf(format: "Shared library argument missing\n" ); |
32 | // CHECK-NOT: Shared library argument missing |
33 | return 1; |
34 | } |
35 | |
36 | const char *dso_path = argv[1]; |
37 | |
38 | void *dso_handle = dlopen(file: dso_path, RTLD_LAZY); |
39 | if (!dso_handle) { |
40 | printf(format: "Failed to load shared library\n" ); |
41 | char *error = dlerror(); |
42 | if (error) { |
43 | fprintf(stderr, format: "%s\n" , error); |
44 | return 1; |
45 | } |
46 | return 1; |
47 | } |
48 | |
49 | dso_func_type instrumented_in_dso = |
50 | (dso_func_type)dlsym(handle: dso_handle, name: "_Z19instrumented_in_dsov" ); |
51 | if (!instrumented_in_dso) { |
52 | printf(format: "Failed to find symbol\n" ); |
53 | char *error = dlerror(); |
54 | if (error) { |
55 | fprintf(stderr, format: "%s\n" , error); |
56 | return 1; |
57 | } |
58 | return 1; |
59 | } |
60 | |
61 | __xray_set_handler(entry: test_handler); |
62 | |
63 | instrumented_in_executable(); |
64 | // CHECK: called: {{.*}}, type=0 |
65 | // CHECK-NEXT: instrumented_in_executable called |
66 | // CHECK-NEXT: called: {{.*}}, type=1 |
67 | instrumented_in_dso(); |
68 | // CHECK-NEXT: called: {{.*}}, type=0 |
69 | // CHECK-NEXT: instrumented_in_dso called |
70 | // CHECK-NEXT: called: {{.*}}, type=1 |
71 | |
72 | auto status = __xray_unpatch(); |
73 | printf(format: "unpatching status: %d\n" , static_cast<int32_t>(status)); |
74 | // CHECK-NEXT: unpatching status: 1 |
75 | |
76 | instrumented_in_executable(); |
77 | // CHECK-NEXT: instrumented_in_executable called |
78 | instrumented_in_dso(); |
79 | // CHECK-NEXT: instrumented_in_dso called |
80 | |
81 | status = __xray_patch(); |
82 | printf(format: "patching status: %d\n" , static_cast<int32_t>(status)); |
83 | // CHECK-NEXT: patching status: 1 |
84 | |
85 | instrumented_in_executable(); |
86 | // CHECK-NEXT: called: {{.*}}, type=0 |
87 | // CHECK-NEXT: instrumented_in_executable called |
88 | // CHECK-NEXT: called: {{.*}}, type=1 |
89 | instrumented_in_dso(); |
90 | // CHECK-NEXT: called: {{.*}}, type=0 |
91 | // CHECK-NEXT: instrumented_in_dso called |
92 | // CHECK-NEXT: called: {{.*}}, type=1 |
93 | |
94 | dlclose(handle: dso_handle); |
95 | |
96 | status = __xray_unpatch(); |
97 | printf(format: "unpatching status: %d\n" , static_cast<int32_t>(status)); |
98 | // CHECK-NEXT: unpatching status: 1 |
99 | } |
100 | |
101 | //--- testlib.cpp |
102 | |
103 | #include <cstdio> |
104 | |
105 | [[clang::xray_always_instrument]] void instrumented_in_dso() { |
106 | printf(format: "instrumented_in_dso called\n" ); |
107 | } |
108 | |