asan_thread.cc revision 7e8434940a1fe7dce531d4c458ccd714da48f609
1bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant//===-- asan_thread.cc ----------------------------------------------------===// 2bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant// 3f5256e16dfc425c1d466f6308d4026d529ce9e0bHoward Hinnant// The LLVM Compiler Infrastructure 4bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant// 5b64f8b07c104c6cc986570ac8ee0ed16a9f23976Howard Hinnant// This file is distributed under the University of Illinois Open Source 6b64f8b07c104c6cc986570ac8ee0ed16a9f23976Howard Hinnant// License. See LICENSE.TXT for details. 7bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant// 8bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant//===----------------------------------------------------------------------===// 9bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant// 10bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant// This file is a part of AddressSanitizer, an address sanity checker. 11bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant// 12bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant// Thread-related code. 13bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant//===----------------------------------------------------------------------===// 14bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "asan_allocator.h" 15bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "asan_interceptors.h" 16bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "asan_poisoning.h" 17bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "asan_stack.h" 18bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "asan_thread.h" 19bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "asan_mapping.h" 20bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "sanitizer_common/sanitizer_common.h" 21bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant#include "sanitizer_common/sanitizer_placement_new.h" 22bc8d3f97eb5c958007f2713238472e0c1c8fe02Howard Hinnant 23namespace __asan { 24 25// AsanThreadContext implementation. 26 27void AsanThreadContext::OnCreated(void *arg) { 28 CreateThreadContextArgs *args = static_cast<CreateThreadContextArgs*>(arg); 29 if (args->stack) { 30 internal_memcpy(&stack, args->stack, sizeof(stack)); 31 } 32 thread = args->thread; 33 thread->set_context(this); 34} 35 36void AsanThreadContext::OnFinished() { 37 // Drop the link to the AsanThread object. 38 thread = 0; 39} 40 41static char thread_registry_placeholder[sizeof(ThreadRegistry)]; 42static ThreadRegistry *asan_thread_registry; 43 44static ThreadContextBase *GetAsanThreadContext(u32 tid) { 45 void *mem = MmapOrDie(sizeof(AsanThreadContext), "AsanThreadContext"); 46 return new(mem) AsanThreadContext(tid); 47} 48 49ThreadRegistry &asanThreadRegistry() { 50 static bool initialized; 51 // Don't worry about thread_safety - this should be called when there is 52 // a single thread. 53 if (!initialized) { 54 // Never reuse ASan threads: we store pointer to AsanThreadContext 55 // in TSD and can't reliably tell when no more TSD destructors will 56 // be called. It would be wrong to reuse AsanThreadContext for another 57 // thread before all TSD destructors will be called for it. 58 asan_thread_registry = new(thread_registry_placeholder) ThreadRegistry( 59 GetAsanThreadContext, kMaxNumberOfThreads, kMaxNumberOfThreads); 60 initialized = true; 61 } 62 return *asan_thread_registry; 63} 64 65AsanThreadContext *GetThreadContextByTidLocked(u32 tid) { 66 return static_cast<AsanThreadContext *>( 67 asanThreadRegistry().GetThreadLocked(tid)); 68} 69 70// AsanThread implementation. 71 72AsanThread *AsanThread::Create(thread_callback_t start_routine, 73 void *arg) { 74 uptr PageSize = GetPageSizeCached(); 75 uptr size = RoundUpTo(sizeof(AsanThread), PageSize); 76 AsanThread *thread = (AsanThread*)MmapOrDie(size, __FUNCTION__); 77 thread->start_routine_ = start_routine; 78 thread->arg_ = arg; 79 thread->context_ = 0; 80 81 return thread; 82} 83 84void AsanThread::TSDDtor(void *tsd) { 85 AsanThreadContext *context = (AsanThreadContext*)tsd; 86 if (flags()->verbosity >= 1) 87 Report("T%d TSDDtor\n", context->tid); 88 if (context->thread) 89 context->thread->Destroy(); 90} 91 92void AsanThread::Destroy() { 93 if (flags()->verbosity >= 1) { 94 Report("T%d exited\n", tid()); 95 } 96 97 asanThreadRegistry().FinishThread(tid()); 98 FlushToAccumulatedStats(&stats_); 99 // We also clear the shadow on thread destruction because 100 // some code may still be executing in later TSD destructors 101 // and we don't want it to have any poisoned stack. 102 ClearShadowForThreadStack(); 103 fake_stack().Cleanup(); 104 uptr size = RoundUpTo(sizeof(AsanThread), GetPageSizeCached()); 105 UnmapOrDie(this, size); 106} 107 108void AsanThread::Init() { 109 SetThreadStackTopAndBottom(); 110 CHECK(AddrIsInMem(stack_bottom_)); 111 CHECK(AddrIsInMem(stack_top_ - 1)); 112 ClearShadowForThreadStack(); 113 if (flags()->verbosity >= 1) { 114 int local = 0; 115 Report("T%d: stack [%p,%p) size 0x%zx; local=%p\n", 116 tid(), (void*)stack_bottom_, (void*)stack_top_, 117 stack_top_ - stack_bottom_, &local); 118 } 119 fake_stack_.Init(stack_size()); 120 AsanPlatformThreadInit(); 121} 122 123thread_return_t AsanThread::ThreadStart(uptr os_id) { 124 Init(); 125 asanThreadRegistry().StartThread(tid(), os_id, 0); 126 if (flags()->use_sigaltstack) SetAlternateSignalStack(); 127 128 if (!start_routine_) { 129 // start_routine_ == 0 if we're on the main thread or on one of the 130 // OS X libdispatch worker threads. But nobody is supposed to call 131 // ThreadStart() for the worker threads. 132 CHECK(tid() == 0); 133 return 0; 134 } 135 136 thread_return_t res = start_routine_(arg_); 137 malloc_storage().CommitBack(); 138 if (flags()->use_sigaltstack) UnsetAlternateSignalStack(); 139 140 this->Destroy(); 141 142 return res; 143} 144 145void AsanThread::SetThreadStackTopAndBottom() { 146 GetThreadStackTopAndBottom(tid() == 0, &stack_top_, &stack_bottom_); 147 int local; 148 CHECK(AddrIsInStack((uptr)&local)); 149} 150 151void AsanThread::ClearShadowForThreadStack() { 152 PoisonShadow(stack_bottom_, stack_top_ - stack_bottom_, 0); 153} 154 155const char *AsanThread::GetFrameNameByAddr(uptr addr, uptr *offset, 156 uptr *frame_pc) { 157 uptr bottom = 0; 158 if (AddrIsInStack(addr)) { 159 bottom = stack_bottom(); 160 } else { 161 bottom = fake_stack().AddrIsInFakeStack(addr); 162 CHECK(bottom); 163 *offset = addr - bottom; 164 *frame_pc = ((uptr*)bottom)[2]; 165 return (const char *)((uptr*)bottom)[1]; 166 } 167 uptr aligned_addr = addr & ~(SANITIZER_WORDSIZE/8 - 1); // align addr. 168 u8 *shadow_ptr = (u8*)MemToShadow(aligned_addr); 169 u8 *shadow_bottom = (u8*)MemToShadow(bottom); 170 171 while (shadow_ptr >= shadow_bottom && 172 *shadow_ptr != kAsanStackLeftRedzoneMagic) { 173 shadow_ptr--; 174 } 175 176 while (shadow_ptr >= shadow_bottom && 177 *shadow_ptr == kAsanStackLeftRedzoneMagic) { 178 shadow_ptr--; 179 } 180 181 if (shadow_ptr < shadow_bottom) { 182 *offset = 0; 183 return "UNKNOWN"; 184 } 185 186 uptr* ptr = (uptr*)SHADOW_TO_MEM((uptr)(shadow_ptr + 1)); 187 CHECK(ptr[0] == kCurrentStackFrameMagic); 188 *offset = addr - (uptr)ptr; 189 *frame_pc = ptr[2]; 190 return (const char*)ptr[1]; 191} 192 193static bool ThreadStackContainsAddress(ThreadContextBase *tctx_base, 194 void *addr) { 195 AsanThreadContext *tctx = static_cast<AsanThreadContext*>(tctx_base); 196 AsanThread *t = tctx->thread; 197 return (t && t->fake_stack().StackSize() && 198 (t->fake_stack().AddrIsInFakeStack((uptr)addr) || 199 t->AddrIsInStack((uptr)addr))); 200} 201 202AsanThread *GetCurrentThread() { 203 AsanThreadContext *context = (AsanThreadContext*)AsanTSDGet(); 204 if (!context) { 205 if (SANITIZER_ANDROID) { 206 // On Android, libc constructor is called _after_ asan_init, and cleans up 207 // TSD. Try to figure out if this is still the main thread by the stack 208 // address. We are not entirely sure that we have correct main thread 209 // limits, so only do this magic on Android, and only if the found thread 210 // is the main thread. 211 AsanThreadContext *tctx = GetThreadContextByTidLocked(0); 212 if (ThreadStackContainsAddress(tctx, &context)) { 213 SetCurrentThread(tctx->thread); 214 return tctx->thread; 215 } 216 } 217 return 0; 218 } 219 return context->thread; 220} 221 222void SetCurrentThread(AsanThread *t) { 223 CHECK(t->context()); 224 if (flags()->verbosity >= 2) { 225 Report("SetCurrentThread: %p for thread %p\n", 226 t->context(), (void*)GetThreadSelf()); 227 } 228 // Make sure we do not reset the current AsanThread. 229 CHECK_EQ(0, AsanTSDGet()); 230 AsanTSDSet(t->context()); 231 CHECK_EQ(t->context(), AsanTSDGet()); 232} 233 234u32 GetCurrentTidOrInvalid() { 235 AsanThread *t = GetCurrentThread(); 236 return t ? t->tid() : kInvalidTid; 237} 238 239AsanThread *FindThreadByStackAddress(uptr addr) { 240 asanThreadRegistry().CheckLocked(); 241 AsanThreadContext *tctx = static_cast<AsanThreadContext *>( 242 asanThreadRegistry().FindThreadContextLocked(ThreadStackContainsAddress, 243 (void *)addr)); 244 return tctx ? tctx->thread : 0; 245} 246 247} // namespace __asan 248