15d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines/* RUN: %clang_msan -g -m64 %s -o %t
25d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines   RUN: %clang_msan -g -m64 %s -DBUILD_SO -fPIC -o %t-so.so -shared
35d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines   RUN: %run %t 2>&1
42d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
55d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines   Regression test for a bug in msan/glibc integration,
62d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines   see https://sourceware.org/bugzilla/show_bug.cgi?id=16291
75d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines   and https://code.google.com/p/memory-sanitizer/issues/detail?id=44
82d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines*/
92d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#ifndef BUILD_SO
112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <assert.h>
122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <dlfcn.h>
132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <stdio.h>
142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <stdlib.h>
152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <pthread.h>
162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinestypedef long *(* get_t)();
182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesget_t GetTls;
192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid *Thread1(void *unused) {
202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  long uninitialized;
212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  long *x = GetTls();
222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (*x)
232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    fprintf(stderr, "bar\n");
242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  *x = uninitialized;
252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  fprintf(stderr, "stack: %p dtls: %p\n", &x, x);
262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return 0;
272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid *Thread2(void *unused) {
302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  long *x = GetTls();
312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  fprintf(stderr, "stack: %p dtls: %p\n", &x, x);
322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (*x)
332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    fprintf(stderr, "foo\n");   // False negative here.
342d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return 0;
352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
362d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
372d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesint main(int argc, char *argv[]) {
382d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  char path[4096];
392d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  snprintf(path, sizeof(path), "%s-so.so", argv[0]);
402d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  int i;
412d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  void *handle = dlopen(path, RTLD_LAZY);
432d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (!handle) fprintf(stderr, "%s\n", dlerror());
442d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  assert(handle != 0);
452d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  GetTls = (get_t)dlsym(handle, "GetTls");
462d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  assert(dlerror() == 0);
472d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines
482d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  pthread_t t;
492d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  pthread_create(&t, 0, Thread1, 0);
502d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  pthread_join(t, 0);
512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  pthread_create(&t, 0, Thread2, 0);
522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  pthread_join(t, 0);
532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return 0;
542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
552d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#else  // BUILD_SO
562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines__thread long huge_thread_local_array[1 << 17];
572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hineslong *GetTls() {
582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  return &huge_thread_local_array[0];
592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines}
602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#endif
61