1 // Test that captures the current behavior of indicator-based ASan ODR checker 2 // when globals get unregistered. 3 // 4 // RUN: %clangxx_asan -g -O0 -DSHARED_LIB -DSIZE=1 %s -fPIC -shared -o %t-so-1.so 5 // RUN: %clangxx_asan -g -O0 -DSHARED_LIB -DSIZE=2 %s -fPIC -shared -o %t-so-2.so 6 // RUN: %clangxx_asan -g -O0 %s %libdl -Wl,--export-dynamic -o %t 7 // RUN: %env_asan_opts=report_globals=2:detect_odr_violation=1 %run %t 2>&1 | FileCheck %s 8 9 // FIXME: Checks do not match on Android. 10 // UNSUPPORTED: android 11 12 #include <cstdlib> 13 #include <dlfcn.h> 14 #include <stdio.h> 15 #include <string> 16 17 #ifdef SHARED_LIB 18 namespace foo { 19 char G[SIZE]; 20 } 21 #else // SHARED_LIB 22 void *dlopen_or_die(std::string &path) { 23 void *handle = dlopen(path.c_str(), RTLD_NOW); 24 if (handle) { 25 printf("Successfully called dlopen() on %s\n", path.c_str()); 26 } else { 27 printf("Error in dlopen(): %s\n", dlerror()); 28 std::exit(1); 29 } 30 31 return handle; 32 } 33 34 void dlclose_or_die(void *handle, std::string &path) { 35 if (!dlclose(handle)) { 36 printf("Successfully called dlclose() on %s\n", path.c_str()); 37 } else { 38 printf("Error in dlclose(): %s\n", dlerror()); 39 std::exit(1); 40 } 41 } 42 43 namespace foo { 44 char G[1]; 45 } 46 47 // main has its own version of foo::G 48 // CHECK: Added Global[[MAIN_G:[^\s]+]] size=1/32 name=foo::G {{.*}} 49 int main(int argc, char *argv[]) { 50 std::string base_path = std::string(argv[0]); 51 52 std::string path1 = base_path + "-so-1.so"; 53 // dlopen() brings another foo::G but it matches MAIN_G in size so it's not a 54 // violation 55 // 56 // 57 // CHECK: Added Global[[SO1_G:[^\s]+]] size=1/32 name=foo::G {{.*}} 58 // CHECK-NOT: ERROR: AddressSanitizer: odr-violation 59 void *handle1 = dlopen_or_die(path1); 60 // CHECK: Removed Global[[SO1_G]] size=1/32 name=foo::G {{.*}} 61 dlclose_or_die(handle1, path1); 62 63 // At this point the indicator for foo::G is switched to UNREGISTERED for 64 // **both** MAIN_G and SO1_G because the indicator value is shared. 65 66 std::string path2 = base_path + "-so-2.so"; 67 // CHECK: Added Global[[SO2_G:[^\s]+]] size=2/32 name=foo::G {{.*}} 68 // 69 // This brings another foo::G but now different in size from MAIN_G. We 70 // should've reported a violation, but we actually don't because of what's 71 // described on line60 72 // 73 // CHECK-NOT: ERROR: AddressSanitizer: odr-violation 74 void *handle2 = dlopen_or_die(path2); 75 // CHECK: Removed Global[[MAIN_G]] size=1/32 name=foo::G {{.*}} 76 // CHECK: Removed Global[[SO2_G]] size=2/32 name=foo::G {{.*}} 77 } 78 79 #endif // SHARED_LIB 80