asan_thread.cc revision ee3925515e4c7966f3ef489f687aa7e5692806a9
1c3aae25116e66c177579b0b79182b09340b19753Chris Lattner//===-- asan_thread.cc ------------------------------------------*- C++ -*-===// 2ea61c358720aa6c7a159d51658b34276316aa841Misha Brukman// 36fbcc26f1460eaee4e0eb8b426fc1ff0c7af11beJohn Criswell// The LLVM Compiler Infrastructure 46fbcc26f1460eaee4e0eb8b426fc1ff0c7af11beJohn Criswell// 57ed47a13356daed2a34cd2209a31f92552e3bdd8Chris Lattner// This file is distributed under the University of Illinois Open Source 67ed47a13356daed2a34cd2209a31f92552e3bdd8Chris Lattner// License. See LICENSE.TXT for details. 7ea61c358720aa6c7a159d51658b34276316aa841Misha Brukman// 86fbcc26f1460eaee4e0eb8b426fc1ff0c7af11beJohn Criswell//===----------------------------------------------------------------------===// 9ea61c358720aa6c7a159d51658b34276316aa841Misha Brukman// 10c3aae25116e66c177579b0b79182b09340b19753Chris Lattner// This file is a part of AddressSanitizer, an address sanity checker. 11c3aae25116e66c177579b0b79182b09340b19753Chris Lattner// 12ea61c358720aa6c7a159d51658b34276316aa841Misha Brukman// Thread-related code. 13cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner//===----------------------------------------------------------------------===// 14cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner#include "asan_allocator.h" 15cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner#include "asan_interceptors.h" 16cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner#include "asan_procmaps.h" 17cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner#include "asan_stack.h" 18fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman#include "asan_thread.h" 19c5e7e8d87d4a3b10edd5ac93ba1f3cdb4d1b449aDavid Greene#include "asan_thread_registry.h" 20583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey#include "asan_mapping.h" 214b84086e89d86fb16f562166d9fea8df37db6be7Dan Gohman 22583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskeynamespace __asan { 23b80e2be8894db9f843f32ebaffb9b7fd6b57d206Chris Lattner 24acaf09dbe4a6781163857db1321bbd5795e7d410Dan GohmanAsanThread::AsanThread(LinkerInitialized x) 255892d47a625638a90afeb31dd4f6f80a2f9bacdeChris Lattner : fake_stack_(x), 26322812e603705e1c2037313633e72f689524b163Evan Cheng malloc_storage_(x), 27eb19e40efbd3cae80c908a30cdf4d33450733c45Chris Lattner stats_(x) { } 28d0fde30ce850b78371fd1386338350591f9ff494Brian Gaeke 29d0fde30ce850b78371fd1386338350591f9ff494Brian GaekeAsanThread *AsanThread::Create(int parent_tid, thread_callback_t start_routine, 30fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman void *arg, AsanStackTrace *stack) { 31fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman uptr size = RoundUpTo(sizeof(AsanThread), kPageSize); 32fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman AsanThread *thread = (AsanThread*)AsanMmapSomewhereOrDie(size, __FUNCTION__); 33fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman thread->start_routine_ = start_routine; 34fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman thread->arg_ = arg; 356e7a1617ac4a34792d9097b8d3644b72f57a45f7Devang Patel 36fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman AsanThreadSummary *summary = new AsanThreadSummary(parent_tid, stack); 37fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman summary->set_thread(thread); 38fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman thread->set_summary(summary); 39fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman 408e4018e2de52c534405d7155c7009d0b35afb861Cedric Venet return thread; 418e4018e2de52c534405d7155c7009d0b35afb861Cedric Venet} 42c7f6b8c5d40e17bf43fd3a1549d7d89c9da735e1Gabor Greif 43fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohmanvoid AsanThreadSummary::TSDDtor(void *tsd) { 44fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman AsanThreadSummary *summary = (AsanThreadSummary*)tsd; 45c7f6b8c5d40e17bf43fd3a1549d7d89c9da735e1Gabor Greif if (FLAG_v >= 1) { 46fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman Report("T%d TSDDtor\n", summary->tid()); 47fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman } 48fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman if (summary->thread()) { 49c23b8719ef9d6b1220e854b37d40e9e1c48a82bcGabor Greif summary->thread()->Destroy(); 50c23b8719ef9d6b1220e854b37d40e9e1c48a82bcGabor Greif } 51c23b8719ef9d6b1220e854b37d40e9e1c48a82bcGabor Greif} 52fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman 53fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohmanvoid AsanThread::Destroy() { 54fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman if (FLAG_v >= 1) { 55fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman Report("T%d exited\n", tid()); 56fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman } 57fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman 58c3aae25116e66c177579b0b79182b09340b19753Chris Lattner asanThreadRegistry().UnregisterThread(this); 5925cf2275ff7de3de3bc0e508abaf457413d74725Duncan Sands CHECK(summary()->thread() == 0); 6025cf2275ff7de3de3bc0e508abaf457413d74725Duncan Sands // We also clear the shadow on thread destruction because 6125cf2275ff7de3de3bc0e508abaf457413d74725Duncan Sands // some code may still be executing in later TSD destructors 6225cf2275ff7de3de3bc0e508abaf457413d74725Duncan Sands // and we don't want it to have any poisoned stack. 6325cf2275ff7de3de3bc0e508abaf457413d74725Duncan Sands ClearShadowForThreadStack(); 6425cf2275ff7de3de3bc0e508abaf457413d74725Duncan Sands fake_stack().Cleanup(); 65c3aae25116e66c177579b0b79182b09340b19753Chris Lattner uptr size = RoundUpTo(sizeof(AsanThread), kPageSize); 66c3aae25116e66c177579b0b79182b09340b19753Chris Lattner AsanUnmapOrDie(this, size); 67c3aae25116e66c177579b0b79182b09340b19753Chris Lattner} 68c3aae25116e66c177579b0b79182b09340b19753Chris Lattner 69c3aae25116e66c177579b0b79182b09340b19753Chris Lattnervoid AsanThread::Init() { 70c3aae25116e66c177579b0b79182b09340b19753Chris Lattner SetThreadStackTopAndBottom(); 71c3aae25116e66c177579b0b79182b09340b19753Chris Lattner CHECK(AddrIsInMem(stack_bottom_)); 72c3aae25116e66c177579b0b79182b09340b19753Chris Lattner CHECK(AddrIsInMem(stack_top_)); 73c3aae25116e66c177579b0b79182b09340b19753Chris Lattner ClearShadowForThreadStack(); 74c3aae25116e66c177579b0b79182b09340b19753Chris Lattner if (FLAG_v >= 1) { 75cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner int local = 0; 76cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner Report("T%d: stack [%p,%p) size 0x%zx; local=%p\n", 77063287a76b5d1486f498fcf674a26d1155471a3fChris Lattner tid(), stack_bottom_, stack_top_, 787c3234c6be0dc0bdf4b5d6f848cd728a77f349d7Dan Gohman stack_top_ - stack_bottom_, &local); 79ead0d88ad7659dabd66cc3149af97d98256fca84Chris Lattner } 8044c3b9fdd416c79f4b67cde1aecfced5921efd81Jim Laskey fake_stack_.Init(stack_size()); 816e7a1617ac4a34792d9097b8d3644b72f57a45f7Devang Patel} 82cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner 83f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohmanthread_return_t AsanThread::ThreadStart() { 84f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman Init(); 85f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman if (FLAG_use_sigaltstack) SetAlternateSignalStack(); 86f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman 87f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman if (!start_routine_) { 88cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner // start_routine_ == 0 if we're on the main thread or on one of the 89213a16c637926bfc38ba373d3aba6778e181e3ecChris Lattner // OS X libdispatch worker threads. But nobody is supposed to call 90fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman // ThreadStart() for the worker threads. 91fed90b6d097d50881afb45e4d79f430db66dd741Dan Gohman CHECK(tid() == 0); 92f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman return 0; 93f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman } 94f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman 95f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman thread_return_t res = start_routine_(arg_); 96f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman malloc_storage().CommitBack(); 97f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman if (FLAG_use_sigaltstack) UnsetAlternateSignalStack(); 98f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman 99f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman this->Destroy(); 100691ef2ba066dda14ae4ac0ad645054fbc967785aAndrew Lenharth 101213a16c637926bfc38ba373d3aba6778e181e3ecChris Lattner return res; 102213a16c637926bfc38ba373d3aba6778e181e3ecChris Lattner} 103583bd47f777fe3eb8305872fa0eadab31e833dffJim Laskey 104213a16c637926bfc38ba373d3aba6778e181e3ecChris Lattnervoid AsanThread::ClearShadowForThreadStack() { 105f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman PoisonShadow(stack_bottom_, stack_top_ - stack_bottom_, 0); 106f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman} 107f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman 108e8be6c63915e0389f1eef6b53c64300d13b2ce99Dan Gohmanconst char *AsanThread::GetFrameNameByAddr(uptr addr, uptr *offset) { 109e8be6c63915e0389f1eef6b53c64300d13b2ce99Dan Gohman uptr bottom = 0; 110e8be6c63915e0389f1eef6b53c64300d13b2ce99Dan Gohman bool is_fake_stack = false; 111e8be6c63915e0389f1eef6b53c64300d13b2ce99Dan Gohman if (AddrIsInStack(addr)) { 112d038e04188047eca4749d025ef1f05f7ae660bcaDuncan Sands bottom = stack_bottom(); 113d038e04188047eca4749d025ef1f05f7ae660bcaDuncan Sands } else { 114d038e04188047eca4749d025ef1f05f7ae660bcaDuncan Sands bottom = fake_stack().AddrIsInFakeStack(addr); 115c5e7e8d87d4a3b10edd5ac93ba1f3cdb4d1b449aDavid Greene CHECK(bottom); 116c5e7e8d87d4a3b10edd5ac93ba1f3cdb4d1b449aDavid Greene is_fake_stack = true; 117c5e7e8d87d4a3b10edd5ac93ba1f3cdb4d1b449aDavid Greene } 118c23b8719ef9d6b1220e854b37d40e9e1c48a82bcGabor Greif uptr aligned_addr = addr & ~(__WORDSIZE/8 - 1); // align addr. 119c23b8719ef9d6b1220e854b37d40e9e1c48a82bcGabor Greif u8 *shadow_ptr = (u8*)MemToShadow(aligned_addr); 120c5e7e8d87d4a3b10edd5ac93ba1f3cdb4d1b449aDavid Greene u8 *shadow_bottom = (u8*)MemToShadow(bottom); 121c5e7e8d87d4a3b10edd5ac93ba1f3cdb4d1b449aDavid Greene 122cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner while (shadow_ptr >= shadow_bottom && 1237c3234c6be0dc0bdf4b5d6f848cd728a77f349d7Dan Gohman *shadow_ptr != kAsanStackLeftRedzoneMagic) { 124cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner shadow_ptr--; 125cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner } 1267c3234c6be0dc0bdf4b5d6f848cd728a77f349d7Dan Gohman 1277c3234c6be0dc0bdf4b5d6f848cd728a77f349d7Dan Gohman while (shadow_ptr >= shadow_bottom && 1287c3234c6be0dc0bdf4b5d6f848cd728a77f349d7Dan Gohman *shadow_ptr == kAsanStackLeftRedzoneMagic) { 1296e7a1617ac4a34792d9097b8d3644b72f57a45f7Devang Patel shadow_ptr--; 1307c3234c6be0dc0bdf4b5d6f848cd728a77f349d7Dan Gohman } 1317c3234c6be0dc0bdf4b5d6f848cd728a77f349d7Dan Gohman 132f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman if (shadow_ptr < shadow_bottom) { 133f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman *offset = 0; 1347c3234c6be0dc0bdf4b5d6f848cd728a77f349d7Dan Gohman return "UNKNOWN"; 135f350b277f32d7d47f86c0e54f4aec4d470500618Dan Gohman } 1367c3234c6be0dc0bdf4b5d6f848cd728a77f349d7Dan Gohman 137063287a76b5d1486f498fcf674a26d1155471a3fChris Lattner uptr* ptr = (uptr*)SHADOW_TO_MEM((uptr)(shadow_ptr + 1)); 138063287a76b5d1486f498fcf674a26d1155471a3fChris Lattner CHECK((ptr[0] == kCurrentStackFrameMagic) || 139ead0d88ad7659dabd66cc3149af97d98256fca84Chris Lattner (is_fake_stack && ptr[0] == kRetiredStackFrameMagic)); 14044c3b9fdd416c79f4b67cde1aecfced5921efd81Jim Laskey *offset = addr - (uptr)ptr; 14183489bb7700c69b7a4a8da59365c42d3f5c8129bDevang Patel return (const char*)ptr[1]; 142cacf462915344c2af25eef1af1f3ee2c7280ff56Chris Lattner} 143ec20402c90b605afeedbcf0e3aabe6f8054f23ddJim Laskey 1441080b9ee534579c67f7c99364cc6fa11edbcd919Chris Lattner} // namespace __asan 145462dc7f4960e5074ddf4769ec8b2ef1ba7a4d2c8Dan Gohman