1 //=-- lsan_posix.cpp -----------------------------------------------------===//
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
7 //===---------------------------------------------------------------------===//
9 // This file is a part of LeakSanitizer.
10 // Standalone LSan RTL code common to POSIX-like systems.
12 //===---------------------------------------------------------------------===//
14 #include "sanitizer_common/sanitizer_platform.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"
27 ThreadContext::ThreadContext(int tid
) : ThreadContextLsanBase(tid
) {}
29 struct OnStartedArgs
{
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
;
51 void ThreadStart(u32 tid
, tid_t os_id
, ThreadType thread_type
) {
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
);
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
));
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();
77 void InitializeMainThread() {
78 u32 tid
= ThreadCreate(kMainTid
, true);
79 CHECK_EQ(tid
, kMainTid
);
80 ThreadStart(tid
, GetTid());
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
);
89 void LsanOnDeadlySignal(int signo
, void *siginfo
, void *context
) {
90 HandleDeadlySignal(siginfo
, context
, GetCurrentThreadId(), &OnStackUnwind
,
94 void InstallAtExitCheckLeaks() {
95 if (common_flags()->detect_leaks
&& common_flags()->leak_check_at_exit
)
99 static void BeforeFork() {
100 VReport(2, "BeforeFork tid: %llu\n", GetTid());
104 StackDepotLockBeforeFork();
107 static void AfterFork(bool fork_child
) {
108 StackDepotUnlockAfterFork(fork_child
);
112 VReport(2, "AfterFork tid: %llu\n", GetTid());
115 void InstallAtForkHandler() {
116 # if SANITIZER_SOLARIS || SANITIZER_NETBSD || SANITIZER_APPLE
117 return; // FIXME: Implement FutexWait.
120 &BeforeFork
, []() { AfterFork(/* fork_child= */ false); },
121 []() { AfterFork(/* fork_child= */ true); });
124 } // namespace __lsan
126 #endif // SANITIZER_POSIX