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