
This is a re-land of https://reviews.llvm.org/D86171 with fix. Fuchsia's system libraries are instrumented and use the lsan allocator for internal purposes. So leak checking needs to run after all atexit hooks and after the system libraries' internal exit-time hooks. The <zircon/sanitizer.h> hook API calls the __sanitizer_process_exit_hook function at exactly the right time. Reviewed By: vitalybuka Differential Revision: https://reviews.llvm.org/D88248
102 lines
3.2 KiB
C++
102 lines
3.2 KiB
C++
//=-- lsan_posix.cpp -----------------------------------------------------===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===---------------------------------------------------------------------===//
|
|
//
|
|
// This file is a part of LeakSanitizer.
|
|
// Standalone LSan RTL code common to POSIX-like systems.
|
|
//
|
|
//===---------------------------------------------------------------------===//
|
|
|
|
#include "sanitizer_common/sanitizer_platform.h"
|
|
|
|
#if SANITIZER_POSIX
|
|
#include "lsan.h"
|
|
#include "lsan_allocator.h"
|
|
#include "sanitizer_common/sanitizer_stacktrace.h"
|
|
#include "sanitizer_common/sanitizer_tls_get_addr.h"
|
|
|
|
namespace __lsan {
|
|
|
|
ThreadContext::ThreadContext(int tid) : ThreadContextLsanBase(tid) {}
|
|
|
|
struct OnStartedArgs {
|
|
uptr stack_begin;
|
|
uptr stack_end;
|
|
uptr cache_begin;
|
|
uptr cache_end;
|
|
uptr tls_begin;
|
|
uptr tls_end;
|
|
DTLS *dtls;
|
|
};
|
|
|
|
void ThreadContext::OnStarted(void *arg) {
|
|
auto args = reinterpret_cast<const OnStartedArgs *>(arg);
|
|
stack_begin_ = args->stack_begin;
|
|
stack_end_ = args->stack_end;
|
|
tls_begin_ = args->tls_begin;
|
|
tls_end_ = args->tls_end;
|
|
cache_begin_ = args->cache_begin;
|
|
cache_end_ = args->cache_end;
|
|
dtls_ = args->dtls;
|
|
}
|
|
|
|
void ThreadStart(u32 tid, tid_t os_id, ThreadType thread_type) {
|
|
OnStartedArgs args;
|
|
uptr stack_size = 0;
|
|
uptr tls_size = 0;
|
|
GetThreadStackAndTls(tid == kMainTid, &args.stack_begin, &stack_size,
|
|
&args.tls_begin, &tls_size);
|
|
args.stack_end = args.stack_begin + stack_size;
|
|
args.tls_end = args.tls_begin + tls_size;
|
|
GetAllocatorCacheRange(&args.cache_begin, &args.cache_end);
|
|
args.dtls = DTLS_Get();
|
|
ThreadContextLsanBase::ThreadStart(tid, os_id, thread_type, &args);
|
|
}
|
|
|
|
bool GetThreadRangesLocked(tid_t os_id, uptr *stack_begin, uptr *stack_end,
|
|
uptr *tls_begin, uptr *tls_end, uptr *cache_begin,
|
|
uptr *cache_end, DTLS **dtls) {
|
|
ThreadContext *context = static_cast<ThreadContext *>(
|
|
GetThreadRegistryLocked()->FindThreadContextByOsIDLocked(os_id));
|
|
if (!context)
|
|
return false;
|
|
*stack_begin = context->stack_begin();
|
|
*stack_end = context->stack_end();
|
|
*tls_begin = context->tls_begin();
|
|
*tls_end = context->tls_end();
|
|
*cache_begin = context->cache_begin();
|
|
*cache_end = context->cache_end();
|
|
*dtls = context->dtls();
|
|
return true;
|
|
}
|
|
|
|
void InitializeMainThread() {
|
|
u32 tid = ThreadCreate(kMainTid, true);
|
|
CHECK_EQ(tid, kMainTid);
|
|
ThreadStart(tid, GetTid());
|
|
}
|
|
|
|
static void OnStackUnwind(const SignalContext &sig, const void *,
|
|
BufferedStackTrace *stack) {
|
|
stack->Unwind(StackTrace::GetNextInstructionPc(sig.pc), sig.bp, sig.context,
|
|
common_flags()->fast_unwind_on_fatal);
|
|
}
|
|
|
|
void LsanOnDeadlySignal(int signo, void *siginfo, void *context) {
|
|
HandleDeadlySignal(siginfo, context, GetCurrentThread(), &OnStackUnwind,
|
|
nullptr);
|
|
}
|
|
|
|
void InstallAtExitCheckLeaks() {
|
|
if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit)
|
|
Atexit(DoLeakCheck);
|
|
}
|
|
|
|
} // namespace __lsan
|
|
|
|
#endif // SANITIZER_POSIX
|