asan_thread.cc revision a7e760a53bc43b8e09bfdf5cd6f215267ba99729
11e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===-- asan_thread.cc ------------------------------------------*- C++ -*-===// 21e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 31e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// The LLVM Compiler Infrastructure 41e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 51e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// This file is distributed under the University of Illinois Open Source 61e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// License. See LICENSE.TXT for details. 71e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 81e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===----------------------------------------------------------------------===// 91e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// This file is a part of AddressSanitizer, an address sanity checker. 111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Thread-related code. 131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===----------------------------------------------------------------------===// 141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_allocator.h" 151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_interceptors.h" 16df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany#include "asan_procmaps.h" 171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_thread.h" 181e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_mapping.h" 191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace __asan { 211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 221e172b4bdec57329bf904f063a29f99cddf2d85fKostya SerebryanyAsanThread::AsanThread(LinkerInitialized x) 231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany : fake_stack_(x), 241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany malloc_storage_(x), 251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany stats_(x) { } 261e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 27a6b52264e1231bfc4ee9a2d9a4f32678c97295f0Kostya SerebryanyAsanThread *AsanThread::Create(int parent_tid, void *(*start_routine) (void *), 28a6b52264e1231bfc4ee9a2d9a4f32678c97295f0Kostya Serebryany void *arg) { 29a6b52264e1231bfc4ee9a2d9a4f32678c97295f0Kostya Serebryany size_t size = RoundUpTo(sizeof(AsanThread), kPageSize); 30a6b52264e1231bfc4ee9a2d9a4f32678c97295f0Kostya Serebryany AsanThread *res = (AsanThread*)AsanMmapSomewhereOrDie(size, __FUNCTION__); 31a6b52264e1231bfc4ee9a2d9a4f32678c97295f0Kostya Serebryany res->start_routine_ = start_routine; 32a6b52264e1231bfc4ee9a2d9a4f32678c97295f0Kostya Serebryany res->arg_ = arg; 33a6b52264e1231bfc4ee9a2d9a4f32678c97295f0Kostya Serebryany return res; 341e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 351e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 36a6b52264e1231bfc4ee9a2d9a4f32678c97295f0Kostya Serebryanyvoid AsanThread::Destroy() { 371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany fake_stack().Cleanup(); 381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // We also clear the shadow on thread destruction because 391e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // some code may still be executing in later TSD destructors 401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // and we don't want it to have any poisoned stack. 411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ClearShadowForThreadStack(); 42a6b52264e1231bfc4ee9a2d9a4f32678c97295f0Kostya Serebryany size_t size = RoundUpTo(sizeof(AsanThread), kPageSize); 43a6b52264e1231bfc4ee9a2d9a4f32678c97295f0Kostya Serebryany AsanUnmapOrDie(this, size); 441e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 451e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 461e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid AsanThread::ClearShadowForThreadStack() { 471e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany uintptr_t shadow_bot = MemToShadow(stack_bottom_); 481e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany uintptr_t shadow_top = MemToShadow(stack_top_); 491e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany real_memset((void*)shadow_bot, 0, shadow_top - shadow_bot); 501e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 511e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 5269eca73ac96688c8bfe1f23ee006af29c7858c40Kostya Serebryanyvoid AsanThread::Init() { 531e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany SetThreadStackTopAndBottom(); 541e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany fake_stack_.Init(stack_size()); 551e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (FLAG_v >= 1) { 561e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany int local = 0; 57a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany Report("T%d: stack [%p,%p) size 0x%lx; local=%p\n", 581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany tid(), stack_bottom_, stack_top_, 59a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany stack_top_ - stack_bottom_, &local); 601e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 611e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 621e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany CHECK(AddrIsInMem(stack_bottom_)); 631e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany CHECK(AddrIsInMem(stack_top_)); 641e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ClearShadowForThreadStack(); 6669eca73ac96688c8bfe1f23ee006af29c7858c40Kostya Serebryany} 6769eca73ac96688c8bfe1f23ee006af29c7858c40Kostya Serebryany 6869eca73ac96688c8bfe1f23ee006af29c7858c40Kostya Serebryanyvoid *AsanThread::ThreadStart() { 6969eca73ac96688c8bfe1f23ee006af29c7858c40Kostya Serebryany Init(); 701e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 711e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (!start_routine_) { 721e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // start_routine_ == NULL if we're on the main thread or on one of the 731e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // OS X libdispatch worker threads. But nobody is supposed to call 741e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // ThreadStart() for the worker threads. 751e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany CHECK(tid() == 0); 761e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return 0; 771e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 781e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 791e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany void *res = start_routine_(arg_); 801e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany malloc_storage().CommitBack(); 811e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 821e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (FLAG_v >= 1) { 831e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany Report("T%d exited\n", tid()); 841e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 851e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 861e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return res; 871e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 881e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 891e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyconst char *AsanThread::GetFrameNameByAddr(uintptr_t addr, uintptr_t *offset) { 901e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany uintptr_t bottom = 0; 911e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany bool is_fake_stack = false; 921e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (AddrIsInStack(addr)) { 931e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany bottom = stack_bottom(); 941e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } else { 951e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany bottom = fake_stack().AddrIsInFakeStack(addr); 961e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany CHECK(bottom); 971e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany is_fake_stack = true; 981e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 991e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany uintptr_t aligned_addr = addr & ~(__WORDSIZE/8 - 1); // align addr. 1001e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany uintptr_t *ptr = (uintptr_t*)aligned_addr; 1011e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany while (ptr >= (uintptr_t*)bottom) { 1021e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany if (ptr[0] == kCurrentStackFrameMagic || 1031e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany (is_fake_stack && ptr[0] == kRetiredStackFrameMagic)) { 1041e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany *offset = addr - (uintptr_t)ptr; 1051e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return (const char*)ptr[1]; 1061e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 1071e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany ptr--; 1081e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany } 1091e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany *offset = 0; 1101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany return "UNKNOWN"; 1111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 1131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} // namespace __asan 114