1// Regression test for
2// https://code.google.com/p/address-sanitizer/issues/detail?id=178
3
4// Assume we're on Darwin and try to pass -U to the linker. If this flag is
5// unsupported, don't use it.
6// RUN: %clangxx_asan -O0 -DSHARED_LIB %s \
7// RUN:     -fPIC -shared -o %t-so.so -Wl,-U,_inc_global || \
8// RUN:     %clangxx_asan -O0 -DSHARED_LIB %s \
9// RUN:         -fPIC -shared -o %t-so.so
10// If the linker doesn't support --export-dynamic (which is ELF-specific),
11// try to link without that option.
12// FIXME: find a better solution.
13// RUN: %clangxx_asan -O0 %s -pthread -ldl -o %t -Wl,--export-dynamic || \
14// RUN:     %clangxx_asan -O0 %s -pthread -ldl -o %t
15// RUN: ASAN_OPTIONS=strict_init_order=true %run %t 2>&1 | FileCheck %s
16#if !defined(SHARED_LIB)
17#include <dlfcn.h>
18#include <pthread.h>
19#include <stdio.h>
20#include <unistd.h>
21
22#include <string>
23
24using std::string;
25
26int foo() {
27  return 42;
28}
29int global = foo();
30
31__attribute__((visibility("default")))
32extern "C"
33void inc_global() {
34  global++;
35}
36
37void *global_poller(void *arg) {
38  while (true) {
39    if (global != 42)
40      break;
41    usleep(100);
42  }
43  return 0;
44}
45
46int main(int argc, char *argv[]) {
47  pthread_t p;
48  pthread_create(&p, 0, global_poller, 0);
49  string path = string(argv[0]) + "-so.so";
50  if (0 == dlopen(path.c_str(), RTLD_NOW)) {
51    fprintf(stderr, "dlerror: %s\n", dlerror());
52    return 1;
53  }
54  pthread_join(p, 0);
55  printf("PASSED\n");
56  // CHECK: PASSED
57  return 0;
58}
59#else  // SHARED_LIB
60#include <stdio.h>
61#include <unistd.h>
62
63extern "C" void inc_global();
64
65int slow_init() {
66  sleep(1);
67  inc_global();
68  return 42;
69}
70
71int slowly_init_glob = slow_init();
72#endif  // SHARED_LIB
73