1 // REQUIRES: asan-64-bits
2 // Stress test dynamic TLS + dlopen + threads.
4 // Note that glibc 2.15 seems utterly broken on this test,
5 // it fails with ~17 DSOs dlopen-ed.
6 // glibc 2.19 seems fine.
9 // RUN: %clangxx_asan -x c -DSO_NAME=f0 %s -shared -o %t-f0.so -fPIC
10 // RUN: %clangxx_asan -x c -DSO_NAME=f1 %s -shared -o %t-f1.so -fPIC
11 // RUN: %clangxx_asan -x c -DSO_NAME=f2 %s -shared -o %t-f2.so -fPIC
12 // RUN: %clangxx_asan %s -o %t
15 // RUN: ASAN_OPTIONS=verbosity=2 %t 2 2 2>&1 | FileCheck %s
16 // CHECK: __tls_get_addr
17 // CHECK: __tls_get_addr
18 // CHECK: __tls_get_addr
19 // CHECK: __tls_get_addr
20 // CHECK: __tls_get_addr
24 $cc stress_dtls.c -lpthread -ldl
25 for((i=0;i<100;i++)); do
26 $cc -fPIC -shared -DSO_NAME=f$i -o a.out-f$i.so stress_dtls.c;
28 ./a.out 2 4 # <<<<<< 2 threads, 4 libs
29 ./a.out 3 50 # <<<<<< 3 threads, 50 libs
40 typedef void **(*f_t
)();
44 #define MAX_N_FUNCTIONS 1000
45 f_t Functions
[MAX_N_FUNCTIONS
];
47 void *PrintStuff(void *unused
) {
49 // fprintf(stderr, "STACK: %p TLS: %p SELF: %p\n", &stack, &my_tls,
50 // (void *)pthread_self());
52 for (i
= 0; i
< MAX_N_FUNCTIONS
; i
++) {
53 if (!Functions
[i
]) break;
54 uintptr_t dtls
= (uintptr_t)Functions
[i
]();
55 fprintf(stderr
, " dtls[%03d]: %lx\n", i
, dtls
);
56 *(long*)dtls
= 42; // check that this is writable.
61 int main(int argc
, char *argv
[]) {
65 num_threads
= atoi(argv
[1]);
67 num_libs
= atoi(argv
[2]);
68 assert(num_libs
<= MAX_N_FUNCTIONS
);
71 for (lib
= 0; lib
< num_libs
; lib
++) {
73 snprintf(buf
, sizeof(buf
), "%s-f%d.so", argv
[0], lib
);
74 void *handle
= dlopen(buf
, RTLD_LAZY
);
76 fprintf(stderr
, "%s\n", dlerror());
79 snprintf(buf
, sizeof(buf
), "f%d", lib
);
80 Functions
[lib
] = (f_t
)dlsym(handle
, buf
);
81 if (!Functions
[lib
]) {
82 fprintf(stderr
, "%s\n", dlerror());
85 fprintf(stderr
, "LIB[%03d] %s: %p\n", lib
, buf
, Functions
[lib
]);
89 for (i
= 0; i
< num_threads
; i
++) {
91 pthread_create(&t
, 0, PrintStuff
, 0);
99 # define DTLS_SIZE (1 << 17)
101 __thread
void *huge_thread_local_array
[DTLS_SIZE
];
103 return &huge_thread_local_array
[0];