forked from OSchip/llvm-project
[lsan] On Fuchsia, don't use atexit hook for leak checks
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, phosek Differential Revision: https://reviews.llvm.org/D86171
This commit is contained in:
parent
5281ba1994
commit
0caad9fe44
|
@ -14,16 +14,17 @@
|
|||
#include "sanitizer_common/sanitizer_fuchsia.h"
|
||||
#if SANITIZER_FUCHSIA
|
||||
|
||||
#include "asan_interceptors.h"
|
||||
#include "asan_internal.h"
|
||||
#include "asan_stack.h"
|
||||
#include "asan_thread.h"
|
||||
|
||||
#include <limits.h>
|
||||
#include <zircon/sanitizer.h>
|
||||
#include <zircon/syscalls.h>
|
||||
#include <zircon/threads.h>
|
||||
|
||||
#include "asan_interceptors.h"
|
||||
#include "asan_internal.h"
|
||||
#include "asan_stack.h"
|
||||
#include "asan_thread.h"
|
||||
#include "lsan/lsan_common.h"
|
||||
|
||||
namespace __asan {
|
||||
|
||||
// The system already set up the shadow memory for us.
|
||||
|
@ -31,7 +32,8 @@ namespace __asan {
|
|||
// AsanInitInternal->InitializeHighMemEnd (asan_rtl.cpp).
|
||||
// Just do some additional sanity checks here.
|
||||
void InitializeShadowMemory() {
|
||||
if (Verbosity()) PrintAddressSpaceLayout();
|
||||
if (Verbosity())
|
||||
PrintAddressSpaceLayout();
|
||||
|
||||
// Make sure SHADOW_OFFSET doesn't use __asan_shadow_memory_dynamic_address.
|
||||
__asan_shadow_memory_dynamic_address = kDefaultShadowSentinel;
|
||||
|
@ -148,7 +150,8 @@ static void *BeforeThreadCreateHook(uptr user_id, bool detached,
|
|||
uptr stack_size) {
|
||||
EnsureMainThreadIDIsCorrect();
|
||||
// Strict init-order checking is thread-hostile.
|
||||
if (flags()->strict_init_order) StopInitOrderChecking();
|
||||
if (flags()->strict_init_order)
|
||||
StopInitOrderChecking();
|
||||
|
||||
GET_STACK_TRACE_THREAD;
|
||||
u32 parent_tid = GetCurrentTidOrInvalid();
|
||||
|
@ -202,8 +205,18 @@ void FlushUnneededASanShadowMemory(uptr p, uptr size) {
|
|||
__sanitizer_fill_shadow(p, size, 0, 0);
|
||||
}
|
||||
|
||||
// On Fuchsia, leak detection is done by a special hook after atexit hooks.
|
||||
// So this doesn't install any atexit hook like on other platforms.
|
||||
void InstallAtExitCheckLeaks() {}
|
||||
|
||||
} // namespace __asan
|
||||
|
||||
namespace __lsan {
|
||||
|
||||
bool UseExitcodeOnLeak() { return __asan::flags()->halt_on_error; }
|
||||
|
||||
} // namespace __lsan
|
||||
|
||||
// These are declared (in extern "C") by <zircon/sanitizer.h>.
|
||||
// The system runtime will call our definitions directly.
|
||||
|
||||
|
|
|
@ -123,6 +123,8 @@ void *AsanDlSymNext(const char *sym);
|
|||
// `dlopen()` specific initialization inside this function.
|
||||
bool HandleDlopenInit();
|
||||
|
||||
void InstallAtExitCheckLeaks();
|
||||
|
||||
// Add convenient macro for interface functions that may be represented as
|
||||
// weak hooks.
|
||||
#define ASAN_MALLOC_HOOK(ptr, size) \
|
||||
|
|
|
@ -140,6 +140,18 @@ void PlatformTSDDtor(void *tsd) {
|
|||
AsanThread::TSDDtor(tsd);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if CAN_SANITIZE_LEAKS
|
||||
void InstallAtExitCheckLeaks() {
|
||||
if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit) {
|
||||
if (flags()->halt_on_error)
|
||||
Atexit(__lsan::DoLeakCheck);
|
||||
else
|
||||
Atexit(__lsan::DoRecoverableLeakCheckVoid);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace __asan
|
||||
|
||||
#endif // SANITIZER_POSIX
|
||||
|
|
|
@ -500,12 +500,7 @@ static void AsanInitInternal() {
|
|||
|
||||
if (CAN_SANITIZE_LEAKS) {
|
||||
__lsan::InitCommonLsan();
|
||||
if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit) {
|
||||
if (flags()->halt_on_error)
|
||||
Atexit(__lsan::DoLeakCheck);
|
||||
else
|
||||
Atexit(__lsan::DoRecoverableLeakCheckVoid);
|
||||
}
|
||||
InstallAtExitCheckLeaks();
|
||||
}
|
||||
|
||||
#if CAN_SANITIZE_UB
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
//===-- asan_win.cpp ------------------------------------------------------===//
|
||||
//===-- asan_win.cpp
|
||||
//------------------------------------------------------===//>
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
|
@ -14,9 +15,8 @@
|
|||
#include "sanitizer_common/sanitizer_platform.h"
|
||||
#if SANITIZER_WINDOWS
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <windows.h>
|
||||
|
||||
#include "asan_interceptors.h"
|
||||
#include "asan_internal.h"
|
||||
|
@ -49,8 +49,8 @@ uptr __asan_get_shadow_memory_dynamic_address() {
|
|||
static LPTOP_LEVEL_EXCEPTION_FILTER default_seh_handler;
|
||||
static LPTOP_LEVEL_EXCEPTION_FILTER user_seh_handler;
|
||||
|
||||
extern "C" SANITIZER_INTERFACE_ATTRIBUTE
|
||||
long __asan_unhandled_exception_filter(EXCEPTION_POINTERS *info) {
|
||||
extern "C" SANITIZER_INTERFACE_ATTRIBUTE long __asan_unhandled_exception_filter(
|
||||
EXCEPTION_POINTERS *info) {
|
||||
EXCEPTION_RECORD *exception_record = info->ExceptionRecord;
|
||||
CONTEXT *context = info->ContextRecord;
|
||||
|
||||
|
@ -187,6 +187,8 @@ void InitializePlatformInterceptors() {
|
|||
}
|
||||
}
|
||||
|
||||
void InstallAtExitCheckLeaks() {}
|
||||
|
||||
void AsanApplyToGlobals(globals_op_fptr op, const void *needle) {
|
||||
UNIMPLEMENTED();
|
||||
}
|
||||
|
|
|
@ -103,9 +103,7 @@ extern "C" void __lsan_init() {
|
|||
InitializeThreadRegistry();
|
||||
InstallDeadlySignalHandlers(LsanOnDeadlySignal);
|
||||
InitializeMainThread();
|
||||
|
||||
if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit)
|
||||
Atexit(DoLeakCheck);
|
||||
InstallAtExitCheckLeaks();
|
||||
|
||||
InitializeCoverage(common_flags()->coverage, common_flags()->coverage_dir);
|
||||
|
||||
|
|
|
@ -39,6 +39,7 @@ namespace __lsan {
|
|||
void InitializeInterceptors();
|
||||
void ReplaceSystemMalloc();
|
||||
void LsanOnDeadlySignal(int signo, void *siginfo, void *context);
|
||||
void InstallAtExitCheckLeaks();
|
||||
|
||||
#define ENSURE_LSAN_INITED do { \
|
||||
CHECK(!lsan_init_is_running); \
|
||||
|
|
|
@ -51,7 +51,16 @@ void ProcessPlatformSpecificAllocations(Frontier *frontier) {}
|
|||
// behavior and causes rare race conditions.
|
||||
void HandleLeaks() {}
|
||||
|
||||
// This is defined differently in asan_fuchsiap.cpp and lsan_fuchsia.cpp.
|
||||
bool UseExitcodeOnLeak();
|
||||
|
||||
int ExitHook(int status) {
|
||||
if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit) {
|
||||
if (UseExitcodeOnLeak())
|
||||
DoLeakCheck();
|
||||
else
|
||||
DoRecoverableLeakCheckVoid();
|
||||
}
|
||||
return status == 0 && HasReportedLeaks() ? common_flags()->exitcode : status;
|
||||
}
|
||||
|
||||
|
|
|
@ -76,6 +76,13 @@ void GetAllThreadAllocatorCachesLocked(InternalMmapVector<uptr> *caches) {
|
|||
caches);
|
||||
}
|
||||
|
||||
// On Fuchsia, leak detection is done by a special hook after atexit hooks.
|
||||
// So this doesn't install any atexit hook like on other platforms.
|
||||
void InstallAtExitCheckLeaks() {}
|
||||
|
||||
// ASan defines this to check its `halt_on_error` flag.
|
||||
bool UseExitcodeOnLeak() { return true; }
|
||||
|
||||
} // namespace __lsan
|
||||
|
||||
// These are declared (in extern "C") by <zircon/sanitizer.h>.
|
||||
|
|
|
@ -91,6 +91,11 @@ void LsanOnDeadlySignal(int signo, void *siginfo, void *context) {
|
|||
nullptr);
|
||||
}
|
||||
|
||||
void InstallAtExitCheckLeaks() {
|
||||
if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit)
|
||||
Atexit(DoLeakCheck);
|
||||
}
|
||||
|
||||
} // namespace __lsan
|
||||
|
||||
#endif // SANITIZER_POSIX
|
||||
|
|
Loading…
Reference in New Issue