[compiler-rt] a54b6b3 - [sanitizer][win] Fix `Atexit()` on MinGW asan_dynamic runtime

Alvin Wong via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 10 08:21:43 PDT 2023


Author: Alvin Wong
Date: 2023-04-10T23:21:16+08:00
New Revision: a54b6b33184ffa8e1c127029edf6b857b8199ea1

URL: https://github.com/llvm/llvm-project/commit/a54b6b33184ffa8e1c127029edf6b857b8199ea1
DIFF: https://github.com/llvm/llvm-project/commit/a54b6b33184ffa8e1c127029edf6b857b8199ea1.diff

LOG: [sanitizer][win] Fix `Atexit()` on MinGW asan_dynamic runtime

Some functions of asan depends on `Atexit()` handlers. On Windows, this
is implemented in ad3ec82bb1c7217b0187a1e16bb22642e194ce94 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

Added: 
    

Modified: 
    compiler-rt/lib/sanitizer_common/sanitizer_win.cpp
    compiler-rt/test/asan/TestCases/Windows/coverage-basic.cpp
    compiler-rt/test/asan/TestCases/atexit_stats.cpp

Removed: 
    


################################################################################
diff  --git a/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp
index e0568c9b62d5e..1c9b2dd8a5e45 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp
@@ -718,13 +718,24 @@ void ListOfModules::fallbackInit() { clear(); }
 // atexit() as soon as it is ready for use (i.e. after .CRT$XIC initializers).
 InternalMmapVectorNoCtor<void (*)(void)> atexit_functions;
 
-int Atexit(void (*function)(void)) {
+static int queueAtexit(void (*function)(void)) {
   atexit_functions.push_back(function);
   return 0;
 }
 
+// If Atexit() is being called after RunAtexit() has already been run, it needs
+// to be able to call atexit() directly. Here we use a function ponter to
+// switch out its behaviour.
+// An example of where this is needed is the asan_dynamic runtime on MinGW-w64.
+// On this environment, __asan_init is called during global constructor phase,
+// way after calling the .CRT$XID initializer.
+static int (*volatile queueOrCallAtExit)(void (*)(void)) = &queueAtexit;
+
+int Atexit(void (*function)(void)) { return queueOrCallAtExit(function); }
+
 static int RunAtexit() {
   TraceLoggingUnregister(g_asan_provider);
+  queueOrCallAtExit = &atexit;
   int ret = 0;
   for (uptr i = 0; i < atexit_functions.size(); ++i) {
     ret |= atexit(atexit_functions[i]);

diff  --git a/compiler-rt/test/asan/TestCases/Windows/coverage-basic.cpp b/compiler-rt/test/asan/TestCases/Windows/coverage-basic.cpp
index 96262cafffe82..71291e8a53158 100644
--- a/compiler-rt/test/asan/TestCases/Windows/coverage-basic.cpp
+++ b/compiler-rt/test/asan/TestCases/Windows/coverage-basic.cpp
@@ -5,9 +5,6 @@
 //
 // RUN: %sancov print *.sancov | FileCheck %s
 
-// FIXME: Investigate failure on MinGW.
-// XFAIL: target={{.*-windows-gnu}}
-
 #include <stdio.h>
 
 void foo() { fputs("FOO", stderr); }

diff  --git a/compiler-rt/test/asan/TestCases/atexit_stats.cpp b/compiler-rt/test/asan/TestCases/atexit_stats.cpp
index 1774385f9e1c4..c8d97da529212 100644
--- a/compiler-rt/test/asan/TestCases/atexit_stats.cpp
+++ b/compiler-rt/test/asan/TestCases/atexit_stats.cpp
@@ -6,9 +6,6 @@
 // https://code.google.com/p/address-sanitizer/issues/detail?id=263
 // UNSUPPORTED: android
 
-// FIXME: Investigate failure on MinGW.
-// XFAIL: target={{.*-windows-gnu}}
-
 #include <stdlib.h>
 #if !defined(__APPLE__) && !defined(__FreeBSD__) && !defined(__NetBSD__)
 #include <malloc.h>


        


More information about the llvm-commits mailing list