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