2 #include "msan_thread.h"
5 #include "msan_interface_internal.h"
6 #include "sanitizer_common/sanitizer_tls_get_addr.h"
8 using namespace __msan
;
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() {
23 GetThreadStackAndTls(IsMainThread(), &stack_
.bottom
, &stack_
.top
, &tls_begin_
,
26 CHECK(AddrIsInStack((uptr
)&local
));
29 void MsanThread::ClearShadowForThreadStackAndTLS() {
30 __msan_unpoison((void *)stack_
.bottom
, stack_
.top
- stack_
.bottom
);
31 if (tls_begin_
!= tls_end_
)
32 __msan_unpoison((void *)tls_begin_
, tls_end_
- tls_begin_
);
33 DTLS
*dtls
= DTLS_Get();
35 ForEachDVT(dtls
, [](const DTLS::DTV
&dtv
, int id
) {
36 __msan_unpoison((void *)(dtv
.beg
), dtv
.size
);
40 void MsanThread::Init() {
41 SetThreadStackAndTls();
42 CHECK(MEM_IS_APP(stack_
.bottom
));
43 CHECK(MEM_IS_APP(stack_
.top
- 1));
44 ClearShadowForThreadStackAndTLS();
45 malloc_storage().Init();
48 void MsanThread::TSDDtor(void *tsd
) {
49 MsanThread
*t
= (MsanThread
*)tsd
;
53 void MsanThread::Destroy() {
54 malloc_storage().CommitBack();
55 // We also clear the shadow on thread destruction because
56 // some code may still be executing in later TSD destructors
57 // and we don't want it to have any poisoned stack.
58 ClearShadowForThreadStackAndTLS();
59 uptr size
= RoundUpTo(sizeof(MsanThread
), GetPageSizeCached());
60 UnmapOrDie(this, size
);
64 thread_return_t
MsanThread::ThreadStart() {
65 if (!start_routine_
) {
66 // start_routine_ == 0 if we're on the main thread or on one of the
67 // OS X libdispatch worker threads. But nobody is supposed to call
68 // ThreadStart() for the worker threads.
72 return start_routine_(arg_
);
75 MsanThread::StackBounds
MsanThread::GetStackBounds() const {
76 if (!stack_switching_
)
77 return {stack_
.bottom
, stack_
.top
};
78 const uptr cur_stack
= GET_CURRENT_FRAME();
79 // Note: need to check next stack first, because FinishSwitchFiber
80 // may be in process of overwriting stack_.top/bottom_. But in such case
81 // we are already on the next stack.
82 if (cur_stack
>= next_stack_
.bottom
&& cur_stack
< next_stack_
.top
)
83 return {next_stack_
.bottom
, next_stack_
.top
};
84 return {stack_
.bottom
, stack_
.top
};
87 uptr
MsanThread::stack_top() { return GetStackBounds().top
; }
89 uptr
MsanThread::stack_bottom() { return GetStackBounds().bottom
; }
91 bool MsanThread::AddrIsInStack(uptr addr
) {
92 const auto bounds
= GetStackBounds();
93 return addr
>= bounds
.bottom
&& addr
< bounds
.top
;
96 void MsanThread::StartSwitchFiber(uptr bottom
, uptr size
) {
97 CHECK(!stack_switching_
);
98 next_stack_
.bottom
= bottom
;
99 next_stack_
.top
= bottom
+ size
;
100 stack_switching_
= true;
103 void MsanThread::FinishSwitchFiber(uptr
*bottom_old
, uptr
*size_old
) {
104 CHECK(stack_switching_
);
106 *bottom_old
= stack_
.bottom
;
108 *size_old
= stack_
.top
- stack_
.bottom
;
109 stack_
.bottom
= next_stack_
.bottom
;
110 stack_
.top
= next_stack_
.top
;
111 stack_switching_
= false;
113 next_stack_
.bottom
= 0;