127 lines · cpp
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-exception6//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_POSIX17# 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 25namespace __lsan {26 27ThreadContext::ThreadContext(int tid) : ThreadContextLsanBase(tid) {}28 29struct 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 39void 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 51void ThreadStart(u32 tid, ThreadID 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 60bool GetThreadRangesLocked(ThreadID 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 77void InitializeMainThread() {78 u32 tid = ThreadCreate(kMainTid, true);79 CHECK_EQ(tid, kMainTid);80 ThreadStart(tid, GetTid());81}82 83static 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 89void LsanOnDeadlySignal(int signo, void *siginfo, void *context) {90 HandleDeadlySignal(siginfo, context, GetCurrentThreadId(), &OnStackUnwind,91 nullptr);92}93 94void InstallAtExitCheckLeaks() {95 if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit)96 Atexit(DoLeakCheck);97}98 99static void BeforeFork() {100 VReport(2, "BeforeFork tid: %llu\n", GetTid());101 LockGlobal();102 LockThreads();103 LockAllocator();104 StackDepotLockBeforeFork();105}106 107static 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 115void InstallAtForkHandler() {116# if SANITIZER_SOLARIS || SANITIZER_NETBSD || SANITIZER_APPLE117 return; // FIXME: Implement FutexWait.118# endif119 pthread_atfork(120 &BeforeFork, []() { AfterFork(/* fork_child= */ false); },121 []() { AfterFork(/* fork_child= */ true); });122}123 124} // namespace __lsan125 126#endif // SANITIZER_POSIX127