1 // Regression test for 2 // http://code.google.com/p/address-sanitizer/issues/detail?id=19 3 // Bug description: 4 // 1. application dlopens foo.so 5 // 2. asan registers all globals from foo.so 6 // 3. application dlcloses foo.so 7 // 4. application mmaps some memory to the location where foo.so was before 8 // 5. application starts using this mmaped memory, but asan still thinks there 9 // are globals. 10 // 6. BOOM 11 12 // RUN: %clangxx_asan -m64 -O0 %p/SharedLibs/dlclose-test-so.cc \ 13 // RUN: -fPIC -shared -o %t-so.so 14 // RUN: %clangxx_asan -m64 -O0 %s -o %t && %t 2>&1 | FileCheck %s 15 // RUN: %clangxx_asan -m64 -O1 %p/SharedLibs/dlclose-test-so.cc \ 16 // RUN: -fPIC -shared -o %t-so.so 17 // RUN: %clangxx_asan -m64 -O1 %s -o %t && %t 2>&1 | FileCheck %s 18 // RUN: %clangxx_asan -m64 -O2 %p/SharedLibs/dlclose-test-so.cc \ 19 // RUN: -fPIC -shared -o %t-so.so 20 // RUN: %clangxx_asan -m64 -O2 %s -o %t && %t 2>&1 | FileCheck %s 21 // RUN: %clangxx_asan -m64 -O3 %p/SharedLibs/dlclose-test-so.cc \ 22 // RUN: -fPIC -shared -o %t-so.so 23 // RUN: %clangxx_asan -m64 -O3 %s -o %t && %t 2>&1 | FileCheck %s 24 // RUN: %clangxx_asan -m32 -O0 %p/SharedLibs/dlclose-test-so.cc \ 25 // RUN: -fPIC -shared -o %t-so.so 26 // RUN: %clangxx_asan -m32 -O0 %s -o %t && %t 2>&1 | FileCheck %s 27 // RUN: %clangxx_asan -m32 -O1 %p/SharedLibs/dlclose-test-so.cc \ 28 // RUN: -fPIC -shared -o %t-so.so 29 // RUN: %clangxx_asan -m32 -O1 %s -o %t && %t 2>&1 | FileCheck %s 30 // RUN: %clangxx_asan -m32 -O2 %p/SharedLibs/dlclose-test-so.cc \ 31 // RUN: -fPIC -shared -o %t-so.so 32 // RUN: %clangxx_asan -m32 -O2 %s -o %t && %t 2>&1 | FileCheck %s 33 // RUN: %clangxx_asan -m32 -O3 %p/SharedLibs/dlclose-test-so.cc \ 34 // RUN: -fPIC -shared -o %t-so.so 35 // RUN: %clangxx_asan -m32 -O3 %s -o %t && %t 2>&1 | FileCheck %s 36 37 #include <assert.h> 38 #include <dlfcn.h> 39 #include <stdio.h> 40 #include <string.h> 41 #include <sys/mman.h> 42 43 #include <string> 44 45 using std::string; 46 47 static const int kPageSize = 4096; 48 49 typedef int *(fun_t)(); 50 51 int main(int argc, char *argv[]) { 52 string path = string(argv[0]) + "-so.so"; 53 printf("opening %s ... \n", path.c_str()); 54 void *lib = dlopen(path.c_str(), RTLD_NOW); 55 if (!lib) { 56 printf("error in dlopen(): %s\n", dlerror()); 57 return 1; 58 } 59 fun_t *get = (fun_t*)dlsym(lib, "get_address_of_static_var"); 60 if (!get) { 61 printf("failed dlsym\n"); 62 return 1; 63 } 64 int *addr = get(); 65 assert(((size_t)addr % 32) == 0); // should be 32-byte aligned. 66 printf("addr: %p\n", addr); 67 addr[0] = 1; // make sure we can write there. 68 69 // Now dlclose the shared library. 70 printf("attempting to dlclose\n"); 71 if (dlclose(lib)) { 72 printf("failed to dlclose\n"); 73 return 1; 74 } 75 // Now, the page where 'addr' is unmapped. Map it. 76 size_t page_beg = ((size_t)addr) & ~(kPageSize - 1); 77 void *res = mmap((void*)(page_beg), kPageSize, 78 PROT_READ | PROT_WRITE, 79 MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE, 0, 0); 80 if (res == (char*)-1L) { 81 printf("failed to mmap\n"); 82 return 1; 83 } 84 addr[1] = 2; // BOOM (if the bug is not fixed). 85 printf("PASS\n"); 86 // CHECK: PASS 87 return 0; 88 } 89