diff --git a/compiler-rt/lib/lsan/CMakeLists.txt b/compiler-rt/lib/lsan/CMakeLists.txt --- a/compiler-rt/lib/lsan/CMakeLists.txt +++ b/compiler-rt/lib/lsan/CMakeLists.txt @@ -12,10 +12,11 @@ set(LSAN_SOURCES lsan.cpp lsan_allocator.cpp - lsan_linux.cpp lsan_interceptors.cpp + lsan_linux.cpp lsan_mac.cpp lsan_malloc_mac.cpp + lsan_posix.cpp lsan_preinit.cpp lsan_thread.cpp ) diff --git a/compiler-rt/lib/lsan/lsan.h b/compiler-rt/lib/lsan/lsan.h --- a/compiler-rt/lib/lsan/lsan.h +++ b/compiler-rt/lib/lsan/lsan.h @@ -12,6 +12,9 @@ //===----------------------------------------------------------------------===// #include "lsan_thread.h" +#if SANITIZER_POSIX +#include "lsan_posix.h" +#endif #include "sanitizer_common/sanitizer_flags.h" #include "sanitizer_common/sanitizer_stacktrace.h" diff --git a/compiler-rt/lib/lsan/lsan.cpp b/compiler-rt/lib/lsan/lsan.cpp --- a/compiler-rt/lib/lsan/lsan.cpp +++ b/compiler-rt/lib/lsan/lsan.cpp @@ -114,10 +114,7 @@ InitializeInterceptors(); InitializeThreadRegistry(); InstallDeadlySignalHandlers(LsanOnDeadlySignal); - u32 tid = ThreadCreate(0, 0, true); - CHECK_EQ(tid, 0); - ThreadStart(tid, GetTid()); - SetCurrentThread(tid); + InitializeMainThread(); if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit) Atexit(DoLeakCheck); diff --git a/compiler-rt/lib/lsan/lsan_interceptors.cpp b/compiler-rt/lib/lsan/lsan_interceptors.cpp --- a/compiler-rt/lib/lsan/lsan_interceptors.cpp +++ b/compiler-rt/lib/lsan/lsan_interceptors.cpp @@ -22,7 +22,9 @@ #include "sanitizer_common/sanitizer_platform_interceptors.h" #include "sanitizer_common/sanitizer_platform_limits_netbsd.h" #include "sanitizer_common/sanitizer_platform_limits_posix.h" +#if SANITIZER_POSIX #include "sanitizer_common/sanitizer_posix.h" +#endif #include "sanitizer_common/sanitizer_tls_get_addr.h" #include "lsan.h" #include "lsan_allocator.h" @@ -416,7 +418,6 @@ int tid = 0; while ((tid = atomic_load(&p->tid, memory_order_acquire)) == 0) internal_sched_yield(); - SetCurrentThread(tid); ThreadStart(tid, GetTid()); atomic_store(&p->tid, 0, memory_order_release); return callback(param); diff --git a/compiler-rt/lib/lsan/lsan_posix.h b/compiler-rt/lib/lsan/lsan_posix.h new file mode 100644 --- /dev/null +++ b/compiler-rt/lib/lsan/lsan_posix.h @@ -0,0 +1,48 @@ +//=-- lsan_posix.h -----------------------------------------------------===// +// +// 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. +// +//===---------------------------------------------------------------------===// + +#ifndef LSAN_POSIX_H +#define LSAN_POSIX_H + +#include "sanitizer_common/sanitizer_platform.h" +#include "lsan_thread.h" + +#if !SANITIZER_POSIX +#error "lsan_posix.h is used only on POSIX-like systems (SANITIZER_POSIX)" +#endif + +namespace __sanitizer { +struct DTLS; +} + +namespace __lsan { + +class ThreadContext : public ThreadContextLsanBase { + public: + explicit ThreadContext(int tid); + void OnStarted(void *arg) override; + uptr tls_begin() { return tls_begin_; } + uptr tls_end() { return tls_end_; } + DTLS *dtls() { return dtls_; } + + private: + uptr tls_begin_, tls_end_; + DTLS *dtls_; +}; + +void ThreadStart(u32 tid, tid_t os_id, + ThreadType thread_type = ThreadType::Regular); + +} // namespace __lsan + +#endif // LSAN_POSIX_H diff --git a/compiler-rt/lib/lsan/lsan_posix.cpp b/compiler-rt/lib/lsan/lsan_posix.cpp new file mode 100644 --- /dev/null +++ b/compiler-rt/lib/lsan/lsan_posix.cpp @@ -0,0 +1,85 @@ +//=-- 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), + tls_begin_(0), + tls_end_(0), + dtls_(nullptr) {} + +struct OnStartedArgs { + uptr stack_begin, stack_end, + cache_begin, cache_end, + tls_begin, tls_end; + DTLS *dtls; +}; + +void ThreadContext::OnStarted(void *arg) { + auto args = reinterpret_cast(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 == 0, &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( + 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(0, 0, true); + CHECK_EQ(tid, 0); + ThreadStart(tid, GetTid()); +} + +} // namespace __lsan + +#endif // SANITIZER_POSIX diff --git a/compiler-rt/lib/lsan/lsan_thread.h b/compiler-rt/lib/lsan/lsan_thread.h --- a/compiler-rt/lib/lsan/lsan_thread.h +++ b/compiler-rt/lib/lsan/lsan_thread.h @@ -16,38 +16,34 @@ #include "sanitizer_common/sanitizer_thread_registry.h" -namespace __sanitizer { -struct DTLS; -} - namespace __lsan { -class ThreadContext : public ThreadContextBase { +class ThreadContextLsanBase : public ThreadContextBase { public: - explicit ThreadContext(int tid); - void OnStarted(void *arg) override; + explicit ThreadContextLsanBase(int tid); void OnFinished() override; uptr stack_begin() { return stack_begin_; } uptr stack_end() { return stack_end_; } - uptr tls_begin() { return tls_begin_; } - uptr tls_end() { return tls_end_; } uptr cache_begin() { return cache_begin_; } uptr cache_end() { return cache_end_; } - DTLS *dtls() { return dtls_; } - private: + // The argument is passed on to the subclass's OnStarted member function. + static void ThreadStart(u32 tid, tid_t os_id, ThreadType thread_type, + void *onstarted_arg); + + protected: uptr stack_begin_, stack_end_, - cache_begin_, cache_end_, - tls_begin_, tls_end_; - DTLS *dtls_; + cache_begin_, cache_end_; }; +// This subclass of ThreadContextLsanBase is declared in an OS-specific header. +class ThreadContext; + void InitializeThreadRegistry(); +void InitializeMainThread(); -void ThreadStart(u32 tid, tid_t os_id, - ThreadType thread_type = ThreadType::Regular); +u32 ThreadCreate(u32 tid, uptr uid, bool detached, void *arg = nullptr); void ThreadFinish(); -u32 ThreadCreate(u32 tid, uptr uid, bool detached); void ThreadJoin(u32 tid); u32 ThreadTid(uptr uid); @@ -55,6 +51,7 @@ void SetCurrentThread(u32 tid); ThreadContext *CurrentThreadContext(); void EnsureMainThreadIDIsCorrect(); + } // namespace __lsan #endif // LSAN_THREAD_H diff --git a/compiler-rt/lib/lsan/lsan_thread.cpp b/compiler-rt/lib/lsan/lsan_thread.cpp --- a/compiler-rt/lib/lsan/lsan_thread.cpp +++ b/compiler-rt/lib/lsan/lsan_thread.cpp @@ -17,6 +17,7 @@ #include "sanitizer_common/sanitizer_placement_new.h" #include "sanitizer_common/sanitizer_thread_registry.h" #include "sanitizer_common/sanitizer_tls_get_addr.h" +#include "lsan.h" #include "lsan_allocator.h" #include "lsan_common.h" @@ -38,55 +39,26 @@ ThreadRegistry(CreateThreadContext, kMaxThreads, kThreadQuarantineSize); } -ThreadContext::ThreadContext(int tid) +ThreadContextLsanBase::ThreadContextLsanBase(int tid) : ThreadContextBase(tid), stack_begin_(0), stack_end_(0), cache_begin_(0), - cache_end_(0), - tls_begin_(0), - tls_end_(0), - dtls_(nullptr) {} - -struct OnStartedArgs { - uptr stack_begin, stack_end, - cache_begin, cache_end, - tls_begin, tls_end; - DTLS *dtls; -}; - -void ThreadContext::OnStarted(void *arg) { - OnStartedArgs *args = reinterpret_cast(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; -} + cache_end_(0) {} -void ThreadContext::OnFinished() { +void ThreadContextLsanBase::OnFinished() { AllocatorThreadFinish(); DTLS_Destroy(); } -u32 ThreadCreate(u32 parent_tid, uptr user_id, bool detached) { - return thread_registry->CreateThread(user_id, detached, parent_tid, - /* arg */ nullptr); +u32 ThreadCreate(u32 parent_tid, uptr user_id, bool detached, void *arg) { + return thread_registry->CreateThread(user_id, detached, parent_tid, arg); } -void ThreadStart(u32 tid, tid_t os_id, ThreadType thread_type) { - OnStartedArgs args; - uptr stack_size = 0; - uptr tls_size = 0; - GetThreadStackAndTls(tid == 0, &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(); - thread_registry->StartThread(tid, os_id, thread_type, &args); +void ThreadContextLsanBase::ThreadStart(u32 tid, tid_t os_id, + ThreadType thread_type, void *arg) { + thread_registry->StartThread(tid, os_id, thread_type, arg); + SetCurrentThread(tid); } void ThreadFinish() { @@ -126,22 +98,6 @@ ///// Interface to the common LSan module. ///// -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( - thread_registry->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 ForEachExtraStackRange(tid_t os_id, RangeIteratorCallback callback, void *arg) { }