198 lines · cpp
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 %t6//7// Build shared libs with dependencies b->c and e->f8// RUN: %clangxx_xray -g -fPIC -fxray-instrument -fxray-shared -shared -std=c++11 %t/testliba.cpp -o %t/testliba.so9// RUN: %clangxx_xray -g -fPIC -fxray-instrument -fxray-shared -shared -std=c++11 %t/testlibc.cpp -o %t/testlibc.so10// RUN: %clangxx_xray -g -fPIC -fxray-instrument -fxray-shared -shared -std=c++11 %t/testlibb.cpp %t/testlibc.so -o %t/testlibb.so11// RUN: %clangxx_xray -g -fPIC -fxray-instrument -fxray-shared -shared -std=c++11 %t/testlibd.cpp -o %t/testlibd.so12// RUN: %clangxx_xray -g -fPIC -fxray-instrument -fxray-shared -shared -std=c++11 %t/testlibf.cpp -o %t/testlibf.so13// RUN: %clangxx_xray -g -fPIC -fxray-instrument -fxray-shared -shared -std=c++11 %t/testlibe.cpp %t/testlibf.so -o %t/testlibe.so14//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.o17//18// RUN: env XRAY_OPTIONS="patch_premain=true" %run %t/main.o %t/testlibd.so %t/testlibe.so 2>&1 | FileCheck %s19 20// REQUIRES: target={{(aarch64|x86_64)-.*}}21 22//--- main.cpp23 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("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("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(path, mode);43 if (!dso_handle) {44 printf("failed to load shared library\n");45 char *error = dlerror();46 if (error) {47 fprintf(stderr, "%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(dso_handle, fn);57 if (!dso_fn) {58 printf("failed to find symbol\n");59 char *error = dlerror();60 if (error) {61 fprintf(stderr, "%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("Shared library arguments missing\n");75 // CHECK-NOT: Shared library arguments missing76 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(test_handler);83 84 instrumented_in_executable();85 // CHECK: called: {{[0-9]+}}, object=0, fn={{[0-9]+}}, type=086 // CHECK-NEXT: instrumented_in_executable called87 // CHECK-NEXT: called: {{[0-9]+}}, object=0, fn={{[0-9]+}}, type=188 89 a();90 // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ1:[0-9]+]], fn=1, type=091 // CHECK-NEXT: a called92 // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ1]], fn=1, type=193 94 // Make sure this object ID does not appear again95 // CHECK-NOT: called: {{[0-9]+}}, object=[[OBJ1]]96 97 b(); // b calls c98 // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ2:[0-9]+]], fn=1, type=099 // CHECK-NEXT: b called100 // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ3:[0-9]+]], fn=1, type=0101 // CHECK-NEXT: c called102 // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ3]], fn=1, type=1103 // CHECK-NOT: called: {{[0-9]+}}, object=[[OBJ3]]104 // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ2]], fn=1, type=1105 // CHECK-NOT: called: {{[0-9]+}}, object=[[OBJ2]]106 107 // Now check explicit loading with RTLD_LOCAL108 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 library112 113 find_and_call(dso_handle_d, "_Z1dv");114 // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ4:[0-9]+]], fn=1, type=0115 // CHECK-NEXT: d called116 // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ4]], fn=1, type=1117 // CHECK-NOT: called: {{[0-9]+}}, object=[[OBJ4]]118 119 find_and_call(dso_handle_e, "_Z1ev");120 // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ5:[0-9]+]], fn=1, type=0121 // CHECK-NEXT: e called122 // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ6:[0-9]+]], fn=1, type=0123 // CHECK-NEXT: f called124 // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ6]], fn=1, type=1125 // CHECK-NOT: called: {{[0-9]+}}, object=[[OBJ6]]126 // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ5]], fn=1, type=1127 // CHECK-NOT: called: {{[0-9]+}}, object=[[OBJ5]]128 129 // Unload DSOs130 dlclose(dso_handle_d);131 dlclose(dso_handle_e);132 133 // Repeat test with RTLD_GLOBAL134 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 library137 138 find_and_call(dso_handle_d, "_Z1dv");139 // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ7:[0-9]+]], fn=1, type=0140 // CHECK-NEXT: d called141 // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ7]], fn=1, type=1142 // CHECK-NOT: called: {{[0-9]+}}, object=[[OBJ7]]143 144 find_and_call(dso_handle_e, "_Z1ev");145 // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ8:[0-9]+]], fn=1, type=0146 // CHECK-NEXT: e called147 // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ9:[0-9]+]], fn=1, type=0148 // CHECK-NEXT: f called149 // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ9]], fn=1, type=1150 // CHECK-NOT: called: {{[0-9]+}}, object=[[OBJ9]]151 // CHECK-NEXT: called: {{[0-9]+}}, object=[[OBJ8]], fn=1, type=1152 // CHECK-NOT: called: {{[0-9]+}}, object=[[OBJ8]]153 154 auto status = __xray_unpatch();155 printf("unpatching status: %d\n", static_cast<int32_t>(status));156 // CHECK-NEXT: unpatching status: 1157 158 dlclose(dso_handle_d);159 dlclose(dso_handle_e);160}161 162//--- libgenmacro.inc163#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.cpp176#include "libgenmacro.inc"177GENERATE_LIB(a)178 179//--- testlibb.cpp180#include "libgenmacro.inc"181GENERATE_LIB_WITH_CALL(b, c)182 183//--- testlibc.cpp184#include "libgenmacro.inc"185GENERATE_LIB(c)186 187//--- testlibd.cpp188#include "libgenmacro.inc"189GENERATE_LIB(d)190 191//--- testlibe.cpp192#include "libgenmacro.inc"193GENERATE_LIB_WITH_CALL(e, f)194 195//--- testlibf.cpp196#include "libgenmacro.inc"197GENERATE_LIB(f)198