asan_thread.cc revision c98fc1f8e52812cfaf5b19a29db5ed56acb0a682
1e5f5895bda30f374b0b51412fd4d837fa59aed66Alexey Samsonov//===-- asan_thread.cc ----------------------------------------------------===//
21e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//
31e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//                     The LLVM Compiler Infrastructure
41e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//
51e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// This file is distributed under the University of Illinois Open Source
61e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// License. See LICENSE.TXT for details.
71e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//
81e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===----------------------------------------------------------------------===//
91e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//
101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// This file is a part of AddressSanitizer, an address sanity checker.
111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//
121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Thread-related code.
131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===----------------------------------------------------------------------===//
141e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_allocator.h"
151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_interceptors.h"
167e8434940a1fe7dce531d4c458ccd714da48f609Alexey Samsonov#include "asan_poisoning.h"
1755cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov#include "asan_stack.h"
181e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_thread.h"
191e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_mapping.h"
20e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include "sanitizer_common/sanitizer_common.h"
21def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov#include "sanitizer_common/sanitizer_placement_new.h"
22f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveev#include "lsan/lsan_common.h"
231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace __asan {
251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
26def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov// AsanThreadContext implementation.
271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
28def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonovvoid AsanThreadContext::OnCreated(void *arg) {
29def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  CreateThreadContextArgs *args = static_cast<CreateThreadContextArgs*>(arg);
30def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  if (args->stack) {
31def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov    internal_memcpy(&stack, args->stack, sizeof(stack));
32def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  }
33def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  thread = args->thread;
34def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  thread->set_context(this);
35def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov}
36def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov
37def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonovvoid AsanThreadContext::OnFinished() {
38def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  // Drop the link to the AsanThread object.
39def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  thread = 0;
40def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov}
41def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov
4240527a579131210fcfa2373620a0c2200800e7c4Kostya Serebryany// MIPS requires aligned address
437c9ffde46a475d6dd739e977b547c27ac5968976Timur Iskhodzhanovstatic ALIGNED(16) char thread_registry_placeholder[sizeof(ThreadRegistry)];
44def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonovstatic ThreadRegistry *asan_thread_registry;
45def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov
46def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonovstatic ThreadContextBase *GetAsanThreadContext(u32 tid) {
47def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  void *mem = MmapOrDie(sizeof(AsanThreadContext), "AsanThreadContext");
48def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  return new(mem) AsanThreadContext(tid);
49def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov}
50def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov
51def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey SamsonovThreadRegistry &asanThreadRegistry() {
52def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  static bool initialized;
53def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  // Don't worry about thread_safety - this should be called when there is
54def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  // a single thread.
55def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  if (!initialized) {
56def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov    // Never reuse ASan threads: we store pointer to AsanThreadContext
57def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov    // in TSD and can't reliably tell when no more TSD destructors will
58def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov    // be called. It would be wrong to reuse AsanThreadContext for another
59def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov    // thread before all TSD destructors will be called for it.
60def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov    asan_thread_registry = new(thread_registry_placeholder) ThreadRegistry(
61def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov        GetAsanThreadContext, kMaxNumberOfThreads, kMaxNumberOfThreads);
62def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov    initialized = true;
63def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  }
64def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  return *asan_thread_registry;
65def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov}
66def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov
67def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey SamsonovAsanThreadContext *GetThreadContextByTidLocked(u32 tid) {
68def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  return static_cast<AsanThreadContext *>(
69def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov      asanThreadRegistry().GetThreadLocked(tid));
70def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov}
71def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov
72def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov// AsanThread implementation.
73def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov
74def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey SamsonovAsanThread *AsanThread::Create(thread_callback_t start_routine,
75def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov                               void *arg) {
76f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany  uptr PageSize = GetPageSizeCached();
77f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany  uptr size = RoundUpTo(sizeof(AsanThread), PageSize);
78a25b3463477d2a825df4f656001fc07c594b35acAlexey Samsonov  AsanThread *thread = (AsanThread*)MmapOrDie(size, __FUNCTION__);
7955cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov  thread->start_routine_ = start_routine;
8055cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov  thread->arg_ = arg;
81def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  thread->context_ = 0;
8255cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov
8355cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov  return thread;
841e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
851e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
86def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonovvoid AsanThread::TSDDtor(void *tsd) {
87def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  AsanThreadContext *context = (AsanThreadContext*)tsd;
88def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  if (flags()->verbosity >= 1)
89def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov    Report("T%d TSDDtor\n", context->tid);
90def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  if (context->thread)
91def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov    context->thread->Destroy();
92f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany}
93f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany
94a6b52264e1231bfc4ee9a2d9a4f32678c97295f0Kostya Serebryanyvoid AsanThread::Destroy() {
95cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->verbosity >= 1) {
96f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany    Report("T%d exited\n", tid());
97f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany  }
98f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany
99def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  asanThreadRegistry().FinishThread(tid());
100717ece58e18190c4aef50bd16254db1d74036395Alexey Samsonov  FlushToDeadThreadStats(&stats_);
1011e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // We also clear the shadow on thread destruction because
1021e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // some code may still be executing in later TSD destructors
1031e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // and we don't want it to have any poisoned stack.
10412d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev  ClearShadowForThreadStackAndTLS();
1057a0bba457ee05ced3adf37a0c0790d0ed23a5446Kostya Serebryany  DeleteFakeStack();
106f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany  uptr size = RoundUpTo(sizeof(AsanThread), GetPageSizeCached());
107a25b3463477d2a825df4f656001fc07c594b35acAlexey Samsonov  UnmapOrDie(this, size);
1081e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
1091e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
110c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany// We want to create the FakeStack lazyly on the first use, but not eralier
111c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany// than the stack size is known and the procedure has to be async-signal safe.
112c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya SerebryanyFakeStack *AsanThread::AsyncSignalSafeLazyInitFakeStack() {
113c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany  uptr stack_size = this->stack_size();
114c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany  if (stack_size == 0)  // stack_size is not yet available, don't use FakeStack.
115c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany    return 0;
116c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany  uptr old_val = 0;
117c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany  // fake_stack_ has 3 states:
118c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany  // 0   -- not initialized
119c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany  // 1   -- being initialized
120c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany  // ptr -- initialized
121c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany  // This CAS checks if the state was 0 and if so changes it to state 1,
122c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany  // if that was successfull, it initilizes the pointer.
123c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany  if (atomic_compare_exchange_strong(
124c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany      reinterpret_cast<atomic_uintptr_t *>(&fake_stack_), &old_val, 1UL,
125c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany      memory_order_relaxed))
126c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany    return fake_stack_ =
127c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany               FakeStack::Create(Log2(RoundUpToPowerOfTwo(stack_size)));
128c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany  return 0;
129c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany}
130c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany
13169eca73ac96688c8bfe1f23ee006af29c7858c40Kostya Serebryanyvoid AsanThread::Init() {
13212d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev  SetThreadStackAndTls();
13355cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov  CHECK(AddrIsInMem(stack_bottom_));
134541cfb10f5daa17e48eb42365a74233cd551c545Kostya Serebryany  CHECK(AddrIsInMem(stack_top_ - 1));
13512d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev  ClearShadowForThreadStackAndTLS();
136cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->verbosity >= 1) {
1371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    int local = 0;
138739eb7984139d457216623347ae3b7a706c0aadfEvgeniy Stepanov    Report("T%d: stack [%p,%p) size 0x%zx; local=%p\n",
1395bcca4e33ececdddd8e9e07619c129e870492251Alexey Samsonov           tid(), (void*)stack_bottom_, (void*)stack_top_,
140a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany           stack_top_ - stack_bottom_, &local);
1411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
1427a0bba457ee05ced3adf37a0c0790d0ed23a5446Kostya Serebryany  fake_stack_ = 0;  // Will be initialized lazily if needed.
14375b19ebf25af204cf209d108997272822241d6daAlexander Potapenko  AsanPlatformThreadInit();
14469eca73ac96688c8bfe1f23ee006af29c7858c40Kostya Serebryany}
14569eca73ac96688c8bfe1f23ee006af29c7858c40Kostya Serebryany
146def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonovthread_return_t AsanThread::ThreadStart(uptr os_id) {
14769eca73ac96688c8bfe1f23ee006af29c7858c40Kostya Serebryany  Init();
148def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  asanThreadRegistry().StartThread(tid(), os_id, 0);
149cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->use_sigaltstack) SetAlternateSignalStack();
1501e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
1511e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (!start_routine_) {
1523f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany    // start_routine_ == 0 if we're on the main thread or on one of the
1531e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    // OS X libdispatch worker threads. But nobody is supposed to call
1541e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    // ThreadStart() for the worker threads.
155a27bdf70ca24202dce21cf7c1a387aeaa400d889Kostya Serebryany    CHECK_EQ(tid(), 0);
1561e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    return 0;
1571e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
1581e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
159600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  thread_return_t res = start_routine_(arg_);
1601e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  malloc_storage().CommitBack();
161cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->use_sigaltstack) UnsetAlternateSignalStack();
1621e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
163af3441580555ceed092170232cd5f2cc180f19f4Kostya Serebryany  this->Destroy();
164af3441580555ceed092170232cd5f2cc180f19f4Kostya Serebryany
1651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return res;
1661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
1671e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
16812d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveevvoid AsanThread::SetThreadStackAndTls() {
16912d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev  uptr stack_size = 0, tls_size = 0;
17012d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev  GetThreadStackAndTls(tid() == 0, &stack_bottom_, &stack_size, &tls_begin_,
17112d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev                       &tls_size);
17212d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev  stack_top_ = stack_bottom_ + stack_size;
17312d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev  tls_end_ = tls_begin_ + tls_size;
17412d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev
175e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  int local;
176e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  CHECK(AddrIsInStack((uptr)&local));
177e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov}
178e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov
17912d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveevvoid AsanThread::ClearShadowForThreadStackAndTLS() {
18055cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov  PoisonShadow(stack_bottom_, stack_top_ - stack_bottom_, 0);
18112d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev  if (tls_begin_ != tls_end_)
18212d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev    PoisonShadow(tls_begin_, tls_end_ - tls_begin_, 0);
18355cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov}
18455cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov
18550f3daa00d3da0a80c8798a3e977705e96ec106fKostya Serebryanyconst char *AsanThread::GetFrameNameByAddr(uptr addr, uptr *offset,
18650f3daa00d3da0a80c8798a3e977705e96ec106fKostya Serebryany                                           uptr *frame_pc) {
1873f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  uptr bottom = 0;
1881e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (AddrIsInStack(addr)) {
1891e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    bottom = stack_bottom();
1907a0bba457ee05ced3adf37a0c0790d0ed23a5446Kostya Serebryany  } else if (fake_stack()) {
1917a0bba457ee05ced3adf37a0c0790d0ed23a5446Kostya Serebryany    bottom = fake_stack()->AddrIsInFakeStack(addr);
1921e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    CHECK(bottom);
193e406c8c47570659287e619e23479f9fb6640299eAlexander Potapenko    *offset = addr - bottom;
19450f3daa00d3da0a80c8798a3e977705e96ec106fKostya Serebryany    *frame_pc = ((uptr*)bottom)[2];
195e406c8c47570659287e619e23479f9fb6640299eAlexander Potapenko    return  (const char *)((uptr*)bottom)[1];
1961e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
1975af39e50366f1aacbebc284f572f08ad1ad07357Kostya Serebryany  uptr aligned_addr = addr & ~(SANITIZER_WORDSIZE/8 - 1);  // align addr.
198ee3925515e4c7966f3ef489f687aa7e5692806a9Kostya Serebryany  u8 *shadow_ptr = (u8*)MemToShadow(aligned_addr);
199ee3925515e4c7966f3ef489f687aa7e5692806a9Kostya Serebryany  u8 *shadow_bottom = (u8*)MemToShadow(bottom);
2003972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov
2013972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov  while (shadow_ptr >= shadow_bottom &&
202e406c8c47570659287e619e23479f9fb6640299eAlexander Potapenko         *shadow_ptr != kAsanStackLeftRedzoneMagic) {
2033972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov    shadow_ptr--;
2043972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov  }
2053972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov
2063972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov  while (shadow_ptr >= shadow_bottom &&
207e406c8c47570659287e619e23479f9fb6640299eAlexander Potapenko         *shadow_ptr == kAsanStackLeftRedzoneMagic) {
2083972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov    shadow_ptr--;
2091e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
2103972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov
2113972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov  if (shadow_ptr < shadow_bottom) {
212e406c8c47570659287e619e23479f9fb6640299eAlexander Potapenko    *offset = 0;
213e406c8c47570659287e619e23479f9fb6640299eAlexander Potapenko    return "UNKNOWN";
2143972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov  }
2153972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov
2163f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  uptr* ptr = (uptr*)SHADOW_TO_MEM((uptr)(shadow_ptr + 1));
217e406c8c47570659287e619e23479f9fb6640299eAlexander Potapenko  CHECK(ptr[0] == kCurrentStackFrameMagic);
2183f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  *offset = addr - (uptr)ptr;
21950f3daa00d3da0a80c8798a3e977705e96ec106fKostya Serebryany  *frame_pc = ptr[2];
2203972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov  return (const char*)ptr[1];
2211e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
2221e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
223def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonovstatic bool ThreadStackContainsAddress(ThreadContextBase *tctx_base,
224def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov                                       void *addr) {
225def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  AsanThreadContext *tctx = static_cast<AsanThreadContext*>(tctx_base);
226def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  AsanThread *t = tctx->thread;
2277a0bba457ee05ced3adf37a0c0790d0ed23a5446Kostya Serebryany  if (!t) return false;
2287a0bba457ee05ced3adf37a0c0790d0ed23a5446Kostya Serebryany  if (t->AddrIsInStack((uptr)addr)) return true;
2297a0bba457ee05ced3adf37a0c0790d0ed23a5446Kostya Serebryany  if (t->fake_stack() && t->fake_stack()->AddrIsInFakeStack((uptr)addr))
2307a0bba457ee05ced3adf37a0c0790d0ed23a5446Kostya Serebryany    return true;
2317a0bba457ee05ced3adf37a0c0790d0ed23a5446Kostya Serebryany  return false;
232def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov}
233def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov
23489c1384464848c1ad041becf8b97936fa10de21bAlexey SamsonovAsanThread *GetCurrentThread() {
235c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev  AsanThreadContext *context =
236c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev      reinterpret_cast<AsanThreadContext *>(AsanTSDGet());
237def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  if (!context) {
238def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov    if (SANITIZER_ANDROID) {
239def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov      // On Android, libc constructor is called _after_ asan_init, and cleans up
240def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov      // TSD. Try to figure out if this is still the main thread by the stack
241def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov      // address. We are not entirely sure that we have correct main thread
242195369bb7f59896487c4542716ca9c5d53975e78Dmitry Vyukov      // limits, so only do this magic on Android, and only if the found thread
243195369bb7f59896487c4542716ca9c5d53975e78Dmitry Vyukov      // is the main thread.
244def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov      AsanThreadContext *tctx = GetThreadContextByTidLocked(0);
245def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov      if (ThreadStackContainsAddress(tctx, &context)) {
246def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov        SetCurrentThread(tctx->thread);
247def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov        return tctx->thread;
248def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov      }
24989c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov    }
25089c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov    return 0;
25189c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov  }
252def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  return context->thread;
25389c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov}
25489c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov
25589c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonovvoid SetCurrentThread(AsanThread *t) {
256def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  CHECK(t->context());
25789c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov  if (flags()->verbosity >= 2) {
25889c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov    Report("SetCurrentThread: %p for thread %p\n",
259def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov           t->context(), (void*)GetThreadSelf());
26089c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov  }
26189c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov  // Make sure we do not reset the current AsanThread.
262def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  CHECK_EQ(0, AsanTSDGet());
263def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  AsanTSDSet(t->context());
264def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  CHECK_EQ(t->context(), AsanTSDGet());
26589c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov}
26689c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov
26789c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonovu32 GetCurrentTidOrInvalid() {
26889c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov  AsanThread *t = GetCurrentThread();
26989c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov  return t ? t->tid() : kInvalidTid;
27089c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov}
27189c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov
272def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey SamsonovAsanThread *FindThreadByStackAddress(uptr addr) {
273def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  asanThreadRegistry().CheckLocked();
274def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  AsanThreadContext *tctx = static_cast<AsanThreadContext *>(
275def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov      asanThreadRegistry().FindThreadContextLocked(ThreadStackContainsAddress,
276def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov                                                   (void *)addr));
277def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  return tctx ? tctx->thread : 0;
278def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov}
279c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev
280c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveevvoid EnsureMainThreadIDIsCorrect() {
281c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev  AsanThreadContext *context =
282c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev      reinterpret_cast<AsanThreadContext *>(AsanTSDGet());
283c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev  if (context && (context->tid == 0))
284c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev    context->os_id = GetTid();
285c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev}
2861e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}  // namespace __asan
287f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveev
288f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveev// --- Implementation of LSan-specific functions --- {{{1
289f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveevnamespace __lsan {
290f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveevbool GetThreadRangesLocked(uptr os_id, uptr *stack_begin, uptr *stack_end,
291f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveev                           uptr *tls_begin, uptr *tls_end,
292f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveev                           uptr *cache_begin, uptr *cache_end) {
29312d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev  __asan::AsanThreadContext *context = static_cast<__asan::AsanThreadContext *>(
29412d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev      __asan::asanThreadRegistry().FindThreadContextByOsIDLocked(os_id));
29512d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev  if (!context) return false;
29612d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev  __asan::AsanThread *t = context->thread;
29712d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev  if (!t) return false;
29812d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev  *stack_begin = t->stack_bottom();
29912d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev  *stack_end = t->stack_top();
30012d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev  *tls_begin = t->tls_begin();
30112d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev  *tls_end = t->tls_end();
30212d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev  // ASan doesn't keep allocator caches in TLS, so these are unused.
30312d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev  *cache_begin = 0;
30412d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev  *cache_end = 0;
30512d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev  return true;
306f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveev}
307f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveev
308f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveevvoid LockThreadRegistry() {
309f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveev  __asan::asanThreadRegistry().Lock();
310f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveev}
311f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveev
312f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveevvoid UnlockThreadRegistry() {
313f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveev  __asan::asanThreadRegistry().Unlock();
314f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveev}
315c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev
316c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveevvoid EnsureMainThreadIDIsCorrect() {
317c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev  __asan::EnsureMainThreadIDIsCorrect();
318c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev}
319f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveev}  // namespace __lsan
320