asan_thread.cc revision 238901
1238901Sandrew//===-- asan_thread.cc ----------------------------------------------------===// 2229109Sed// 3229109Sed// The LLVM Compiler Infrastructure 4229109Sed// 5229109Sed// This file is distributed under the University of Illinois Open Source 6229109Sed// License. See LICENSE.TXT for details. 7229109Sed// 8229109Sed//===----------------------------------------------------------------------===// 9229109Sed// 10229109Sed// This file is a part of AddressSanitizer, an address sanity checker. 11229109Sed// 12229109Sed// Thread-related code. 13229109Sed//===----------------------------------------------------------------------===// 14229109Sed#include "asan_allocator.h" 15229109Sed#include "asan_interceptors.h" 16238901Sandrew#include "asan_stack.h" 17229109Sed#include "asan_thread.h" 18229109Sed#include "asan_thread_registry.h" 19229109Sed#include "asan_mapping.h" 20238901Sandrew#include "sanitizer_common/sanitizer_common.h" 21229109Sed 22229109Sednamespace __asan { 23229109Sed 24229109SedAsanThread::AsanThread(LinkerInitialized x) 25229109Sed : fake_stack_(x), 26229109Sed malloc_storage_(x), 27229109Sed stats_(x) { } 28229109Sed 29238901Sandrewstatic AsanLock mu_for_thread_summary(LINKER_INITIALIZED); 30238901Sandrewstatic LowLevelAllocator allocator_for_thread_summary(LINKER_INITIALIZED); 31238901Sandrew 32238901SandrewAsanThread *AsanThread::Create(u32 parent_tid, thread_callback_t start_routine, 33238901Sandrew void *arg, AsanStackTrace *stack) { 34238901Sandrew uptr size = RoundUpTo(sizeof(AsanThread), kPageSize); 35238901Sandrew AsanThread *thread = (AsanThread*)MmapOrDie(size, __FUNCTION__); 36238901Sandrew thread->start_routine_ = start_routine; 37238901Sandrew thread->arg_ = arg; 38238901Sandrew 39238901Sandrew const uptr kSummaryAllocSize = 1024; 40238901Sandrew CHECK_LE(sizeof(AsanThreadSummary), kSummaryAllocSize); 41238901Sandrew AsanThreadSummary *summary; 42238901Sandrew { 43238901Sandrew ScopedLock lock(&mu_for_thread_summary); 44238901Sandrew summary = (AsanThreadSummary*) 45238901Sandrew allocator_for_thread_summary.Allocate(kSummaryAllocSize); 46238901Sandrew } 47238901Sandrew summary->Init(parent_tid, stack); 48238901Sandrew summary->set_thread(thread); 49238901Sandrew thread->set_summary(summary); 50238901Sandrew 51238901Sandrew return thread; 52229109Sed} 53229109Sed 54238901Sandrewvoid AsanThreadSummary::TSDDtor(void *tsd) { 55238901Sandrew AsanThreadSummary *summary = (AsanThreadSummary*)tsd; 56238901Sandrew if (flags()->verbosity >= 1) { 57238901Sandrew Report("T%d TSDDtor\n", summary->tid()); 58238901Sandrew } 59238901Sandrew if (summary->thread()) { 60238901Sandrew summary->thread()->Destroy(); 61238901Sandrew } 62238901Sandrew} 63238901Sandrew 64238901Sandrewvoid AsanThread::Destroy() { 65238901Sandrew if (flags()->verbosity >= 1) { 66238901Sandrew Report("T%d exited\n", tid()); 67238901Sandrew } 68238901Sandrew 69229109Sed asanThreadRegistry().UnregisterThread(this); 70238901Sandrew CHECK(summary()->thread() == 0); 71229109Sed // We also clear the shadow on thread destruction because 72229109Sed // some code may still be executing in later TSD destructors 73229109Sed // and we don't want it to have any poisoned stack. 74229109Sed ClearShadowForThreadStack(); 75238901Sandrew fake_stack().Cleanup(); 76238901Sandrew uptr size = RoundUpTo(sizeof(AsanThread), kPageSize); 77238901Sandrew UnmapOrDie(this, size); 78229109Sed} 79229109Sed 80229109Sedvoid AsanThread::Init() { 81229109Sed SetThreadStackTopAndBottom(); 82229109Sed CHECK(AddrIsInMem(stack_bottom_)); 83229109Sed CHECK(AddrIsInMem(stack_top_)); 84229109Sed ClearShadowForThreadStack(); 85238901Sandrew if (flags()->verbosity >= 1) { 86238901Sandrew int local = 0; 87238901Sandrew Report("T%d: stack [%p,%p) size 0x%zx; local=%p\n", 88238901Sandrew tid(), (void*)stack_bottom_, (void*)stack_top_, 89238901Sandrew stack_top_ - stack_bottom_, &local); 90238901Sandrew } 91238901Sandrew fake_stack_.Init(stack_size()); 92238901Sandrew AsanPlatformThreadInit(); 93229109Sed} 94229109Sed 95238901Sandrewthread_return_t AsanThread::ThreadStart() { 96229109Sed Init(); 97238901Sandrew if (flags()->use_sigaltstack) SetAlternateSignalStack(); 98229109Sed 99229109Sed if (!start_routine_) { 100238901Sandrew // start_routine_ == 0 if we're on the main thread or on one of the 101229109Sed // OS X libdispatch worker threads. But nobody is supposed to call 102229109Sed // ThreadStart() for the worker threads. 103229109Sed CHECK(tid() == 0); 104229109Sed return 0; 105229109Sed } 106229109Sed 107238901Sandrew thread_return_t res = start_routine_(arg_); 108229109Sed malloc_storage().CommitBack(); 109238901Sandrew if (flags()->use_sigaltstack) UnsetAlternateSignalStack(); 110229109Sed 111238901Sandrew this->Destroy(); 112229109Sed 113229109Sed return res; 114229109Sed} 115229109Sed 116238901Sandrewvoid AsanThread::SetThreadStackTopAndBottom() { 117238901Sandrew GetThreadStackTopAndBottom(tid() == 0, &stack_top_, &stack_bottom_); 118238901Sandrew int local; 119238901Sandrew CHECK(AddrIsInStack((uptr)&local)); 120238901Sandrew} 121238901Sandrew 122238901Sandrewvoid AsanThread::ClearShadowForThreadStack() { 123238901Sandrew PoisonShadow(stack_bottom_, stack_top_ - stack_bottom_, 0); 124238901Sandrew} 125238901Sandrew 126238901Sandrewconst char *AsanThread::GetFrameNameByAddr(uptr addr, uptr *offset) { 127238901Sandrew uptr bottom = 0; 128229109Sed bool is_fake_stack = false; 129229109Sed if (AddrIsInStack(addr)) { 130229109Sed bottom = stack_bottom(); 131229109Sed } else { 132229109Sed bottom = fake_stack().AddrIsInFakeStack(addr); 133229109Sed CHECK(bottom); 134229109Sed is_fake_stack = true; 135229109Sed } 136238901Sandrew uptr aligned_addr = addr & ~(__WORDSIZE/8 - 1); // align addr. 137238901Sandrew u8 *shadow_ptr = (u8*)MemToShadow(aligned_addr); 138238901Sandrew u8 *shadow_bottom = (u8*)MemToShadow(bottom); 139238901Sandrew 140238901Sandrew while (shadow_ptr >= shadow_bottom && 141238901Sandrew *shadow_ptr != kAsanStackLeftRedzoneMagic) { 142238901Sandrew shadow_ptr--; 143229109Sed } 144229109Sed 145238901Sandrew while (shadow_ptr >= shadow_bottom && 146238901Sandrew *shadow_ptr == kAsanStackLeftRedzoneMagic) { 147238901Sandrew shadow_ptr--; 148238901Sandrew } 149229109Sed 150238901Sandrew if (shadow_ptr < shadow_bottom) { 151238901Sandrew *offset = 0; 152238901Sandrew return "UNKNOWN"; 153229109Sed } 154229109Sed 155238901Sandrew uptr* ptr = (uptr*)SHADOW_TO_MEM((uptr)(shadow_ptr + 1)); 156238901Sandrew CHECK((ptr[0] == kCurrentStackFrameMagic) || 157238901Sandrew (is_fake_stack && ptr[0] == kRetiredStackFrameMagic)); 158238901Sandrew *offset = addr - (uptr)ptr; 159238901Sandrew return (const char*)ptr[1]; 160229109Sed} 161229109Sed 162229109Sed} // namespace __asan 163