[compiler-rt] [compiler-rt] Retain sanitizer callbacks with MinGW GCC (PR #222711)

via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 10 09:52:13 PDT 2026


https://github.com/oltolm created https://github.com/llvm/llvm-project/pull/222711

MSVC and clang-cl use /include directives emitted by WIN_FORCE_LINK. GNU tools need an ordinary used relocation instead. Keep the sanitizer initialization callbacks and ASan DSO registration object reachable when linking with MinGW GCC.

>From 72fec94202d9c35f266b6d729883dae56c0bea3b Mon Sep 17 00:00:00 2001
From: Oleg Tolmatcev <oleg.tolmatcev at gmail.com>
Date: Thu, 10 Sep 2026 17:53:41 +0200
Subject: [PATCH] [compiler-rt] Retain sanitizer callbacks with MinGW GCC

MSVC and clang-cl use /include directives emitted by WIN_FORCE_LINK.
GNU tools need an ordinary used relocation instead. Keep the sanitizer
initialization callbacks and ASan DSO registration object reachable when
linking with MinGW GCC.

Co-authored-by: Hannes Domani <ssbssa at yahoo.de>
---
 compiler-rt/lib/asan/asan_win.cpp             |  2 ++
 .../asan/asan_win_common_runtime_thunk.cpp    |  1 +
 .../lib/sanitizer_common/sanitizer_win_defs.h | 20 +++++++++++++------
 .../sanitizer_win_thunk_interception.cpp      |  2 ++
 4 files changed, 19 insertions(+), 6 deletions(-)

diff --git a/compiler-rt/lib/asan/asan_win.cpp b/compiler-rt/lib/asan/asan_win.cpp
index c671a2d6327eb..dfc44a528885e 100644
--- a/compiler-rt/lib/asan/asan_win.cpp
+++ b/compiler-rt/lib/asan/asan_win.cpp
@@ -414,6 +414,8 @@ static void NTAPI asan_thread_exit(void *module, DWORD reason, void *reserved) {
 IN_SECTION(".CRT$XLY")
 void(NTAPI* __asan_tls_exit)(void*, unsigned long, void*) = asan_thread_exit;
 
+extern "C" void (*const __asan_dso_reg_hook)();
+
 WIN_FORCE_LINK(__asan_dso_reg_hook)
 
 // }}}
diff --git a/compiler-rt/lib/asan/asan_win_common_runtime_thunk.cpp b/compiler-rt/lib/asan/asan_win_common_runtime_thunk.cpp
index f49296f624360..553c2d93efe0b 100644
--- a/compiler-rt/lib/asan/asan_win_common_runtime_thunk.cpp
+++ b/compiler-rt/lib/asan/asan_win_common_runtime_thunk.cpp
@@ -105,6 +105,7 @@ extern "C" IN_SECTION(".CRT$XCAB") int (*__asan_seh_interceptor)() =
 WIN_FORCE_LINK(__asan_seh_interceptor)
 }
 
+extern "C" void (*const __asan_dso_reg_hook)();
 WIN_FORCE_LINK(__asan_dso_reg_hook)
 
 #endif  // defined(SANITIZER_DYNAMIC_RUNTIME_THUNK) ||
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_win_defs.h b/compiler-rt/lib/sanitizer_common/sanitizer_win_defs.h
index 7f36f3ae743c3..ca4918720da95 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_win_defs.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_win_defs.h
@@ -71,12 +71,20 @@
   __pragma(comment(linker, "/alternatename:" WIN_SYM_PREFIX STRINGIFY(Name) "="\
                                              WIN_SYM_PREFIX STRINGIFY(Default)))
 
-#define WIN_FORCE_LINK(Name)                                                   \
-  __pragma(comment(linker, "/include:" WIN_SYM_PREFIX STRINGIFY(Name)))
-
-#define WIN_EXPORT(ExportedName, Name)                                         \
-  __pragma(comment(linker, "/export:" WIN_EXPORT_PREFIX STRINGIFY(ExportedName)\
-                                  "=" WIN_EXPORT_PREFIX STRINGIFY(Name)))
+#    if !defined(__GNUC__) || defined(__clang__)
+#      define WIN_FORCE_LINK(Name) \
+        __pragma(comment(linker, "/include:" WIN_SYM_PREFIX STRINGIFY(Name)))
+#    else
+#      define WIN_FORCE_LINK(Name)                                           \
+        extern "C" __typeof__(Name) Name;                                    \
+        static __attribute__((used)) __typeof__(&Name) __force_link_##Name = \
+            &Name;
+#    endif
+
+#    define WIN_EXPORT(ExportedName, Name)                \
+      __pragma(comment(                                   \
+          linker, "/export:" WIN_EXPORT_PREFIX STRINGIFY( \
+                      ExportedName) "=" WIN_EXPORT_PREFIX STRINGIFY(Name)))
 
 // We cannot define weak functions on Windows, but we can use WIN_WEAK_ALIAS()
 // which defines an alias to a default implementation, and only works when
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_win_thunk_interception.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_win_thunk_interception.cpp
index d9cf6ac0a76af..794f61fd34418 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_win_thunk_interception.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_win_thunk_interception.cpp
@@ -91,6 +91,7 @@ extern "C" int __sanitizer_thunk_init() {
 #  pragma section(".CRT$XIB", long, read)
 extern "C" IN_SECTION(".CRT$XIB") int (*__sanitizer_thunk_init_ptr)() =
     __sanitizer_thunk_init;
+WIN_FORCE_LINK(__sanitizer_thunk_init_ptr)
 
 static void WINAPI sanitizer_thunk_thread_init(void *mod, unsigned long reason,
                                                void *reserved) {
@@ -102,5 +103,6 @@ static void WINAPI sanitizer_thunk_thread_init(void *mod, unsigned long reason,
 extern "C" IN_SECTION(".CRT$XLAB") void(
     WINAPI* __sanitizer_thunk_thread_init_ptr)(void*, unsigned long, void*) =
     sanitizer_thunk_thread_init;
+WIN_FORCE_LINK(__sanitizer_thunk_thread_init_ptr)
 #endif  // defined(SANITIZER_STATIC_RUNTIME_THUNK) ||
         // defined(SANITIZER_DYNAMIC_RUNTIME_THUNK)



More information about the llvm-commits mailing list