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