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