1 //===-- asan_thread.cc ----------------------------------------------------===//
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
6 //===----------------------------------------------------------------------===//
8 // This file is a part of AddressSanitizer, an address sanity checker.
10 // Thread-related code.
11 //===----------------------------------------------------------------------===//
12 #include "asan_allocator.h"
13 #include "asan_interceptors.h"
14 #include "asan_stack.h"
15 #include "asan_thread.h"
16 #include "asan_thread_registry.h"
17 #include "asan_mapping.h"
18 #include "sanitizer_common/sanitizer_common.h"
22 AsanThread::AsanThread(LinkerInitialized x
)
27 AsanThread
*AsanThread::Create(u32 parent_tid
, thread_callback_t start_routine
,
28 void *arg
, StackTrace
*stack
) {
29 uptr size
= RoundUpTo(sizeof(AsanThread
), kPageSize
);
30 AsanThread
*thread
= (AsanThread
*)MmapOrDie(size
, __FUNCTION__
);
31 thread
->start_routine_
= start_routine
;
34 const uptr kSummaryAllocSize
= kPageSize
;
35 CHECK_LE(sizeof(AsanThreadSummary
), kSummaryAllocSize
);
36 AsanThreadSummary
*summary
=
37 (AsanThreadSummary
*)MmapOrDie(kPageSize
, "AsanThreadSummary");
38 summary
->Init(parent_tid
, stack
);
39 summary
->set_thread(thread
);
40 thread
->set_summary(summary
);
45 void AsanThreadSummary::TSDDtor(void *tsd
) {
46 AsanThreadSummary
*summary
= (AsanThreadSummary
*)tsd
;
47 if (flags()->verbosity
>= 1) {
48 Report("T%d TSDDtor\n", summary
->tid());
50 if (summary
->thread()) {
51 summary
->thread()->Destroy();
55 void AsanThread::Destroy() {
56 if (flags()->verbosity
>= 1) {
57 Report("T%d exited\n", tid());
60 asanThreadRegistry().UnregisterThread(this);
61 CHECK(summary()->thread() == 0);
62 // We also clear the shadow on thread destruction because
63 // some code may still be executing in later TSD destructors
64 // and we don't want it to have any poisoned stack.
65 ClearShadowForThreadStack();
66 fake_stack().Cleanup();
67 uptr size
= RoundUpTo(sizeof(AsanThread
), kPageSize
);
68 UnmapOrDie(this, size
);
71 void AsanThread::Init() {
72 SetThreadStackTopAndBottom();
73 CHECK(AddrIsInMem(stack_bottom_
));
74 CHECK(AddrIsInMem(stack_top_
));
75 ClearShadowForThreadStack();
76 if (flags()->verbosity
>= 1) {
78 Report("T%d: stack [%p,%p) size 0x%zx; local=%p\n",
79 tid(), (void*)stack_bottom_
, (void*)stack_top_
,
80 stack_top_
- stack_bottom_
, &local
);
82 fake_stack_
.Init(stack_size());
83 AsanPlatformThreadInit();
86 thread_return_t
AsanThread::ThreadStart() {
88 if (flags()->use_sigaltstack
) SetAlternateSignalStack();
90 if (!start_routine_
) {
91 // start_routine_ == 0 if we're on the main thread or on one of the
92 // OS X libdispatch worker threads. But nobody is supposed to call
93 // ThreadStart() for the worker threads.
98 thread_return_t res
= start_routine_(arg_
);
99 malloc_storage().CommitBack();
100 if (flags()->use_sigaltstack
) UnsetAlternateSignalStack();
107 void AsanThread::SetThreadStackTopAndBottom() {
108 GetThreadStackTopAndBottom(tid() == 0, &stack_top_
, &stack_bottom_
);
110 CHECK(AddrIsInStack((uptr
)&local
));
113 void AsanThread::ClearShadowForThreadStack() {
114 PoisonShadow(stack_bottom_
, stack_top_
- stack_bottom_
, 0);
117 const char *AsanThread::GetFrameNameByAddr(uptr addr
, uptr
*offset
) {
119 bool is_fake_stack
= false;
120 if (AddrIsInStack(addr
)) {
121 bottom
= stack_bottom();
123 bottom
= fake_stack().AddrIsInFakeStack(addr
);
125 is_fake_stack
= true;
127 uptr aligned_addr
= addr
& ~(__WORDSIZE
/8 - 1); // align addr.
128 u8
*shadow_ptr
= (u8
*)MemToShadow(aligned_addr
);
129 u8
*shadow_bottom
= (u8
*)MemToShadow(bottom
);
131 while (shadow_ptr
>= shadow_bottom
&&
132 *shadow_ptr
!= kAsanStackLeftRedzoneMagic
) {
136 while (shadow_ptr
>= shadow_bottom
&&
137 *shadow_ptr
== kAsanStackLeftRedzoneMagic
) {
141 if (shadow_ptr
< shadow_bottom
) {
146 uptr
* ptr
= (uptr
*)SHADOW_TO_MEM((uptr
)(shadow_ptr
+ 1));
147 CHECK((ptr
[0] == kCurrentStackFrameMagic
) ||
148 (is_fake_stack
&& ptr
[0] == kRetiredStackFrameMagic
));
149 *offset
= addr
- (uptr
)ptr
;
150 return (const char*)ptr
[1];
153 } // namespace __asan