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