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