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