xref: /freebsd-src/contrib/llvm-project/compiler-rt/lib/msan/msan_thread.cpp (revision 68d75eff68281c1b445e3010bb975eae07aac225)
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