1//===-- asan_thread.cc ----------------------------------------------------===//
2//
3//                     The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file is a part of AddressSanitizer, an address sanity checker.
11//
12// Thread-related code.
13//===----------------------------------------------------------------------===//
14#include "asan_allocator.h"
15#include "asan_interceptors.h"
16#include "asan_poisoning.h"
17#include "asan_stack.h"
18#include "asan_thread.h"
19#include "asan_mapping.h"
20#include "sanitizer_common/sanitizer_common.h"
21#include "sanitizer_common/sanitizer_placement_new.h"
22#include "sanitizer_common/sanitizer_stackdepot.h"
23#include "sanitizer_common/sanitizer_tls_get_addr.h"
24#include "lsan/lsan_common.h"
25
26namespace __asan {
27
28// AsanThreadContext implementation.
29
30void AsanThreadContext::OnCreated(void *arg) {
31  CreateThreadContextArgs *args = static_cast<CreateThreadContextArgs*>(arg);
32  if (args->stack)
33    stack_id = StackDepotPut(args->stack->trace, args->stack->size);
34  thread = args->thread;
35  thread->set_context(this);
36}
37
38void AsanThreadContext::OnFinished() {
39  // Drop the link to the AsanThread object.
40  thread = 0;
41}
42
43// MIPS requires aligned address
44static ALIGNED(16) char thread_registry_placeholder[sizeof(ThreadRegistry)];
45static ThreadRegistry *asan_thread_registry;
46
47static BlockingMutex mu_for_thread_context(LINKER_INITIALIZED);
48static LowLevelAllocator allocator_for_thread_context;
49
50static ThreadContextBase *GetAsanThreadContext(u32 tid) {
51  BlockingMutexLock lock(&mu_for_thread_context);
52  return new(allocator_for_thread_context) AsanThreadContext(tid);
53}
54
55ThreadRegistry &asanThreadRegistry() {
56  static bool initialized;
57  // Don't worry about thread_safety - this should be called when there is
58  // a single thread.
59  if (!initialized) {
60    // Never reuse ASan threads: we store pointer to AsanThreadContext
61    // in TSD and can't reliably tell when no more TSD destructors will
62    // be called. It would be wrong to reuse AsanThreadContext for another
63    // thread before all TSD destructors will be called for it.
64    asan_thread_registry = new(thread_registry_placeholder) ThreadRegistry(
65        GetAsanThreadContext, kMaxNumberOfThreads, kMaxNumberOfThreads);
66    initialized = true;
67  }
68  return *asan_thread_registry;
69}
70
71AsanThreadContext *GetThreadContextByTidLocked(u32 tid) {
72  return static_cast<AsanThreadContext *>(
73      asanThreadRegistry().GetThreadLocked(tid));
74}
75
76// AsanThread implementation.
77
78AsanThread *AsanThread::Create(thread_callback_t start_routine,
79                               void *arg) {
80  uptr PageSize = GetPageSizeCached();
81  uptr size = RoundUpTo(sizeof(AsanThread), PageSize);
82  AsanThread *thread = (AsanThread*)MmapOrDie(size, __func__);
83  thread->start_routine_ = start_routine;
84  thread->arg_ = arg;
85
86  return thread;
87}
88
89void AsanThread::TSDDtor(void *tsd) {
90  AsanThreadContext *context = (AsanThreadContext*)tsd;
91  VReport(1, "T%d TSDDtor\n", context->tid);
92  if (context->thread)
93    context->thread->Destroy();
94}
95
96void AsanThread::Destroy() {
97  int tid = this->tid();
98  VReport(1, "T%d exited\n", tid);
99
100  malloc_storage().CommitBack();
101  if (common_flags()->use_sigaltstack) UnsetAlternateSignalStack();
102  asanThreadRegistry().FinishThread(tid);
103  FlushToDeadThreadStats(&stats_);
104  // We also clear the shadow on thread destruction because
105  // some code may still be executing in later TSD destructors
106  // and we don't want it to have any poisoned stack.
107  ClearShadowForThreadStackAndTLS();
108  DeleteFakeStack(tid);
109  uptr size = RoundUpTo(sizeof(AsanThread), GetPageSizeCached());
110  UnmapOrDie(this, size);
111  DTLS_Destroy();
112}
113
114// We want to create the FakeStack lazyly on the first use, but not eralier
115// than the stack size is known and the procedure has to be async-signal safe.
116FakeStack *AsanThread::AsyncSignalSafeLazyInitFakeStack() {
117  uptr stack_size = this->stack_size();
118  if (stack_size == 0)  // stack_size is not yet available, don't use FakeStack.
119    return 0;
120  uptr old_val = 0;
121  // fake_stack_ has 3 states:
122  // 0   -- not initialized
123  // 1   -- being initialized
124  // ptr -- initialized
125  // This CAS checks if the state was 0 and if so changes it to state 1,
126  // if that was successful, it initializes the pointer.
127  if (atomic_compare_exchange_strong(
128      reinterpret_cast<atomic_uintptr_t *>(&fake_stack_), &old_val, 1UL,
129      memory_order_relaxed)) {
130    uptr stack_size_log = Log2(RoundUpToPowerOfTwo(stack_size));
131    CHECK_LE(flags()->min_uar_stack_size_log, flags()->max_uar_stack_size_log);
132    stack_size_log =
133        Min(stack_size_log, static_cast<uptr>(flags()->max_uar_stack_size_log));
134    stack_size_log =
135        Max(stack_size_log, static_cast<uptr>(flags()->min_uar_stack_size_log));
136    fake_stack_ = FakeStack::Create(stack_size_log);
137    SetTLSFakeStack(fake_stack_);
138    return fake_stack_;
139  }
140  return 0;
141}
142
143void AsanThread::Init() {
144  fake_stack_ = 0;  // Will be initialized lazily if needed.
145  CHECK_EQ(this->stack_size(), 0U);
146  SetThreadStackAndTls();
147  CHECK_GT(this->stack_size(), 0U);
148  CHECK(AddrIsInMem(stack_bottom_));
149  CHECK(AddrIsInMem(stack_top_ - 1));
150  ClearShadowForThreadStackAndTLS();
151  int local = 0;
152  VReport(1, "T%d: stack [%p,%p) size 0x%zx; local=%p\n", tid(),
153          (void *)stack_bottom_, (void *)stack_top_, stack_top_ - stack_bottom_,
154          &local);
155  AsanPlatformThreadInit();
156}
157
158thread_return_t AsanThread::ThreadStart(uptr os_id) {
159  Init();
160  asanThreadRegistry().StartThread(tid(), os_id, 0);
161  if (common_flags()->use_sigaltstack) SetAlternateSignalStack();
162
163  if (!start_routine_) {
164    // start_routine_ == 0 if we're on the main thread or on one of the
165    // OS X libdispatch worker threads. But nobody is supposed to call
166    // ThreadStart() for the worker threads.
167    CHECK_EQ(tid(), 0);
168    return 0;
169  }
170
171  thread_return_t res = start_routine_(arg_);
172
173  // On POSIX systems we defer this to the TSD destructor. LSan will consider
174  // the thread's memory as non-live from the moment we call Destroy(), even
175  // though that memory might contain pointers to heap objects which will be
176  // cleaned up by a user-defined TSD destructor. Thus, calling Destroy() before
177  // the TSD destructors have run might cause false positives in LSan.
178  if (!SANITIZER_POSIX)
179    this->Destroy();
180
181  return res;
182}
183
184void AsanThread::SetThreadStackAndTls() {
185  uptr tls_size = 0;
186  GetThreadStackAndTls(tid() == 0, &stack_bottom_, &stack_size_, &tls_begin_,
187                       &tls_size);
188  stack_top_ = stack_bottom_ + stack_size_;
189  tls_end_ = tls_begin_ + tls_size;
190
191  int local;
192  CHECK(AddrIsInStack((uptr)&local));
193}
194
195void AsanThread::ClearShadowForThreadStackAndTLS() {
196  PoisonShadow(stack_bottom_, stack_top_ - stack_bottom_, 0);
197  if (tls_begin_ != tls_end_)
198    PoisonShadow(tls_begin_, tls_end_ - tls_begin_, 0);
199}
200
201const char *AsanThread::GetFrameNameByAddr(uptr addr, uptr *offset,
202                                           uptr *frame_pc) {
203  uptr bottom = 0;
204  if (AddrIsInStack(addr)) {
205    bottom = stack_bottom();
206  } else if (has_fake_stack()) {
207    bottom = fake_stack()->AddrIsInFakeStack(addr);
208    CHECK(bottom);
209    *offset = addr - bottom;
210    *frame_pc = ((uptr*)bottom)[2];
211    return  (const char *)((uptr*)bottom)[1];
212  }
213  uptr aligned_addr = addr & ~(SANITIZER_WORDSIZE/8 - 1);  // align addr.
214  u8 *shadow_ptr = (u8*)MemToShadow(aligned_addr);
215  u8 *shadow_bottom = (u8*)MemToShadow(bottom);
216
217  while (shadow_ptr >= shadow_bottom &&
218         *shadow_ptr != kAsanStackLeftRedzoneMagic) {
219    shadow_ptr--;
220  }
221
222  while (shadow_ptr >= shadow_bottom &&
223         *shadow_ptr == kAsanStackLeftRedzoneMagic) {
224    shadow_ptr--;
225  }
226
227  if (shadow_ptr < shadow_bottom) {
228    *offset = 0;
229    return "UNKNOWN";
230  }
231
232  uptr* ptr = (uptr*)SHADOW_TO_MEM((uptr)(shadow_ptr + 1));
233  CHECK(ptr[0] == kCurrentStackFrameMagic);
234  *offset = addr - (uptr)ptr;
235  *frame_pc = ptr[2];
236  return (const char*)ptr[1];
237}
238
239static bool ThreadStackContainsAddress(ThreadContextBase *tctx_base,
240                                       void *addr) {
241  AsanThreadContext *tctx = static_cast<AsanThreadContext*>(tctx_base);
242  AsanThread *t = tctx->thread;
243  if (!t) return false;
244  if (t->AddrIsInStack((uptr)addr)) return true;
245  if (t->has_fake_stack() && t->fake_stack()->AddrIsInFakeStack((uptr)addr))
246    return true;
247  return false;
248}
249
250AsanThread *GetCurrentThread() {
251  AsanThreadContext *context =
252      reinterpret_cast<AsanThreadContext *>(AsanTSDGet());
253  if (!context) {
254    if (SANITIZER_ANDROID) {
255      // On Android, libc constructor is called _after_ asan_init, and cleans up
256      // TSD. Try to figure out if this is still the main thread by the stack
257      // address. We are not entirely sure that we have correct main thread
258      // limits, so only do this magic on Android, and only if the found thread
259      // is the main thread.
260      AsanThreadContext *tctx = GetThreadContextByTidLocked(0);
261      if (ThreadStackContainsAddress(tctx, &context)) {
262        SetCurrentThread(tctx->thread);
263        return tctx->thread;
264      }
265    }
266    return 0;
267  }
268  return context->thread;
269}
270
271void SetCurrentThread(AsanThread *t) {
272  CHECK(t->context());
273  VReport(2, "SetCurrentThread: %p for thread %p\n", t->context(),
274          (void *)GetThreadSelf());
275  // Make sure we do not reset the current AsanThread.
276  CHECK_EQ(0, AsanTSDGet());
277  AsanTSDSet(t->context());
278  CHECK_EQ(t->context(), AsanTSDGet());
279}
280
281u32 GetCurrentTidOrInvalid() {
282  AsanThread *t = GetCurrentThread();
283  return t ? t->tid() : kInvalidTid;
284}
285
286AsanThread *FindThreadByStackAddress(uptr addr) {
287  asanThreadRegistry().CheckLocked();
288  AsanThreadContext *tctx = static_cast<AsanThreadContext *>(
289      asanThreadRegistry().FindThreadContextLocked(ThreadStackContainsAddress,
290                                                   (void *)addr));
291  return tctx ? tctx->thread : 0;
292}
293
294void EnsureMainThreadIDIsCorrect() {
295  AsanThreadContext *context =
296      reinterpret_cast<AsanThreadContext *>(AsanTSDGet());
297  if (context && (context->tid == 0))
298    context->os_id = GetTid();
299}
300
301__asan::AsanThread *GetAsanThreadByOsIDLocked(uptr os_id) {
302  __asan::AsanThreadContext *context = static_cast<__asan::AsanThreadContext *>(
303      __asan::asanThreadRegistry().FindThreadContextByOsIDLocked(os_id));
304  if (!context) return 0;
305  return context->thread;
306}
307}  // namespace __asan
308
309// --- Implementation of LSan-specific functions --- {{{1
310namespace __lsan {
311bool GetThreadRangesLocked(uptr os_id, uptr *stack_begin, uptr *stack_end,
312                           uptr *tls_begin, uptr *tls_end,
313                           uptr *cache_begin, uptr *cache_end) {
314  __asan::AsanThread *t = __asan::GetAsanThreadByOsIDLocked(os_id);
315  if (!t) return false;
316  *stack_begin = t->stack_bottom();
317  *stack_end = t->stack_top();
318  *tls_begin = t->tls_begin();
319  *tls_end = t->tls_end();
320  // ASan doesn't keep allocator caches in TLS, so these are unused.
321  *cache_begin = 0;
322  *cache_end = 0;
323  return true;
324}
325
326void ForEachExtraStackRange(uptr os_id, RangeIteratorCallback callback,
327                            void *arg) {
328  __asan::AsanThread *t = __asan::GetAsanThreadByOsIDLocked(os_id);
329  if (t && t->has_fake_stack())
330    t->fake_stack()->ForEachFakeFrame(callback, arg);
331}
332
333void LockThreadRegistry() {
334  __asan::asanThreadRegistry().Lock();
335}
336
337void UnlockThreadRegistry() {
338  __asan::asanThreadRegistry().Unlock();
339}
340
341void EnsureMainThreadIDIsCorrect() {
342  __asan::EnsureMainThreadIDIsCorrect();
343}
344}  // namespace __lsan
345