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 uptr stack_size = 0; 54 uptr tls_size = 0; 55 GetThreadStackAndTls(tid == kMainTid, &args.stack_begin, &stack_size, 56 &args.tls_begin, &tls_size); 57 args.stack_end = args.stack_begin + stack_size; 58 args.tls_end = args.tls_begin + tls_size; 59 GetAllocatorCacheRange(&args.cache_begin, &args.cache_end); 60 args.dtls = DTLS_Get(); 61 ThreadContextLsanBase::ThreadStart(tid, os_id, thread_type, &args); 62 } 63 64 bool GetThreadRangesLocked(tid_t os_id, uptr *stack_begin, uptr *stack_end, 65 uptr *tls_begin, uptr *tls_end, uptr *cache_begin, 66 uptr *cache_end, DTLS **dtls) { 67 ThreadContext *context = static_cast<ThreadContext *>( 68 GetLsanThreadRegistryLocked()->FindThreadContextByOsIDLocked(os_id)); 69 if (!context) 70 return false; 71 *stack_begin = context->stack_begin(); 72 *stack_end = context->stack_end(); 73 *tls_begin = context->tls_begin(); 74 *tls_end = context->tls_end(); 75 *cache_begin = context->cache_begin(); 76 *cache_end = context->cache_end(); 77 *dtls = context->dtls(); 78 return true; 79 } 80 81 void InitializeMainThread() { 82 u32 tid = ThreadCreate(kMainTid, true); 83 CHECK_EQ(tid, kMainTid); 84 ThreadStart(tid, GetTid()); 85 } 86 87 static void OnStackUnwind(const SignalContext &sig, const void *, 88 BufferedStackTrace *stack) { 89 stack->Unwind(StackTrace::GetNextInstructionPc(sig.pc), sig.bp, sig.context, 90 common_flags()->fast_unwind_on_fatal); 91 } 92 93 void LsanOnDeadlySignal(int signo, void *siginfo, void *context) { 94 HandleDeadlySignal(siginfo, context, GetCurrentThreadId(), &OnStackUnwind, 95 nullptr); 96 } 97 98 void InstallAtExitCheckLeaks() { 99 if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit) 100 Atexit(DoLeakCheck); 101 } 102 103 static void BeforeFork() { 104 LockGlobal(); 105 LockThreads(); 106 LockAllocator(); 107 StackDepotLockBeforeFork(); 108 } 109 110 static void AfterFork(bool fork_child) { 111 StackDepotUnlockAfterFork(fork_child); 112 UnlockAllocator(); 113 UnlockThreads(); 114 UnlockGlobal(); 115 } 116 117 void InstallAtForkHandler() { 118 # if SANITIZER_SOLARIS || SANITIZER_NETBSD || SANITIZER_APPLE 119 return; // FIXME: Implement FutexWait. 120 # endif 121 pthread_atfork( 122 &BeforeFork, []() { AfterFork(/* fork_child= */ false); }, 123 []() { AfterFork(/* fork_child= */ true); }); 124 } 125 126 } // namespace __lsan 127 128 #endif // SANITIZER_POSIX 129