1673dc3d4SNico Weber // Check that unloading a module doesn't break coverage dumping for remaining
2673dc3d4SNico Weber // modules.
3673dc3d4SNico Weber // RUN: %clangxx_asan -fsanitize-coverage=func,trace-pc-guard -DSHARED %s -shared -o %dynamiclib1 -fPIC
4673dc3d4SNico Weber // RUN: %clangxx_asan -fsanitize-coverage=func,trace-pc-guard -DSHARED %s -shared -o %dynamiclib2 -fPIC
5673dc3d4SNico Weber // RUN: %clangxx_asan -fsanitize-coverage=func,trace-pc-guard %s %libdl -o %t.exe
6673dc3d4SNico Weber // RUN: mkdir -p %t.tmp/coverage-module-unloaded && cd %t.tmp/coverage-module-unloaded
7673dc3d4SNico Weber // RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t.exe %dynamiclib1 %dynamiclib2 2>&1        | FileCheck %s
8673dc3d4SNico Weber // RUN: %env_asan_opts=coverage=1:verbosity=1 %run %t.exe %dynamiclib1 %dynamiclib2 foo 2>&1    | FileCheck %s
9673dc3d4SNico Weber //
10673dc3d4SNico Weber // https://code.google.com/p/address-sanitizer/issues/detail?id=263
11673dc3d4SNico Weber // XFAIL: android
12673dc3d4SNico Weber // UNSUPPORTED: ios
13673dc3d4SNico Weber 
14673dc3d4SNico Weber #include <assert.h>
15673dc3d4SNico Weber #include <dlfcn.h>
16*ad14b5b0SMatheus Izvekov #include <stdint.h>
17673dc3d4SNico Weber #include <stdio.h>
18673dc3d4SNico Weber #include <unistd.h>
19673dc3d4SNico Weber 
20673dc3d4SNico Weber #ifdef SHARED
21673dc3d4SNico Weber extern "C" {
bar()22673dc3d4SNico Weber void bar() { printf("bar\n"); }
23673dc3d4SNico Weber }
24673dc3d4SNico Weber #else
25673dc3d4SNico Weber 
main(int argc,char ** argv)26673dc3d4SNico Weber int main(int argc, char **argv) {
27673dc3d4SNico Weber   fprintf(stderr, "PID: %d\n", getpid());
28673dc3d4SNico Weber   assert(argc > 2);
29673dc3d4SNico Weber   void *handle1 = dlopen(argv[1], RTLD_LAZY);  // %dynamiclib1
30673dc3d4SNico Weber   assert(handle1);
31673dc3d4SNico Weber   void (*bar1)() = (void (*)())dlsym(handle1, "bar");
32673dc3d4SNico Weber   assert(bar1);
33673dc3d4SNico Weber   bar1();
34673dc3d4SNico Weber   void *handle2 = dlopen(argv[2], RTLD_LAZY);  // %dynamiclib2
35673dc3d4SNico Weber   assert(handle2);
36673dc3d4SNico Weber   void (*bar2)() = (void (*)())dlsym(handle2, "bar");
37673dc3d4SNico Weber   assert(bar2);
38673dc3d4SNico Weber   bar2();
39673dc3d4SNico Weber 
40673dc3d4SNico Weber   // It matters whether the unloaded module has a higher or lower address range
41673dc3d4SNico Weber   // than the remaining one. Make sure to test both cases.
42*ad14b5b0SMatheus Izvekov   bool lt = reinterpret_cast<uintptr_t>(bar1) < reinterpret_cast<uintptr_t>(bar2);
43673dc3d4SNico Weber   if (argc < 2)
44*ad14b5b0SMatheus Izvekov     dlclose(lt ? handle1 : handle2);
45673dc3d4SNico Weber   else
46*ad14b5b0SMatheus Izvekov     dlclose(lt ? handle2 : handle1);
47673dc3d4SNico Weber   return 0;
48673dc3d4SNico Weber }
49673dc3d4SNico Weber #endif
50673dc3d4SNico Weber 
51673dc3d4SNico Weber // CHECK: PID: [[PID:[0-9]+]]
52673dc3d4SNico Weber // CHECK-DAG: exe{{.*}}[[PID]].sancov: {{.*}}PCs written
53673dc3d4SNico Weber // CHECK-DAG: dynamic{{.*}}[[PID]].sancov: {{.*}}PCs written
54