msan_thread.cc revision 5d71de26cedae3dafc17449fe0182045c0bd20e8
1
2#include "msan.h"
3#include "msan_thread.h"
4#include "msan_interface_internal.h"
5
6#include "sanitizer_common/sanitizer_tls_get_addr.h"
7
8namespace __msan {
9
10MsanThread *MsanThread::Create(thread_callback_t start_routine,
11                               void *arg) {
12  uptr PageSize = GetPageSizeCached();
13  uptr size = RoundUpTo(sizeof(MsanThread), PageSize);
14  MsanThread *thread = (MsanThread*)MmapOrDie(size, __func__);
15  thread->start_routine_ = start_routine;
16  thread->arg_ = arg;
17  thread->destructor_iterations_ = kPthreadDestructorIterations;
18
19  return thread;
20}
21
22void MsanThread::SetThreadStackAndTls() {
23  uptr tls_size = 0;
24  uptr stack_size = 0;
25  GetThreadStackAndTls(IsMainThread(), &stack_bottom_, &stack_size,
26                       &tls_begin_, &tls_size);
27  stack_top_ = stack_bottom_ + stack_size;
28  tls_end_ = tls_begin_ + tls_size;
29
30  int local;
31  CHECK(AddrIsInStack((uptr)&local));
32}
33
34void MsanThread::ClearShadowForThreadStackAndTLS() {
35  __msan_unpoison((void *)stack_bottom_, stack_top_ - stack_bottom_);
36  if (tls_begin_ != tls_end_)
37    __msan_unpoison((void *)tls_begin_, tls_end_ - tls_begin_);
38  DTLS *dtls = DTLS_Get();
39  for (uptr i = 0; i < dtls->dtv_size; ++i)
40    __msan_unpoison((void *)(dtls->dtv[i].beg), dtls->dtv[i].size);
41}
42
43void MsanThread::Init() {
44  SetThreadStackAndTls();
45  CHECK(MEM_IS_APP(stack_bottom_));
46  CHECK(MEM_IS_APP(stack_top_ - 1));
47  ClearShadowForThreadStackAndTLS();
48}
49
50void MsanThread::TSDDtor(void *tsd) {
51  MsanThread *t = (MsanThread*)tsd;
52  t->Destroy();
53}
54
55void MsanThread::Destroy() {
56  malloc_storage().CommitBack();
57  // We also clear the shadow on thread destruction because
58  // some code may still be executing in later TSD destructors
59  // and we don't want it to have any poisoned stack.
60  ClearShadowForThreadStackAndTLS();
61  uptr size = RoundUpTo(sizeof(MsanThread), GetPageSizeCached());
62  UnmapOrDie(this, size);
63  DTLS_Destroy();
64}
65
66thread_return_t MsanThread::ThreadStart() {
67  Init();
68
69  if (!start_routine_) {
70    // start_routine_ == 0 if we're on the main thread or on one of the
71    // OS X libdispatch worker threads. But nobody is supposed to call
72    // ThreadStart() for the worker threads.
73    return 0;
74  }
75
76  thread_return_t res = IndirectExternCall(start_routine_)(arg_);
77
78  return res;
79}
80
81MsanThread *GetCurrentThread() {
82  return reinterpret_cast<MsanThread *>(MsanTSDGet());
83}
84
85void SetCurrentThread(MsanThread *t) {
86  // Make sure we do not reset the current MsanThread.
87  CHECK_EQ(0, MsanTSDGet());
88  MsanTSDSet(t);
89  CHECK_EQ(t, MsanTSDGet());
90}
91
92} // namespace __msan
93