1 //=-- lsan_posix.cpp -----------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===---------------------------------------------------------------------===// 8 // 9 // This file is a part of LeakSanitizer. 10 // Standalone LSan RTL code common to POSIX-like systems. 11 // 12 //===---------------------------------------------------------------------===// 13 14 #include "sanitizer_common/sanitizer_platform.h" 15 16 #if SANITIZER_POSIX 17 # include <pthread.h> 18 19 # include "lsan.h" 20 # include "lsan_allocator.h" 21 # include "lsan_thread.h" 22 # include "sanitizer_common/sanitizer_stacktrace.h" 23 # include "sanitizer_common/sanitizer_tls_get_addr.h" 24 25 namespace __lsan { 26 27 ThreadContext::ThreadContext(int tid) : ThreadContextLsanBase(tid) {} 28 29 struct OnStartedArgs { 30 uptr stack_begin; 31 uptr stack_end; 32 uptr cache_begin; 33 uptr cache_end; 34 uptr tls_begin; 35 uptr tls_end; 36 DTLS *dtls; 37 }; 38 39 void ThreadContext::OnStarted(void *arg) { 40 ThreadContextLsanBase::OnStarted(arg); 41 auto args = reinterpret_cast<const OnStartedArgs *>(arg); 42 stack_begin_ = args->stack_begin; 43 stack_end_ = args->stack_end; 44 tls_begin_ = args->tls_begin; 45 tls_end_ = args->tls_end; 46 cache_begin_ = args->cache_begin; 47 cache_end_ = args->cache_end; 48 dtls_ = args->dtls; 49 } 50 51 void ThreadStart(u32 tid, tid_t os_id, ThreadType thread_type) { 52 OnStartedArgs args; 53 GetThreadStackAndTls(tid == kMainTid, &args.stack_begin, &args.stack_end, 54 &args.tls_begin, &args.tls_end); 55 GetAllocatorCacheRange(&args.cache_begin, &args.cache_end); 56 args.dtls = DTLS_Get(); 57 ThreadContextLsanBase::ThreadStart(tid, os_id, thread_type, &args); 58 } 59 60 bool GetThreadRangesLocked(tid_t os_id, uptr *stack_begin, uptr *stack_end, 61 uptr *tls_begin, uptr *tls_end, uptr *cache_begin, 62 uptr *cache_end, DTLS **dtls) { 63 ThreadContext *context = static_cast<ThreadContext *>( 64 GetLsanThreadRegistryLocked()->FindThreadContextByOsIDLocked(os_id)); 65 if (!context) 66 return false; 67 *stack_begin = context->stack_begin(); 68 *stack_end = context->stack_end(); 69 *tls_begin = context->tls_begin(); 70 *tls_end = context->tls_end(); 71 *cache_begin = context->cache_begin(); 72 *cache_end = context->cache_end(); 73 *dtls = context->dtls(); 74 return true; 75 } 76 77 void InitializeMainThread() { 78 u32 tid = ThreadCreate(kMainTid, true); 79 CHECK_EQ(tid, kMainTid); 80 ThreadStart(tid, GetTid()); 81 } 82 83 static void OnStackUnwind(const SignalContext &sig, const void *, 84 BufferedStackTrace *stack) { 85 stack->Unwind(StackTrace::GetNextInstructionPc(sig.pc), sig.bp, sig.context, 86 common_flags()->fast_unwind_on_fatal); 87 } 88 89 void LsanOnDeadlySignal(int signo, void *siginfo, void *context) { 90 HandleDeadlySignal(siginfo, context, GetCurrentThreadId(), &OnStackUnwind, 91 nullptr); 92 } 93 94 void InstallAtExitCheckLeaks() { 95 if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit) 96 Atexit(DoLeakCheck); 97 } 98 99 static void BeforeFork() { 100 VReport(2, "BeforeFork tid: %llu\n", GetTid()); 101 LockGlobal(); 102 LockThreads(); 103 LockAllocator(); 104 StackDepotLockBeforeFork(); 105 } 106 107 static void AfterFork(bool fork_child) { 108 StackDepotUnlockAfterFork(fork_child); 109 UnlockAllocator(); 110 UnlockThreads(); 111 UnlockGlobal(); 112 VReport(2, "AfterFork tid: %llu\n", GetTid()); 113 } 114 115 void InstallAtForkHandler() { 116 # if SANITIZER_SOLARIS || SANITIZER_NETBSD || SANITIZER_APPLE 117 return; // FIXME: Implement FutexWait. 118 # endif 119 pthread_atfork( 120 &BeforeFork, []() { AfterFork(/* fork_child= */ false); }, 121 []() { AfterFork(/* fork_child= */ true); }); 122 } 123 124 } // namespace __lsan 125 126 #endif // SANITIZER_POSIX 127