1*7c3d14c8STreehugger Robot /* RUN: %clang_msan -g %s -o %t
2*7c3d14c8STreehugger Robot RUN: %clang_msan -g %s -DBUILD_SO -fPIC -o %t-so.so -shared
3*7c3d14c8STreehugger Robot RUN: %run %t 2>&1
4*7c3d14c8STreehugger Robot
5*7c3d14c8STreehugger Robot Regression test for a bug in msan/glibc integration,
6*7c3d14c8STreehugger Robot see https://sourceware.org/bugzilla/show_bug.cgi?id=16291
7*7c3d14c8STreehugger Robot and https://github.com/google/sanitizers/issues/547
8*7c3d14c8STreehugger Robot */
9*7c3d14c8STreehugger Robot
10*7c3d14c8STreehugger Robot #ifndef BUILD_SO
11*7c3d14c8STreehugger Robot #include <assert.h>
12*7c3d14c8STreehugger Robot #include <dlfcn.h>
13*7c3d14c8STreehugger Robot #include <stdio.h>
14*7c3d14c8STreehugger Robot #include <stdlib.h>
15*7c3d14c8STreehugger Robot #include <pthread.h>
16*7c3d14c8STreehugger Robot
17*7c3d14c8STreehugger Robot typedef long *(* get_t)();
18*7c3d14c8STreehugger Robot get_t GetTls;
Thread1(void * unused)19*7c3d14c8STreehugger Robot void *Thread1(void *unused) {
20*7c3d14c8STreehugger Robot long uninitialized;
21*7c3d14c8STreehugger Robot long *x = GetTls();
22*7c3d14c8STreehugger Robot if (*x)
23*7c3d14c8STreehugger Robot fprintf(stderr, "bar\n");
24*7c3d14c8STreehugger Robot *x = uninitialized;
25*7c3d14c8STreehugger Robot fprintf(stderr, "stack: %p dtls: %p\n", &x, x);
26*7c3d14c8STreehugger Robot return 0;
27*7c3d14c8STreehugger Robot }
28*7c3d14c8STreehugger Robot
Thread2(void * unused)29*7c3d14c8STreehugger Robot void *Thread2(void *unused) {
30*7c3d14c8STreehugger Robot long *x = GetTls();
31*7c3d14c8STreehugger Robot fprintf(stderr, "stack: %p dtls: %p\n", &x, x);
32*7c3d14c8STreehugger Robot if (*x)
33*7c3d14c8STreehugger Robot fprintf(stderr, "foo\n"); // False negative here.
34*7c3d14c8STreehugger Robot return 0;
35*7c3d14c8STreehugger Robot }
36*7c3d14c8STreehugger Robot
main(int argc,char * argv[])37*7c3d14c8STreehugger Robot int main(int argc, char *argv[]) {
38*7c3d14c8STreehugger Robot char path[4096];
39*7c3d14c8STreehugger Robot snprintf(path, sizeof(path), "%s-so.so", argv[0]);
40*7c3d14c8STreehugger Robot int i;
41*7c3d14c8STreehugger Robot
42*7c3d14c8STreehugger Robot void *handle = dlopen(path, RTLD_LAZY);
43*7c3d14c8STreehugger Robot if (!handle) fprintf(stderr, "%s\n", dlerror());
44*7c3d14c8STreehugger Robot assert(handle != 0);
45*7c3d14c8STreehugger Robot GetTls = (get_t)dlsym(handle, "GetTls");
46*7c3d14c8STreehugger Robot assert(dlerror() == 0);
47*7c3d14c8STreehugger Robot
48*7c3d14c8STreehugger Robot pthread_t t;
49*7c3d14c8STreehugger Robot pthread_create(&t, 0, Thread1, 0);
50*7c3d14c8STreehugger Robot pthread_join(t, 0);
51*7c3d14c8STreehugger Robot pthread_create(&t, 0, Thread2, 0);
52*7c3d14c8STreehugger Robot pthread_join(t, 0);
53*7c3d14c8STreehugger Robot return 0;
54*7c3d14c8STreehugger Robot }
55*7c3d14c8STreehugger Robot #else // BUILD_SO
56*7c3d14c8STreehugger Robot __thread long huge_thread_local_array[1 << 17];
GetTls()57*7c3d14c8STreehugger Robot long *GetTls() {
58*7c3d14c8STreehugger Robot return &huge_thread_local_array[0];
59*7c3d14c8STreehugger Robot }
60*7c3d14c8STreehugger Robot #endif
61