1//===-- asan_thread.h -------------------------------------------*- C++ -*-===//
2//
3// This file is distributed under the University of Illinois Open Source
4// License. See LICENSE.TXT for details.
5//
6//===----------------------------------------------------------------------===//
7//
8// This file is a part of AddressSanitizer, an address sanity checker.
9//
10// ASan-private header for asan_thread.cc.
11//===----------------------------------------------------------------------===//
12
13#ifndef ASAN_THREAD_H
14#define ASAN_THREAD_H
15
16#include "asan_allocator.h"
17#include "asan_internal.h"
18#include "asan_fake_stack.h"
19#include "asan_stats.h"
20#include "sanitizer_common/sanitizer_common.h"
21#include "sanitizer_common/sanitizer_libc.h"
22#include "sanitizer_common/sanitizer_thread_registry.h"
23
24namespace __sanitizer {
25struct DTLS;
26}  // namespace __sanitizer
27
28namespace __asan {
29
30const u32 kInvalidTid = 0xffffff;  // Must fit into 24 bits.
31const u32 kMaxNumberOfThreads = (1 << 22);  // 4M
32
33class AsanThread;
34
35// These objects are created for every thread and are never deleted,
36// so we can find them by tid even if the thread is long dead.
37class AsanThreadContext : public ThreadContextBase {
38 public:
39  explicit AsanThreadContext(int tid)
40      : ThreadContextBase(tid), announced(false),
41        destructor_iterations(GetPthreadDestructorIterations()), stack_id(0),
42        thread(nullptr) {}
43  bool announced;
44  u8 destructor_iterations;
45  u32 stack_id;
46  AsanThread *thread;
47
48  void OnCreated(void *arg) override;
49  void OnFinished() override;
50
51  struct CreateThreadContextArgs {
52    AsanThread *thread;
53    StackTrace *stack;
54  };
55};
56
57// AsanThreadContext objects are never freed, so we need many of them.
58COMPILER_CHECK(sizeof(AsanThreadContext) <= 256);
59
60// AsanThread are stored in TSD and destroyed when the thread dies.
61class AsanThread {
62 public:
63  static AsanThread *Create(thread_callback_t start_routine, void *arg,
64                            u32 parent_tid, StackTrace *stack, bool detached);
65  static void TSDDtor(void *tsd);
66  void Destroy();
67
68  struct InitOptions;
69  void Init(const InitOptions *options = nullptr);
70
71  thread_return_t ThreadStart(tid_t os_id,
72                              atomic_uintptr_t *signal_thread_is_registered);
73
74  uptr stack_top();
75  uptr stack_bottom();
76  uptr stack_size();
77  uptr tls_begin() { return tls_begin_; }
78  uptr tls_end() { return tls_end_; }
79  DTLS *dtls() { return dtls_; }
80  u32 tid() { return context_->tid; }
81  AsanThreadContext *context() { return context_; }
82  void set_context(AsanThreadContext *context) { context_ = context; }
83
84  struct StackFrameAccess {
85    uptr offset;
86    uptr frame_pc;
87    const char *frame_descr;
88  };
89  bool GetStackFrameAccessByAddr(uptr addr, StackFrameAccess *access);
90
91  // Returns a pointer to the start of the stack variable's shadow memory.
92  uptr GetStackVariableShadowStart(uptr addr);
93
94  bool AddrIsInStack(uptr addr);
95
96  void DeleteFakeStack(int tid) {
97    if (!fake_stack_) return;
98    FakeStack *t = fake_stack_;
99    fake_stack_ = nullptr;
100    SetTLSFakeStack(nullptr);
101    t->Destroy(tid);
102  }
103
104  void StartSwitchFiber(FakeStack **fake_stack_save, uptr bottom, uptr size);
105  void FinishSwitchFiber(FakeStack *fake_stack_save, uptr *bottom_old,
106                         uptr *size_old);
107
108  bool has_fake_stack() {
109    return !atomic_load(&stack_switching_, memory_order_relaxed) &&
110           (reinterpret_cast<uptr>(fake_stack_) > 1);
111  }
112
113  FakeStack *fake_stack() {
114    if (!__asan_option_detect_stack_use_after_return)
115      return nullptr;
116    if (atomic_load(&stack_switching_, memory_order_relaxed))
117      return nullptr;
118    if (!has_fake_stack())
119      return AsyncSignalSafeLazyInitFakeStack();
120    return fake_stack_;
121  }
122
123  // True is this thread is currently unwinding stack (i.e. collecting a stack
124  // trace). Used to prevent deadlocks on platforms where libc unwinder calls
125  // malloc internally. See PR17116 for more details.
126  bool isUnwinding() const { return unwinding_; }
127  void setUnwinding(bool b) { unwinding_ = b; }
128
129  AsanThreadLocalMallocStorage &malloc_storage() { return malloc_storage_; }
130  AsanStats &stats() { return stats_; }
131
132 private:
133  // NOTE: There is no AsanThread constructor. It is allocated
134  // via mmap() and *must* be valid in zero-initialized state.
135
136  void SetThreadStackAndTls(const InitOptions *options);
137
138  void ClearShadowForThreadStackAndTLS();
139  FakeStack *AsyncSignalSafeLazyInitFakeStack();
140
141  struct StackBounds {
142    uptr bottom;
143    uptr top;
144  };
145  StackBounds GetStackBounds() const;
146
147  AsanThreadContext *context_;
148  thread_callback_t start_routine_;
149  void *arg_;
150
151  uptr stack_top_;
152  uptr stack_bottom_;
153  // these variables are used when the thread is about to switch stack
154  uptr next_stack_top_;
155  uptr next_stack_bottom_;
156  // true if switching is in progress
157  atomic_uint8_t stack_switching_;
158
159  uptr tls_begin_;
160  uptr tls_end_;
161  DTLS *dtls_;
162
163  FakeStack *fake_stack_;
164  AsanThreadLocalMallocStorage malloc_storage_;
165  AsanStats stats_;
166  bool unwinding_;
167};
168
169// ScopedUnwinding is a scope for stacktracing member of a context
170class ScopedUnwinding {
171 public:
172  explicit ScopedUnwinding(AsanThread *t) : thread(t) {
173    t->setUnwinding(true);
174  }
175  ~ScopedUnwinding() { thread->setUnwinding(false); }
176
177 private:
178  AsanThread *thread;
179};
180
181// Returns a single instance of registry.
182ThreadRegistry &asanThreadRegistry();
183
184// Must be called under ThreadRegistryLock.
185AsanThreadContext *GetThreadContextByTidLocked(u32 tid);
186
187// Get the current thread. May return 0.
188AsanThread *GetCurrentThread();
189void SetCurrentThread(AsanThread *t);
190u32 GetCurrentTidOrInvalid();
191AsanThread *FindThreadByStackAddress(uptr addr);
192
193// Used to handle fork().
194void EnsureMainThreadIDIsCorrect();
195} // namespace __asan
196
197#endif // ASAN_THREAD_H
198