Home | History | Annotate | Download | only in msan
      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 
      8 namespace __msan {
      9 
     10 MsanThread *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_ = GetPthreadDestructorIterations();
     18 
     19   return thread;
     20 }
     21 
     22 void 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 
     34 void 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   CHECK_NE(dtls, 0);
     40   for (uptr i = 0; i < dtls->dtv_size; ++i)
     41     __msan_unpoison((void *)(dtls->dtv[i].beg), dtls->dtv[i].size);
     42 }
     43 
     44 void MsanThread::Init() {
     45   SetThreadStackAndTls();
     46   CHECK(MEM_IS_APP(stack_bottom_));
     47   CHECK(MEM_IS_APP(stack_top_ - 1));
     48   ClearShadowForThreadStackAndTLS();
     49 }
     50 
     51 void MsanThread::TSDDtor(void *tsd) {
     52   MsanThread *t = (MsanThread*)tsd;
     53   t->Destroy();
     54 }
     55 
     56 void MsanThread::Destroy() {
     57   malloc_storage().CommitBack();
     58   // We also clear the shadow on thread destruction because
     59   // some code may still be executing in later TSD destructors
     60   // and we don't want it to have any poisoned stack.
     61   ClearShadowForThreadStackAndTLS();
     62   uptr size = RoundUpTo(sizeof(MsanThread), GetPageSizeCached());
     63   UnmapOrDie(this, size);
     64   DTLS_Destroy();
     65 }
     66 
     67 thread_return_t MsanThread::ThreadStart() {
     68   Init();
     69 
     70   if (!start_routine_) {
     71     // start_routine_ == 0 if we're on the main thread or on one of the
     72     // OS X libdispatch worker threads. But nobody is supposed to call
     73     // ThreadStart() for the worker threads.
     74     return 0;
     75   }
     76 
     77   thread_return_t res = start_routine_(arg_);
     78 
     79   return res;
     80 }
     81 
     82 } // namespace __msan
     83