asan_thread.h revision 314564
152419Sjulian//===-- asan_thread.h -------------------------------------------*- C++ -*-===//
252419Sjulian//
352419Sjulian//                     The LLVM Compiler Infrastructure
452419Sjulian//
552419Sjulian// This file is distributed under the University of Illinois Open Source
652419Sjulian// License. See LICENSE.TXT for details.
752419Sjulian//
852419Sjulian//===----------------------------------------------------------------------===//
952419Sjulian//
1052419Sjulian// This file is a part of AddressSanitizer, an address sanity checker.
1152419Sjulian//
1252419Sjulian// ASan-private header for asan_thread.cc.
1352419Sjulian//===----------------------------------------------------------------------===//
1452419Sjulian
1552419Sjulian#ifndef ASAN_THREAD_H
1652419Sjulian#define ASAN_THREAD_H
1752419Sjulian
1852419Sjulian#include "asan_allocator.h"
1952419Sjulian#include "asan_internal.h"
2052419Sjulian#include "asan_fake_stack.h"
2152419Sjulian#include "asan_stats.h"
2252419Sjulian#include "sanitizer_common/sanitizer_common.h"
2352419Sjulian#include "sanitizer_common/sanitizer_libc.h"
2452419Sjulian#include "sanitizer_common/sanitizer_thread_registry.h"
2552419Sjulian
2652419Sjuliannamespace __sanitizer {
2752419Sjulianstruct DTLS;
2852419Sjulian}  // namespace __sanitizer
2952419Sjulian
3052419Sjuliannamespace __asan {
3152419Sjulian
3252419Sjulianconst u32 kInvalidTid = 0xffffff;  // Must fit into 24 bits.
3352419Sjulianconst u32 kMaxNumberOfThreads = (1 << 22);  // 4M
3452419Sjulian
3552419Sjulianclass AsanThread;
3652419Sjulian
3752419Sjulian// These objects are created for every thread and are never deleted,
3852419Sjulian// so we can find them by tid even if the thread is long dead.
3952419Sjulianclass AsanThreadContext : public ThreadContextBase {
4052419Sjulian public:
4152419Sjulian  explicit AsanThreadContext(int tid)
4252419Sjulian      : ThreadContextBase(tid), announced(false),
4352419Sjulian        destructor_iterations(GetPthreadDestructorIterations()), stack_id(0),
4456708Sarchie        thread(nullptr) {}
4552419Sjulian  bool announced;
4652419Sjulian  u8 destructor_iterations;
47169551Smav  u32 stack_id;
4856708Sarchie  AsanThread *thread;
49122649Sharti
5052419Sjulian  void OnCreated(void *arg) override;
5152419Sjulian  void OnFinished() override;
5252419Sjulian};
5352419Sjulian
5452419Sjulian// AsanThreadContext objects are never freed, so we need many of them.
5552419SjulianCOMPILER_CHECK(sizeof(AsanThreadContext) <= 256);
5652419Sjulian
5752419Sjulian// AsanThread are stored in TSD and destroyed when the thread dies.
5852419Sjulianclass AsanThread {
59122649Sharti public:
60122649Sharti  static AsanThread *Create(thread_callback_t start_routine, void *arg,
61122649Sharti                            u32 parent_tid, StackTrace *stack, bool detached);
62122649Sharti  static void TSDDtor(void *tsd);
6352419Sjulian  void Destroy();
6452419Sjulian
6552419Sjulian  void Init();  // Should be called from the thread itself.
6652419Sjulian  thread_return_t ThreadStart(uptr os_id,
6752419Sjulian                              atomic_uintptr_t *signal_thread_is_registered);
6852419Sjulian
6952419Sjulian  uptr stack_top();
7052419Sjulian  uptr stack_bottom();
7153913Sarchie  uptr stack_size();
7253913Sarchie  uptr tls_begin() { return tls_begin_; }
7352419Sjulian  uptr tls_end() { return tls_end_; }
7452419Sjulian  DTLS *dtls() { return dtls_; }
75  u32 tid() { return context_->tid; }
76  AsanThreadContext *context() { return context_; }
77  void set_context(AsanThreadContext *context) { context_ = context; }
78
79  struct StackFrameAccess {
80    uptr offset;
81    uptr frame_pc;
82    const char *frame_descr;
83  };
84  bool GetStackFrameAccessByAddr(uptr addr, StackFrameAccess *access);
85
86  bool AddrIsInStack(uptr addr);
87
88  void DeleteFakeStack(int tid) {
89    if (!fake_stack_) return;
90    FakeStack *t = fake_stack_;
91    fake_stack_ = nullptr;
92    SetTLSFakeStack(nullptr);
93    t->Destroy(tid);
94  }
95
96  void StartSwitchFiber(FakeStack **fake_stack_save, uptr bottom, uptr size);
97  void FinishSwitchFiber(FakeStack *fake_stack_save, uptr *bottom_old,
98                         uptr *size_old);
99
100  bool has_fake_stack() {
101    return !atomic_load(&stack_switching_, memory_order_relaxed) &&
102           (reinterpret_cast<uptr>(fake_stack_) > 1);
103  }
104
105  FakeStack *fake_stack() {
106    if (!__asan_option_detect_stack_use_after_return)
107      return nullptr;
108    if (atomic_load(&stack_switching_, memory_order_relaxed))
109      return nullptr;
110    if (!has_fake_stack())
111      return AsyncSignalSafeLazyInitFakeStack();
112    return fake_stack_;
113  }
114
115  // True is this thread is currently unwinding stack (i.e. collecting a stack
116  // trace). Used to prevent deadlocks on platforms where libc unwinder calls
117  // malloc internally. See PR17116 for more details.
118  bool isUnwinding() const { return unwinding_; }
119  void setUnwinding(bool b) { unwinding_ = b; }
120
121  // True if we are in a deadly signal handler.
122  bool isInDeadlySignal() const { return in_deadly_signal_; }
123  void setInDeadlySignal(bool b) { in_deadly_signal_ = b; }
124
125  AsanThreadLocalMallocStorage &malloc_storage() { return malloc_storage_; }
126  AsanStats &stats() { return stats_; }
127
128 private:
129  // NOTE: There is no AsanThread constructor. It is allocated
130  // via mmap() and *must* be valid in zero-initialized state.
131  void SetThreadStackAndTls();
132  void ClearShadowForThreadStackAndTLS();
133  FakeStack *AsyncSignalSafeLazyInitFakeStack();
134
135  struct StackBounds {
136    uptr bottom;
137    uptr top;
138  };
139  StackBounds GetStackBounds() const;
140
141  AsanThreadContext *context_;
142  thread_callback_t start_routine_;
143  void *arg_;
144
145  uptr stack_top_;
146  uptr stack_bottom_;
147  // these variables are used when the thread is about to switch stack
148  uptr next_stack_top_;
149  uptr next_stack_bottom_;
150  // true if switching is in progress
151  atomic_uint8_t stack_switching_;
152
153  uptr tls_begin_;
154  uptr tls_end_;
155  DTLS *dtls_;
156
157  FakeStack *fake_stack_;
158  AsanThreadLocalMallocStorage malloc_storage_;
159  AsanStats stats_;
160  bool unwinding_;
161  bool in_deadly_signal_;
162};
163
164// ScopedUnwinding is a scope for stacktracing member of a context
165class ScopedUnwinding {
166 public:
167  explicit ScopedUnwinding(AsanThread *t) : thread(t) {
168    t->setUnwinding(true);
169  }
170  ~ScopedUnwinding() { thread->setUnwinding(false); }
171
172 private:
173  AsanThread *thread;
174};
175
176// ScopedDeadlySignal is a scope for handling deadly signals.
177class ScopedDeadlySignal {
178 public:
179  explicit ScopedDeadlySignal(AsanThread *t) : thread(t) {
180    if (thread) thread->setInDeadlySignal(true);
181  }
182  ~ScopedDeadlySignal() {
183    if (thread) thread->setInDeadlySignal(false);
184  }
185
186 private:
187  AsanThread *thread;
188};
189
190// Returns a single instance of registry.
191ThreadRegistry &asanThreadRegistry();
192
193// Must be called under ThreadRegistryLock.
194AsanThreadContext *GetThreadContextByTidLocked(u32 tid);
195
196// Get the current thread. May return 0.
197AsanThread *GetCurrentThread();
198void SetCurrentThread(AsanThread *t);
199u32 GetCurrentTidOrInvalid();
200AsanThread *FindThreadByStackAddress(uptr addr);
201
202// Used to handle fork().
203void EnsureMainThreadIDIsCorrect();
204} // namespace __asan
205
206#endif // ASAN_THREAD_H
207