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 PageSize
= GetPageSizeCached();
30 uptr size
= RoundUpTo(sizeof(AsanThread
), PageSize
);
31 AsanThread
*thread
= (AsanThread
*)MmapOrDie(size
, __FUNCTION__
);
32 thread
->start_routine_
= start_routine
;
35 const uptr kSummaryAllocSize
= PageSize
;
36 CHECK_LE(sizeof(AsanThreadSummary
), kSummaryAllocSize
);
37 AsanThreadSummary
*summary
=
38 (AsanThreadSummary
*)MmapOrDie(PageSize
, "AsanThreadSummary");
39 summary
->Init(parent_tid
, stack
);
40 summary
->set_thread(thread
);
41 thread
->set_summary(summary
);
46 void AsanThreadSummary::TSDDtor(void *tsd
) {
47 AsanThreadSummary
*summary
= (AsanThreadSummary
*)tsd
;
48 if (flags()->verbosity
>= 1) {
49 Report("T%d TSDDtor\n", summary
->tid());
51 if (summary
->thread()) {
52 summary
->thread()->Destroy();
56 void AsanThread::Destroy() {
57 if (flags()->verbosity
>= 1) {
58 Report("T%d exited\n", tid());
61 asanThreadRegistry().UnregisterThread(this);
62 CHECK(summary()->thread() == 0);
63 // We also clear the shadow on thread destruction because
64 // some code may still be executing in later TSD destructors
65 // and we don't want it to have any poisoned stack.
66 ClearShadowForThreadStack();
67 fake_stack().Cleanup();
68 uptr size
= RoundUpTo(sizeof(AsanThread
), GetPageSizeCached());
69 UnmapOrDie(this, size
);
72 void AsanThread::Init() {
73 SetThreadStackTopAndBottom();
74 CHECK(AddrIsInMem(stack_bottom_
));
75 CHECK(AddrIsInMem(stack_top_
- 1));
76 ClearShadowForThreadStack();
77 if (flags()->verbosity
>= 1) {
79 Report("T%d: stack [%p,%p) size 0x%zx; local=%p\n",
80 tid(), (void*)stack_bottom_
, (void*)stack_top_
,
81 stack_top_
- stack_bottom_
, &local
);
83 fake_stack_
.Init(stack_size());
84 AsanPlatformThreadInit();
87 thread_return_t
AsanThread::ThreadStart() {
89 if (flags()->use_sigaltstack
) SetAlternateSignalStack();
91 if (!start_routine_
) {
92 // start_routine_ == 0 if we're on the main thread or on one of the
93 // OS X libdispatch worker threads. But nobody is supposed to call
94 // ThreadStart() for the worker threads.
99 thread_return_t res
= start_routine_(arg_
);
100 malloc_storage().CommitBack();
101 if (flags()->use_sigaltstack
) UnsetAlternateSignalStack();
108 void AsanThread::SetThreadStackTopAndBottom() {
109 GetThreadStackTopAndBottom(tid() == 0, &stack_top_
, &stack_bottom_
);
111 CHECK(AddrIsInStack((uptr
)&local
));
114 void AsanThread::ClearShadowForThreadStack() {
115 PoisonShadow(stack_bottom_
, stack_top_
- stack_bottom_
, 0);
118 const char *AsanThread::GetFrameNameByAddr(uptr addr
, uptr
*offset
) {
120 if (AddrIsInStack(addr
)) {
121 bottom
= stack_bottom();
123 bottom
= fake_stack().AddrIsInFakeStack(addr
);
125 *offset
= addr
- bottom
;
126 return (const char *)((uptr
*)bottom
)[1];
128 uptr aligned_addr
= addr
& ~(SANITIZER_WORDSIZE
/8 - 1); // align addr.
129 u8
*shadow_ptr
= (u8
*)MemToShadow(aligned_addr
);
130 u8
*shadow_bottom
= (u8
*)MemToShadow(bottom
);
132 while (shadow_ptr
>= shadow_bottom
&&
133 *shadow_ptr
!= kAsanStackLeftRedzoneMagic
) {
137 while (shadow_ptr
>= shadow_bottom
&&
138 *shadow_ptr
== kAsanStackLeftRedzoneMagic
) {
142 if (shadow_ptr
< shadow_bottom
) {
147 uptr
* ptr
= (uptr
*)SHADOW_TO_MEM((uptr
)(shadow_ptr
+ 1));
148 CHECK(ptr
[0] == kCurrentStackFrameMagic
);
149 *offset
= addr
- (uptr
)ptr
;
150 return (const char*)ptr
[1];
153 } // namespace __asan