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