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"
226d95869fa900da9ddd68e15e2aa065854cfa176bKostya Serebryany#include "sanitizer_common/sanitizer_stackdepot.h"
232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include "sanitizer_common/sanitizer_tls_get_addr.h"
24f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveev#include "lsan/lsan_common.h"
251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
261e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace __asan {
271e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
28def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov// AsanThreadContext implementation.
291e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
30def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonovvoid AsanThreadContext::OnCreated(void *arg) {
31def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  CreateThreadContextArgs *args = static_cast<CreateThreadContextArgs*>(arg);
326d95869fa900da9ddd68e15e2aa065854cfa176bKostya Serebryany  if (args->stack)
336d95869fa900da9ddd68e15e2aa065854cfa176bKostya Serebryany    stack_id = StackDepotPut(args->stack->trace, args->stack->size);
34def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  thread = args->thread;
35def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  thread->set_context(this);
36def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov}
37def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov
38def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonovvoid AsanThreadContext::OnFinished() {
39def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  // Drop the link to the AsanThread object.
40def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  thread = 0;
41def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov}
42def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov
4340527a579131210fcfa2373620a0c2200800e7c4Kostya Serebryany// MIPS requires aligned address
447c9ffde46a475d6dd739e977b547c27ac5968976Timur Iskhodzhanovstatic ALIGNED(16) char thread_registry_placeholder[sizeof(ThreadRegistry)];
45def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonovstatic ThreadRegistry *asan_thread_registry;
46def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov
471fe68b87dcd9be36b5b4d35e74cc5b0666500ec4Kostya Serebryanystatic BlockingMutex mu_for_thread_context(LINKER_INITIALIZED);
481fe68b87dcd9be36b5b4d35e74cc5b0666500ec4Kostya Serebryanystatic LowLevelAllocator allocator_for_thread_context;
491fe68b87dcd9be36b5b4d35e74cc5b0666500ec4Kostya Serebryany
50def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonovstatic ThreadContextBase *GetAsanThreadContext(u32 tid) {
511fe68b87dcd9be36b5b4d35e74cc5b0666500ec4Kostya Serebryany  BlockingMutexLock lock(&mu_for_thread_context);
5253177247698bfba075f2d5b255a447fc3ced6976Peter Collingbourne  return new(allocator_for_thread_context) AsanThreadContext(tid);
53def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov}
54def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov
55def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey SamsonovThreadRegistry &asanThreadRegistry() {
56def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  static bool initialized;
57def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  // Don't worry about thread_safety - this should be called when there is
58def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  // a single thread.
59def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  if (!initialized) {
60def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov    // Never reuse ASan threads: we store pointer to AsanThreadContext
61def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov    // in TSD and can't reliably tell when no more TSD destructors will
62def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov    // be called. It would be wrong to reuse AsanThreadContext for another
63def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov    // thread before all TSD destructors will be called for it.
64def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov    asan_thread_registry = new(thread_registry_placeholder) ThreadRegistry(
65def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov        GetAsanThreadContext, kMaxNumberOfThreads, kMaxNumberOfThreads);
66def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov    initialized = true;
67def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  }
68def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  return *asan_thread_registry;
69def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov}
70def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov
71def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey SamsonovAsanThreadContext *GetThreadContextByTidLocked(u32 tid) {
72def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  return static_cast<AsanThreadContext *>(
73def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov      asanThreadRegistry().GetThreadLocked(tid));
74def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov}
75def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov
76def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov// AsanThread implementation.
77def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov
78def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey SamsonovAsanThread *AsanThread::Create(thread_callback_t start_routine,
79def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov                               void *arg) {
80f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany  uptr PageSize = GetPageSizeCached();
81f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany  uptr size = RoundUpTo(sizeof(AsanThread), PageSize);
822d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  AsanThread *thread = (AsanThread*)MmapOrDie(size, __func__);
8355cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov  thread->start_routine_ = start_routine;
8455cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov  thread->arg_ = arg;
8555cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov
8655cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov  return thread;
871e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
881e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
89def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonovvoid AsanThread::TSDDtor(void *tsd) {
90def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  AsanThreadContext *context = (AsanThreadContext*)tsd;
912d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  VReport(1, "T%d TSDDtor\n", context->tid);
92def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  if (context->thread)
93def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov    context->thread->Destroy();
94f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany}
95f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany
96a6b52264e1231bfc4ee9a2d9a4f32678c97295f0Kostya Serebryanyvoid AsanThread::Destroy() {
972d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  int tid = this->tid();
982d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  VReport(1, "T%d exited\n", tid);
99f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany
100ae914e2fc00c60d0f8f8b9b06bcc8b0b2d470181Kostya Serebryany  malloc_storage().CommitBack();
1012d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (common_flags()->use_sigaltstack) UnsetAlternateSignalStack();
1022d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  asanThreadRegistry().FinishThread(tid);
103717ece58e18190c4aef50bd16254db1d74036395Alexey Samsonov  FlushToDeadThreadStats(&stats_);
1041e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // We also clear the shadow on thread destruction because
1051e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // some code may still be executing in later TSD destructors
1061e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  // and we don't want it to have any poisoned stack.
10712d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev  ClearShadowForThreadStackAndTLS();
1082d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  DeleteFakeStack(tid);
109f67ec2b6e8d2ae328c27de0b026eea2d6667836eKostya Serebryany  uptr size = RoundUpTo(sizeof(AsanThread), GetPageSizeCached());
110a25b3463477d2a825df4f656001fc07c594b35acAlexey Samsonov  UnmapOrDie(this, size);
1112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  DTLS_Destroy();
1121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
1131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
114c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany// We want to create the FakeStack lazyly on the first use, but not eralier
115c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany// than the stack size is known and the procedure has to be async-signal safe.
116c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya SerebryanyFakeStack *AsanThread::AsyncSignalSafeLazyInitFakeStack() {
117c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany  uptr stack_size = this->stack_size();
118c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany  if (stack_size == 0)  // stack_size is not yet available, don't use FakeStack.
119c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany    return 0;
120c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany  uptr old_val = 0;
121c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany  // fake_stack_ has 3 states:
122c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany  // 0   -- not initialized
123c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany  // 1   -- being initialized
124c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany  // ptr -- initialized
125c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany  // This CAS checks if the state was 0 and if so changes it to state 1,
1262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  // if that was successful, it initializes the pointer.
127c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany  if (atomic_compare_exchange_strong(
128c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany      reinterpret_cast<atomic_uintptr_t *>(&fake_stack_), &old_val, 1UL,
1299433af375c7813486be91d2ac76f5072ee41818dKostya Serebryany      memory_order_relaxed)) {
130230e52f4e91b53f05ce19dbbf11047f4a0113483Kostya Serebryany    uptr stack_size_log = Log2(RoundUpToPowerOfTwo(stack_size));
1312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    CHECK_LE(flags()->min_uar_stack_size_log, flags()->max_uar_stack_size_log);
1322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    stack_size_log =
1332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines        Min(stack_size_log, static_cast<uptr>(flags()->max_uar_stack_size_log));
1342d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines    stack_size_log =
1352d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines        Max(stack_size_log, static_cast<uptr>(flags()->min_uar_stack_size_log));
136230e52f4e91b53f05ce19dbbf11047f4a0113483Kostya Serebryany    fake_stack_ = FakeStack::Create(stack_size_log);
1379433af375c7813486be91d2ac76f5072ee41818dKostya Serebryany    SetTLSFakeStack(fake_stack_);
1389433af375c7813486be91d2ac76f5072ee41818dKostya Serebryany    return fake_stack_;
1399433af375c7813486be91d2ac76f5072ee41818dKostya Serebryany  }
140c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany  return 0;
141c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany}
142c98fc1f8e52812cfaf5b19a29db5ed56acb0a682Kostya Serebryany
14369eca73ac96688c8bfe1f23ee006af29c7858c40Kostya Serebryanyvoid AsanThread::Init() {
1445d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  fake_stack_ = 0;  // Will be initialized lazily if needed.
1455d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  CHECK_EQ(this->stack_size(), 0U);
14612d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev  SetThreadStackAndTls();
1475d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines  CHECK_GT(this->stack_size(), 0U);
14855cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov  CHECK(AddrIsInMem(stack_bottom_));
149541cfb10f5daa17e48eb42365a74233cd551c545Kostya Serebryany  CHECK(AddrIsInMem(stack_top_ - 1));
15012d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev  ClearShadowForThreadStackAndTLS();
1512d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  int local = 0;
1522d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  VReport(1, "T%d: stack [%p,%p) size 0x%zx; local=%p\n", tid(),
1532d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines          (void *)stack_bottom_, (void *)stack_top_, stack_top_ - stack_bottom_,
1542d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines          &local);
15575b19ebf25af204cf209d108997272822241d6daAlexander Potapenko  AsanPlatformThreadInit();
15669eca73ac96688c8bfe1f23ee006af29c7858c40Kostya Serebryany}
15769eca73ac96688c8bfe1f23ee006af29c7858c40Kostya Serebryany
158def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonovthread_return_t AsanThread::ThreadStart(uptr os_id) {
15969eca73ac96688c8bfe1f23ee006af29c7858c40Kostya Serebryany  Init();
160def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  asanThreadRegistry().StartThread(tid(), os_id, 0);
1612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  if (common_flags()->use_sigaltstack) SetAlternateSignalStack();
1621e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
1631e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (!start_routine_) {
1643f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany    // start_routine_ == 0 if we're on the main thread or on one of the
1651e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    // OS X libdispatch worker threads. But nobody is supposed to call
1661e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    // ThreadStart() for the worker threads.
167a27bdf70ca24202dce21cf7c1a387aeaa400d889Kostya Serebryany    CHECK_EQ(tid(), 0);
1681e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    return 0;
1691e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
1701e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
171600972e3427173cc8904d741decd1af0ed5de9fdTimur Iskhodzhanov  thread_return_t res = start_routine_(arg_);
1721e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
173e86e35fbe861e73c5991200510a028877427b3e7Sergey Matveev  // On POSIX systems we defer this to the TSD destructor. LSan will consider
174e86e35fbe861e73c5991200510a028877427b3e7Sergey Matveev  // the thread's memory as non-live from the moment we call Destroy(), even
175e86e35fbe861e73c5991200510a028877427b3e7Sergey Matveev  // though that memory might contain pointers to heap objects which will be
176e86e35fbe861e73c5991200510a028877427b3e7Sergey Matveev  // cleaned up by a user-defined TSD destructor. Thus, calling Destroy() before
177e86e35fbe861e73c5991200510a028877427b3e7Sergey Matveev  // the TSD destructors have run might cause false positives in LSan.
178e86e35fbe861e73c5991200510a028877427b3e7Sergey Matveev  if (!SANITIZER_POSIX)
179e86e35fbe861e73c5991200510a028877427b3e7Sergey Matveev    this->Destroy();
180af3441580555ceed092170232cd5f2cc180f19f4Kostya Serebryany
1811e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  return res;
1821e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
1831e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
18412d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveevvoid AsanThread::SetThreadStackAndTls() {
185621770a196153ee61b338d34bafd1170c1899444Kostya Serebryany  uptr tls_size = 0;
186621770a196153ee61b338d34bafd1170c1899444Kostya Serebryany  GetThreadStackAndTls(tid() == 0, &stack_bottom_, &stack_size_, &tls_begin_,
18712d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev                       &tls_size);
188621770a196153ee61b338d34bafd1170c1899444Kostya Serebryany  stack_top_ = stack_bottom_ + stack_size_;
18912d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev  tls_end_ = tls_begin_ + tls_size;
19012d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev
191e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  int local;
192e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  CHECK(AddrIsInStack((uptr)&local));
193e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov}
194e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov
19512d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveevvoid AsanThread::ClearShadowForThreadStackAndTLS() {
19655cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov  PoisonShadow(stack_bottom_, stack_top_ - stack_bottom_, 0);
19712d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev  if (tls_begin_ != tls_end_)
19812d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev    PoisonShadow(tls_begin_, tls_end_ - tls_begin_, 0);
19955cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov}
20055cdfc6c5af92560bc0623b5a0d70af71511c3c8Alexey Samsonov
20150f3daa00d3da0a80c8798a3e977705e96ec106fKostya Serebryanyconst char *AsanThread::GetFrameNameByAddr(uptr addr, uptr *offset,
20250f3daa00d3da0a80c8798a3e977705e96ec106fKostya Serebryany                                           uptr *frame_pc) {
2033f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  uptr bottom = 0;
2041e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  if (AddrIsInStack(addr)) {
2051e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    bottom = stack_bottom();
206dcf98bf49d68533c7aebadbf6c4467afdd486c99Kostya Serebryany  } else if (has_fake_stack()) {
2077a0bba457ee05ced3adf37a0c0790d0ed23a5446Kostya Serebryany    bottom = fake_stack()->AddrIsInFakeStack(addr);
2081e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany    CHECK(bottom);
209e406c8c47570659287e619e23479f9fb6640299eAlexander Potapenko    *offset = addr - bottom;
21050f3daa00d3da0a80c8798a3e977705e96ec106fKostya Serebryany    *frame_pc = ((uptr*)bottom)[2];
211e406c8c47570659287e619e23479f9fb6640299eAlexander Potapenko    return  (const char *)((uptr*)bottom)[1];
2121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
2135af39e50366f1aacbebc284f572f08ad1ad07357Kostya Serebryany  uptr aligned_addr = addr & ~(SANITIZER_WORDSIZE/8 - 1);  // align addr.
214ee3925515e4c7966f3ef489f687aa7e5692806a9Kostya Serebryany  u8 *shadow_ptr = (u8*)MemToShadow(aligned_addr);
215ee3925515e4c7966f3ef489f687aa7e5692806a9Kostya Serebryany  u8 *shadow_bottom = (u8*)MemToShadow(bottom);
2163972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov
2173972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov  while (shadow_ptr >= shadow_bottom &&
218e406c8c47570659287e619e23479f9fb6640299eAlexander Potapenko         *shadow_ptr != kAsanStackLeftRedzoneMagic) {
2193972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov    shadow_ptr--;
2203972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov  }
2213972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov
2223972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov  while (shadow_ptr >= shadow_bottom &&
223e406c8c47570659287e619e23479f9fb6640299eAlexander Potapenko         *shadow_ptr == kAsanStackLeftRedzoneMagic) {
2243972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov    shadow_ptr--;
2251e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany  }
2263972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov
2273972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov  if (shadow_ptr < shadow_bottom) {
228e406c8c47570659287e619e23479f9fb6640299eAlexander Potapenko    *offset = 0;
229e406c8c47570659287e619e23479f9fb6640299eAlexander Potapenko    return "UNKNOWN";
2303972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov  }
2313972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov
2323f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  uptr* ptr = (uptr*)SHADOW_TO_MEM((uptr)(shadow_ptr + 1));
233e406c8c47570659287e619e23479f9fb6640299eAlexander Potapenko  CHECK(ptr[0] == kCurrentStackFrameMagic);
2343f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  *offset = addr - (uptr)ptr;
23550f3daa00d3da0a80c8798a3e977705e96ec106fKostya Serebryany  *frame_pc = ptr[2];
2363972ea03aa52d81ca324945ba94eea22d403df12Evgeniy Stepanov  return (const char*)ptr[1];
2371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}
2381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany
239def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonovstatic bool ThreadStackContainsAddress(ThreadContextBase *tctx_base,
240def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov                                       void *addr) {
241def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  AsanThreadContext *tctx = static_cast<AsanThreadContext*>(tctx_base);
242def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  AsanThread *t = tctx->thread;
2437a0bba457ee05ced3adf37a0c0790d0ed23a5446Kostya Serebryany  if (!t) return false;
2447a0bba457ee05ced3adf37a0c0790d0ed23a5446Kostya Serebryany  if (t->AddrIsInStack((uptr)addr)) return true;
245b39a604ff9d68ba7400197fca341771878443a69Kostya Serebryany  if (t->has_fake_stack() && t->fake_stack()->AddrIsInFakeStack((uptr)addr))
2467a0bba457ee05ced3adf37a0c0790d0ed23a5446Kostya Serebryany    return true;
2477a0bba457ee05ced3adf37a0c0790d0ed23a5446Kostya Serebryany  return false;
248def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov}
249def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov
25089c1384464848c1ad041becf8b97936fa10de21bAlexey SamsonovAsanThread *GetCurrentThread() {
251c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev  AsanThreadContext *context =
252c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev      reinterpret_cast<AsanThreadContext *>(AsanTSDGet());
253def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  if (!context) {
254def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov    if (SANITIZER_ANDROID) {
255def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov      // On Android, libc constructor is called _after_ asan_init, and cleans up
256def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov      // TSD. Try to figure out if this is still the main thread by the stack
257def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov      // address. We are not entirely sure that we have correct main thread
258195369bb7f59896487c4542716ca9c5d53975e78Dmitry Vyukov      // limits, so only do this magic on Android, and only if the found thread
259195369bb7f59896487c4542716ca9c5d53975e78Dmitry Vyukov      // is the main thread.
260def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov      AsanThreadContext *tctx = GetThreadContextByTidLocked(0);
261def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov      if (ThreadStackContainsAddress(tctx, &context)) {
262def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov        SetCurrentThread(tctx->thread);
263def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov        return tctx->thread;
264def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov      }
26589c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov    }
26689c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov    return 0;
26789c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov  }
268def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  return context->thread;
26989c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov}
27089c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov
27189c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonovvoid SetCurrentThread(AsanThread *t) {
272def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  CHECK(t->context());
2732d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines  VReport(2, "SetCurrentThread: %p for thread %p\n", t->context(),
2742d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines          (void *)GetThreadSelf());
27589c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov  // Make sure we do not reset the current AsanThread.
276def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  CHECK_EQ(0, AsanTSDGet());
277def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  AsanTSDSet(t->context());
278def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  CHECK_EQ(t->context(), AsanTSDGet());
27989c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov}
28089c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov
28189c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonovu32 GetCurrentTidOrInvalid() {
28289c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov  AsanThread *t = GetCurrentThread();
28389c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov  return t ? t->tid() : kInvalidTid;
28489c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov}
28589c1384464848c1ad041becf8b97936fa10de21bAlexey Samsonov
286def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey SamsonovAsanThread *FindThreadByStackAddress(uptr addr) {
287def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  asanThreadRegistry().CheckLocked();
288def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  AsanThreadContext *tctx = static_cast<AsanThreadContext *>(
289def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov      asanThreadRegistry().FindThreadContextLocked(ThreadStackContainsAddress,
290def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov                                                   (void *)addr));
291def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov  return tctx ? tctx->thread : 0;
292def1be9b7ef4091ce465c0fbfb26cdb52128ade8Alexey Samsonov}
293c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev
294c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveevvoid EnsureMainThreadIDIsCorrect() {
295c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev  AsanThreadContext *context =
296c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev      reinterpret_cast<AsanThreadContext *>(AsanTSDGet());
297c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev  if (context && (context->tid == 0))
298c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev    context->os_id = GetTid();
299c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev}
300c519335c2d6d32acaac32c0595f08a05081567e7Sergey Matveev
301c519335c2d6d32acaac32c0595f08a05081567e7Sergey Matveev__asan::AsanThread *GetAsanThreadByOsIDLocked(uptr os_id) {
302c519335c2d6d32acaac32c0595f08a05081567e7Sergey Matveev  __asan::AsanThreadContext *context = static_cast<__asan::AsanThreadContext *>(
303c519335c2d6d32acaac32c0595f08a05081567e7Sergey Matveev      __asan::asanThreadRegistry().FindThreadContextByOsIDLocked(os_id));
304c519335c2d6d32acaac32c0595f08a05081567e7Sergey Matveev  if (!context) return 0;
305c519335c2d6d32acaac32c0595f08a05081567e7Sergey Matveev  return context->thread;
306c519335c2d6d32acaac32c0595f08a05081567e7Sergey Matveev}
3071e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany}  // namespace __asan
308f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveev
309f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveev// --- Implementation of LSan-specific functions --- {{{1
310f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveevnamespace __lsan {
311f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveevbool GetThreadRangesLocked(uptr os_id, uptr *stack_begin, uptr *stack_end,
312f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveev                           uptr *tls_begin, uptr *tls_end,
313f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveev                           uptr *cache_begin, uptr *cache_end) {
314c519335c2d6d32acaac32c0595f08a05081567e7Sergey Matveev  __asan::AsanThread *t = __asan::GetAsanThreadByOsIDLocked(os_id);
31512d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev  if (!t) return false;
31612d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev  *stack_begin = t->stack_bottom();
31712d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev  *stack_end = t->stack_top();
31812d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev  *tls_begin = t->tls_begin();
31912d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev  *tls_end = t->tls_end();
32012d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev  // ASan doesn't keep allocator caches in TLS, so these are unused.
32112d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev  *cache_begin = 0;
32212d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev  *cache_end = 0;
32312d01bac1c09a8412546e71485a3cba2d416c0fcSergey Matveev  return true;
324f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveev}
325f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveev
326c519335c2d6d32acaac32c0595f08a05081567e7Sergey Matveevvoid ForEachExtraStackRange(uptr os_id, RangeIteratorCallback callback,
327c519335c2d6d32acaac32c0595f08a05081567e7Sergey Matveev                            void *arg) {
328c519335c2d6d32acaac32c0595f08a05081567e7Sergey Matveev  __asan::AsanThread *t = __asan::GetAsanThreadByOsIDLocked(os_id);
329c519335c2d6d32acaac32c0595f08a05081567e7Sergey Matveev  if (t && t->has_fake_stack())
330c519335c2d6d32acaac32c0595f08a05081567e7Sergey Matveev    t->fake_stack()->ForEachFakeFrame(callback, arg);
331c519335c2d6d32acaac32c0595f08a05081567e7Sergey Matveev}
332c519335c2d6d32acaac32c0595f08a05081567e7Sergey Matveev
333f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveevvoid LockThreadRegistry() {
334f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveev  __asan::asanThreadRegistry().Lock();
335f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveev}
336f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveev
337f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveevvoid UnlockThreadRegistry() {
338f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveev  __asan::asanThreadRegistry().Unlock();
339f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveev}
340c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev
341c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveevvoid EnsureMainThreadIDIsCorrect() {
342c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev  __asan::EnsureMainThreadIDIsCorrect();
343c6ac98d7fcc81768b2ef7ddc785c27e3fc1bdef6Sergey Matveev}
344f1ac1a44b4ed022f0a587a6bd711b1afbd3f8f62Sergey Matveev}  // namespace __lsan
345