asan_thread.h revision c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6
17757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch//===-- asan_thread.h -------------------------------------------*- C++ -*-===// 27757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch// 37757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch// The LLVM Compiler Infrastructure 47757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch// 57757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch// This file is distributed under the University of Illinois Open Source 67757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch// License. See LICENSE.TXT for details. 77757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch// 87757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch//===----------------------------------------------------------------------===// 97757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch// 107757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch// This file is a part of AddressSanitizer, an address sanity checker. 117757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch// 127757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch// ASan-private header for asan_thread.cc. 137757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch//===----------------------------------------------------------------------===// 147757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#ifndef ASAN_THREAD_H 157757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#define ASAN_THREAD_H 167757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 177757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "asan_allocator.h" 187757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "asan_internal.h" 197757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "asan_fake_stack.h" 207757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "asan_stack.h" 217757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "asan_stats.h" 227757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "sanitizer_common/sanitizer_libc.h" 237757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch#include "sanitizer_common/sanitizer_thread_registry.h" 247757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 257757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochnamespace __asan { 267757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 277757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochconst u32 kInvalidTid = 0xffffff; // Must fit into 24 bits. 287757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochconst u32 kMaxNumberOfThreads = (1 << 22); // 4M 297757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 307757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochclass AsanThread; 317757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 327757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch// These objects are created for every thread and are never deleted, 337757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch// so we can find them by tid even if the thread is long dead. 347757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochclass AsanThreadContext : public ThreadContextBase { 357757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch public: 367757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch explicit AsanThreadContext(int tid) 377757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch : ThreadContextBase(tid), 387757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch announced(false), 397757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch thread(0) { 407757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch internal_memset(&stack, 0, sizeof(stack)); 417757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 427757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch bool announced; 437757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch StackTrace stack; 447757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch AsanThread *thread; 457757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 467757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch void OnCreated(void *arg); 477757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch void OnFinished(); 487757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch}; 497757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 507757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch// AsanThreadContext objects are never freed, so we need many of them. 517757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen MurdochCOMPILER_CHECK(sizeof(AsanThreadContext) <= 4096); 527757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 537757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch// AsanThread are stored in TSD and destroyed when the thread dies. 547757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdochclass AsanThread { 557757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch public: 567757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch static AsanThread *Create(thread_callback_t start_routine, void *arg); 577757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch static void TSDDtor(void *tsd); 587757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch void Destroy(); 597757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 607757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch void Init(); // Should be called from the thread itself. 617757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch thread_return_t ThreadStart(uptr os_id); 627757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 637757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch uptr stack_top() { return stack_top_; } 647757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch uptr stack_bottom() { return stack_bottom_; } 657757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch uptr stack_size() { return stack_top_ - stack_bottom_; } 667757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch uptr tls_begin() { return tls_begin_; } 677757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch uptr tls_end() { return tls_end_; } 687757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch u32 tid() { return context_->tid; } 697757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch AsanThreadContext *context() { return context_; } 707757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch void set_context(AsanThreadContext *context) { context_ = context; } 717757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 727757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch const char *GetFrameNameByAddr(uptr addr, uptr *offset, uptr *frame_pc); 737757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 747757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch bool AddrIsInStack(uptr addr) { 757757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch return addr >= stack_bottom_ && addr < stack_top_; 767757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 777757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 787757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch void LazyInitFakeStack() { 797757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (fake_stack_) return; 807757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch fake_stack_ = (FakeStack*)MmapOrDie(sizeof(FakeStack), "FakeStack"); 817757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch fake_stack_->Init(stack_size()); 827757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 837757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch void DeleteFakeStack() { 847757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch if (!fake_stack_) return; 857757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch fake_stack_->Cleanup(); 867757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch UnmapOrDie(fake_stack_, sizeof(FakeStack)); 877757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch } 887757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch FakeStack *fake_stack() { return fake_stack_; } 897757ec2eadfa2dd8ac2aeed0a4399e9b07ec38cbBen Murdoch 90 AsanThreadLocalMallocStorage &malloc_storage() { return malloc_storage_; } 91 AsanStats &stats() { return stats_; } 92 93 private: 94 AsanThread() {} 95 void SetThreadStackAndTls(); 96 void ClearShadowForThreadStackAndTLS(); 97 AsanThreadContext *context_; 98 thread_callback_t start_routine_; 99 void *arg_; 100 uptr stack_top_; 101 uptr stack_bottom_; 102 uptr tls_begin_; 103 uptr tls_end_; 104 105 FakeStack *fake_stack_; 106 AsanThreadLocalMallocStorage malloc_storage_; 107 AsanStats stats_; 108}; 109 110struct CreateThreadContextArgs { 111 AsanThread *thread; 112 StackTrace *stack; 113}; 114 115// Returns a single instance of registry. 116ThreadRegistry &asanThreadRegistry(); 117 118// Must be called under ThreadRegistryLock. 119AsanThreadContext *GetThreadContextByTidLocked(u32 tid); 120 121// Get the current thread. May return 0. 122AsanThread *GetCurrentThread(); 123void SetCurrentThread(AsanThread *t); 124u32 GetCurrentTidOrInvalid(); 125AsanThread *FindThreadByStackAddress(uptr addr); 126 127// Used to handle fork(). 128void EnsureMainThreadIDIsCorrect(); 129} // namespace __asan 130 131#endif // ASAN_THREAD_H 132