3 #include "msan_thread.h"
4 #include "msan_interface_internal.h"
6 #include "sanitizer_common/sanitizer_tls_get_addr.h"
10 MsanThread
*MsanThread::Create(thread_callback_t start_routine
,
12 uptr PageSize
= GetPageSizeCached();
13 uptr size
= RoundUpTo(sizeof(MsanThread
), PageSize
);
14 MsanThread
*thread
= (MsanThread
*)MmapOrDie(size
, __func__
);
15 thread
->start_routine_
= start_routine
;
17 thread
->destructor_iterations_
= GetPthreadDestructorIterations();
22 void MsanThread::SetThreadStackAndTls() {
25 GetThreadStackAndTls(IsMainThread(), &stack_
.bottom
, &stack_size
, &tls_begin_
,
27 stack_
.top
= stack_
.bottom
+ stack_size
;
28 tls_end_
= tls_begin_
+ tls_size
;
31 CHECK(AddrIsInStack((uptr
)&local
));
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();
40 ForEachDVT(dtls
, [](const DTLS::DTV
&dtv
, int id
) {
41 __msan_unpoison((void *)(dtv
.beg
), dtv
.size
);
45 void MsanThread::Init() {
46 SetThreadStackAndTls();
47 CHECK(MEM_IS_APP(stack_
.bottom
));
48 CHECK(MEM_IS_APP(stack_
.top
- 1));
49 ClearShadowForThreadStackAndTLS();
50 malloc_storage().Init();
53 void MsanThread::TSDDtor(void *tsd
) {
54 MsanThread
*t
= (MsanThread
*)tsd
;
58 void MsanThread::Destroy() {
59 malloc_storage().CommitBack();
60 // We also clear the shadow on thread destruction because
61 // some code may still be executing in later TSD destructors
62 // and we don't want it to have any poisoned stack.
63 ClearShadowForThreadStackAndTLS();
64 uptr size
= RoundUpTo(sizeof(MsanThread
), GetPageSizeCached());
65 UnmapOrDie(this, size
);
69 thread_return_t
MsanThread::ThreadStart() {
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.
77 thread_return_t res
= start_routine_(arg_
);
82 MsanThread::StackBounds
MsanThread::GetStackBounds() const {
83 if (!stack_switching_
)
84 return {stack_
.bottom
, stack_
.top
};
85 const uptr cur_stack
= GET_CURRENT_FRAME();
86 // Note: need to check next stack first, because FinishSwitchFiber
87 // may be in process of overwriting stack_.top/bottom_. But in such case
88 // we are already on the next stack.
89 if (cur_stack
>= next_stack_
.bottom
&& cur_stack
< next_stack_
.top
)
90 return {next_stack_
.bottom
, next_stack_
.top
};
91 return {stack_
.bottom
, stack_
.top
};
94 uptr
MsanThread::stack_top() { return GetStackBounds().top
; }
96 uptr
MsanThread::stack_bottom() { return GetStackBounds().bottom
; }
98 bool MsanThread::AddrIsInStack(uptr addr
) {
99 const auto bounds
= GetStackBounds();
100 return addr
>= bounds
.bottom
&& addr
< bounds
.top
;
103 void MsanThread::StartSwitchFiber(uptr bottom
, uptr size
) {
104 CHECK(!stack_switching_
);
105 next_stack_
.bottom
= bottom
;
106 next_stack_
.top
= bottom
+ size
;
107 stack_switching_
= true;
110 void MsanThread::FinishSwitchFiber(uptr
*bottom_old
, uptr
*size_old
) {
111 CHECK(stack_switching_
);
113 *bottom_old
= stack_
.bottom
;
115 *size_old
= stack_
.top
- stack_
.bottom
;
116 stack_
.bottom
= next_stack_
.bottom
;
117 stack_
.top
= next_stack_
.top
;
118 stack_switching_
= false;
120 next_stack_
.bottom
= 0;
123 } // namespace __msan