Skip to content

Commit 0caad9f

Browse files
committed
[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
1 parent 5281ba1 commit 0caad9f

File tree

10 files changed

+65
-21
lines changed

10 files changed

+65
-21
lines changed

compiler-rt/lib/asan/asan_fuchsia.cpp

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,24 +14,26 @@
1414
#include "sanitizer_common/sanitizer_fuchsia.h"
1515
#if SANITIZER_FUCHSIA
1616

17-
#include "asan_interceptors.h"
18-
#include "asan_internal.h"
19-
#include "asan_stack.h"
20-
#include "asan_thread.h"
21-
2217
#include <limits.h>
2318
#include <zircon/sanitizer.h>
2419
#include <zircon/syscalls.h>
2520
#include <zircon/threads.h>
2621

22+
#include "asan_interceptors.h"
23+
#include "asan_internal.h"
24+
#include "asan_stack.h"
25+
#include "asan_thread.h"
26+
#include "lsan/lsan_common.h"
27+
2728
namespace __asan {
2829

2930
// The system already set up the shadow memory for us.
3031
// __sanitizer::GetMaxUserVirtualAddress has already been called by
3132
// AsanInitInternal->InitializeHighMemEnd (asan_rtl.cpp).
3233
// Just do some additional sanity checks here.
3334
void InitializeShadowMemory() {
34-
if (Verbosity()) PrintAddressSpaceLayout();
35+
if (Verbosity())
36+
PrintAddressSpaceLayout();
3537

3638
// Make sure SHADOW_OFFSET doesn't use __asan_shadow_memory_dynamic_address.
3739
__asan_shadow_memory_dynamic_address = kDefaultShadowSentinel;
@@ -148,7 +150,8 @@ static void *BeforeThreadCreateHook(uptr user_id, bool detached,
148150
uptr stack_size) {
149151
EnsureMainThreadIDIsCorrect();
150152
// Strict init-order checking is thread-hostile.
151-
if (flags()->strict_init_order) StopInitOrderChecking();
153+
if (flags()->strict_init_order)
154+
StopInitOrderChecking();
152155

153156
GET_STACK_TRACE_THREAD;
154157
u32 parent_tid = GetCurrentTidOrInvalid();
@@ -202,8 +205,18 @@ void FlushUnneededASanShadowMemory(uptr p, uptr size) {
202205
__sanitizer_fill_shadow(p, size, 0, 0);
203206
}
204207

208+
// On Fuchsia, leak detection is done by a special hook after atexit hooks.
209+
// So this doesn't install any atexit hook like on other platforms.
210+
void InstallAtExitCheckLeaks() {}
211+
205212
} // namespace __asan
206213

214+
namespace __lsan {
215+
216+
bool UseExitcodeOnLeak() { return __asan::flags()->halt_on_error; }
217+
218+
} // namespace __lsan
219+
207220
// These are declared (in extern "C") by <zircon/sanitizer.h>.
208221
// The system runtime will call our definitions directly.
209222

compiler-rt/lib/asan/asan_internal.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,8 @@ void *AsanDlSymNext(const char *sym);
123123
// `dlopen()` specific initialization inside this function.
124124
bool HandleDlopenInit();
125125

126+
void InstallAtExitCheckLeaks();
127+
126128
// Add convenient macro for interface functions that may be represented as
127129
// weak hooks.
128130
#define ASAN_MALLOC_HOOK(ptr, size) \

compiler-rt/lib/asan/asan_posix.cpp

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,18 @@ void PlatformTSDDtor(void *tsd) {
140140
AsanThread::TSDDtor(tsd);
141141
}
142142
#endif
143+
144+
#if CAN_SANITIZE_LEAKS
145+
void InstallAtExitCheckLeaks() {
146+
if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit) {
147+
if (flags()->halt_on_error)
148+
Atexit(__lsan::DoLeakCheck);
149+
else
150+
Atexit(__lsan::DoRecoverableLeakCheckVoid);
151+
}
152+
}
153+
#endif
154+
143155
} // namespace __asan
144156

145157
#endif // SANITIZER_POSIX

compiler-rt/lib/asan/asan_rtl.cpp

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -500,12 +500,7 @@ static void AsanInitInternal() {
500500

501501
if (CAN_SANITIZE_LEAKS) {
502502
__lsan::InitCommonLsan();
503-
if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit) {
504-
if (flags()->halt_on_error)
505-
Atexit(__lsan::DoLeakCheck);
506-
else
507-
Atexit(__lsan::DoRecoverableLeakCheckVoid);
508-
}
503+
InstallAtExitCheckLeaks();
509504
}
510505

511506
#if CAN_SANITIZE_UB

compiler-rt/lib/asan/asan_win.cpp

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
//===-- asan_win.cpp ------------------------------------------------------===//
1+
//===-- asan_win.cpp
2+
//------------------------------------------------------===//>
23
//
34
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
45
// See https://llvm.org/LICENSE.txt for license information.
@@ -14,9 +15,8 @@
1415
#include "sanitizer_common/sanitizer_platform.h"
1516
#if SANITIZER_WINDOWS
1617
#define WIN32_LEAN_AND_MEAN
17-
#include <windows.h>
18-
1918
#include <stdlib.h>
19+
#include <windows.h>
2020

2121
#include "asan_interceptors.h"
2222
#include "asan_internal.h"
@@ -49,8 +49,8 @@ uptr __asan_get_shadow_memory_dynamic_address() {
4949
static LPTOP_LEVEL_EXCEPTION_FILTER default_seh_handler;
5050
static LPTOP_LEVEL_EXCEPTION_FILTER user_seh_handler;
5151

52-
extern "C" SANITIZER_INTERFACE_ATTRIBUTE
53-
long __asan_unhandled_exception_filter(EXCEPTION_POINTERS *info) {
52+
extern "C" SANITIZER_INTERFACE_ATTRIBUTE long __asan_unhandled_exception_filter(
53+
EXCEPTION_POINTERS *info) {
5454
EXCEPTION_RECORD *exception_record = info->ExceptionRecord;
5555
CONTEXT *context = info->ContextRecord;
5656

@@ -187,6 +187,8 @@ void InitializePlatformInterceptors() {
187187
}
188188
}
189189

190+
void InstallAtExitCheckLeaks() {}
191+
190192
void AsanApplyToGlobals(globals_op_fptr op, const void *needle) {
191193
UNIMPLEMENTED();
192194
}

compiler-rt/lib/lsan/lsan.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,7 @@ extern "C" void __lsan_init() {
103103
InitializeThreadRegistry();
104104
InstallDeadlySignalHandlers(LsanOnDeadlySignal);
105105
InitializeMainThread();
106-
107-
if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit)
108-
Atexit(DoLeakCheck);
106+
InstallAtExitCheckLeaks();
109107

110108
InitializeCoverage(common_flags()->coverage, common_flags()->coverage_dir);
111109

compiler-rt/lib/lsan/lsan.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ namespace __lsan {
3939
void InitializeInterceptors();
4040
void ReplaceSystemMalloc();
4141
void LsanOnDeadlySignal(int signo, void *siginfo, void *context);
42+
void InstallAtExitCheckLeaks();
4243

4344
#define ENSURE_LSAN_INITED do { \
4445
CHECK(!lsan_init_is_running); \

compiler-rt/lib/lsan/lsan_common_fuchsia.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,16 @@ void ProcessPlatformSpecificAllocations(Frontier *frontier) {}
5151
// behavior and causes rare race conditions.
5252
void HandleLeaks() {}
5353

54+
// This is defined differently in asan_fuchsiap.cpp and lsan_fuchsia.cpp.
55+
bool UseExitcodeOnLeak();
56+
5457
int ExitHook(int status) {
58+
if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit) {
59+
if (UseExitcodeOnLeak())
60+
DoLeakCheck();
61+
else
62+
DoRecoverableLeakCheckVoid();
63+
}
5564
return status == 0 && HasReportedLeaks() ? common_flags()->exitcode : status;
5665
}
5766

compiler-rt/lib/lsan/lsan_fuchsia.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,13 @@ void GetAllThreadAllocatorCachesLocked(InternalMmapVector<uptr> *caches) {
7676
caches);
7777
}
7878

79+
// On Fuchsia, leak detection is done by a special hook after atexit hooks.
80+
// So this doesn't install any atexit hook like on other platforms.
81+
void InstallAtExitCheckLeaks() {}
82+
83+
// ASan defines this to check its `halt_on_error` flag.
84+
bool UseExitcodeOnLeak() { return true; }
85+
7986
} // namespace __lsan
8087

8188
// These are declared (in extern "C") by <zircon/sanitizer.h>.

compiler-rt/lib/lsan/lsan_posix.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,11 @@ void LsanOnDeadlySignal(int signo, void *siginfo, void *context) {
9191
nullptr);
9292
}
9393

94+
void InstallAtExitCheckLeaks() {
95+
if (common_flags()->detect_leaks && common_flags()->leak_check_at_exit)
96+
Atexit(DoLeakCheck);
97+
}
98+
9499
} // namespace __lsan
95100

96101
#endif // SANITIZER_POSIX

0 commit comments

Comments
 (0)