Skip to content

Commit a54b6b3

Browse files
committed
[sanitizer][win] Fix Atexit() on MinGW asan_dynamic runtime
Some functions of asan depends on `Atexit()` handlers. On Windows, this is implemented in ad3ec82 to queue the handlers in a vector then register them with `atexit()` only after the CRT is fully initialized. However, this is broken on MinGW with asan_dynamic runtime due to different initialization order. This change fixes the issue by making sure that `Atexit()` can call `atexit()` directly past the pre-initialization phase. This fixes two asan test cases on MinGW. Differential Revision: https://reviews.llvm.org/D147413
1 parent 225d255 commit a54b6b3

File tree

3 files changed

+12
-7
lines changed

3 files changed

+12
-7
lines changed

compiler-rt/lib/sanitizer_common/sanitizer_win.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -718,13 +718,24 @@ void ListOfModules::fallbackInit() { clear(); }
718718
// atexit() as soon as it is ready for use (i.e. after .CRT$XIC initializers).
719719
InternalMmapVectorNoCtor<void (*)(void)> atexit_functions;
720720

721-
int Atexit(void (*function)(void)) {
721+
static int queueAtexit(void (*function)(void)) {
722722
atexit_functions.push_back(function);
723723
return 0;
724724
}
725725

726+
// If Atexit() is being called after RunAtexit() has already been run, it needs
727+
// to be able to call atexit() directly. Here we use a function ponter to
728+
// switch out its behaviour.
729+
// An example of where this is needed is the asan_dynamic runtime on MinGW-w64.
730+
// On this environment, __asan_init is called during global constructor phase,
731+
// way after calling the .CRT$XID initializer.
732+
static int (*volatile queueOrCallAtExit)(void (*)(void)) = &queueAtexit;
733+
734+
int Atexit(void (*function)(void)) { return queueOrCallAtExit(function); }
735+
726736
static int RunAtexit() {
727737
TraceLoggingUnregister(g_asan_provider);
738+
queueOrCallAtExit = &atexit;
728739
int ret = 0;
729740
for (uptr i = 0; i < atexit_functions.size(); ++i) {
730741
ret |= atexit(atexit_functions[i]);

compiler-rt/test/asan/TestCases/Windows/coverage-basic.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,6 @@
55
//
66
// RUN: %sancov print *.sancov | FileCheck %s
77

8-
// FIXME: Investigate failure on MinGW.
9-
// XFAIL: target={{.*-windows-gnu}}
10-
118
#include <stdio.h>
129

1310
void foo() { fputs("FOO", stderr); }

compiler-rt/test/asan/TestCases/atexit_stats.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,6 @@
66
// https://code.google.com/p/address-sanitizer/issues/detail?id=263
77
// UNSUPPORTED: android
88

9-
// FIXME: Investigate failure on MinGW.
10-
// XFAIL: target={{.*-windows-gnu}}
11-
129
#include <stdlib.h>
1310
#if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__NetBSD__)
1411
#include <malloc.h>

0 commit comments

Comments
 (0)