asan_thread.cc revision af3441580555ceed092170232cd5f2cc180f19f4
1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//===-- asan_thread.cc ------------------------------------------*- C++ -*-===// 2ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 3ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// The LLVM Compiler Infrastructure 4ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 5ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// This file is distributed under the University of Illinois Open Source 6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// License. See LICENSE.TXT for details. 7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 8ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//===----------------------------------------------------------------------===// 9ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 10ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// This file is a part of AddressSanitizer, an address sanity checker. 11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// 12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Thread-related code. 13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//===----------------------------------------------------------------------===// 14ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "asan_allocator.h" 15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "asan_interceptors.h" 16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "asan_procmaps.h" 17ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "asan_thread.h" 18#include "asan_thread_registry.h" 19#include "asan_mapping.h" 20 21namespace __asan { 22 23AsanThread::AsanThread(LinkerInitialized x) 24 : fake_stack_(x), 25 malloc_storage_(x), 26 stats_(x) { } 27 28AsanThread *AsanThread::Create(int parent_tid, void *(*start_routine) (void *), 29 void *arg) { 30 size_t size = RoundUpTo(sizeof(AsanThread), kPageSize); 31 AsanThread *res = (AsanThread*)AsanMmapSomewhereOrDie(size, __FUNCTION__); 32 res->start_routine_ = start_routine; 33 res->arg_ = arg; 34 return res; 35} 36 37void AsanThread::Destroy() { 38 fake_stack().Cleanup(); 39 // We also clear the shadow on thread destruction because 40 // some code may still be executing in later TSD destructors 41 // and we don't want it to have any poisoned stack. 42 ClearShadowForThreadStack(); 43 size_t size = RoundUpTo(sizeof(AsanThread), kPageSize); 44 AsanUnmapOrDie(this, size); 45} 46 47void AsanThread::ClearShadowForThreadStack() { 48 uintptr_t shadow_bot = MemToShadow(stack_bottom_); 49 uintptr_t shadow_top = MemToShadow(stack_top_); 50 real_memset((void*)shadow_bot, 0, shadow_top - shadow_bot); 51} 52 53void AsanThread::Init() { 54 SetThreadStackTopAndBottom(); 55 fake_stack_.Init(stack_size()); 56 if (FLAG_v >= 1) { 57 int local = 0; 58 Report("T%d: stack [%p,%p) size 0x%lx; local=%p\n", 59 tid(), stack_bottom_, stack_top_, 60 stack_top_ - stack_bottom_, &local); 61 } 62 63 CHECK(AddrIsInMem(stack_bottom_)); 64 CHECK(AddrIsInMem(stack_top_)); 65 66 ClearShadowForThreadStack(); 67} 68 69void *AsanThread::ThreadStart() { 70 Init(); 71 72 if (!start_routine_) { 73 // start_routine_ == NULL if we're on the main thread or on one of the 74 // OS X libdispatch worker threads. But nobody is supposed to call 75 // ThreadStart() for the worker threads. 76 CHECK(tid() == 0); 77 return 0; 78 } 79 80 void *res = start_routine_(arg_); 81 malloc_storage().CommitBack(); 82 83 if (FLAG_v >= 1) { 84 Report("T%d exited\n", tid()); 85 } 86 87 asanThreadRegistry().UnregisterThread(this); 88 this->Destroy(); 89 90 return res; 91} 92 93const char *AsanThread::GetFrameNameByAddr(uintptr_t addr, uintptr_t *offset) { 94 uintptr_t bottom = 0; 95 bool is_fake_stack = false; 96 if (AddrIsInStack(addr)) { 97 bottom = stack_bottom(); 98 } else { 99 bottom = fake_stack().AddrIsInFakeStack(addr); 100 CHECK(bottom); 101 is_fake_stack = true; 102 } 103 uintptr_t aligned_addr = addr & ~(__WORDSIZE/8 - 1); // align addr. 104 uintptr_t *ptr = (uintptr_t*)aligned_addr; 105 while (ptr >= (uintptr_t*)bottom) { 106 if (ptr[0] == kCurrentStackFrameMagic || 107 (is_fake_stack && ptr[0] == kRetiredStackFrameMagic)) { 108 *offset = addr - (uintptr_t)ptr; 109 return (const char*)ptr[1]; 110 } 111 ptr--; 112 } 113 *offset = 0; 114 return "UNKNOWN"; 115} 116 117} // namespace __asan 118