1 //===-- asan_win_dynamic_runtime_thunk.cpp --------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file is a part of AddressSanitizer, an address sanity checker. 10 // 11 // This file defines things that need to be present for application modules 12 // that are dynamic linked with the C Runtime. 13 // 14 //===----------------------------------------------------------------------===// 15 16 #ifdef SANITIZER_DYNAMIC_RUNTIME_THUNK 17 # define WIN32_LEAN_AND_MEAN 18 # include <windows.h> 19 20 # include "asan_win_common_runtime_thunk.h" 21 # include "sanitizer_common/sanitizer_win_defs.h" 22 23 //////////////////////////////////////////////////////////////////////////////// 24 // For some reason, the MD CRT doesn't call the C/C++ terminators during on DLL 25 // unload or on exit. ASan relies on LLVM global_dtors to call 26 // __asan_unregister_globals on these events, which unfortunately doesn't work 27 // with the MD runtime, see PR22545 for the details. 28 // To work around this, for each DLL we schedule a call to UnregisterGlobals 29 // using atexit() that calls a small subset of C terminators 30 // where LLVM global_dtors is placed. Fingers crossed, no other C terminators 31 // are there. 32 extern "C" int __cdecl atexit(void(__cdecl *f)(void)); 33 extern "C" void __cdecl _initterm(void *a, void *b); 34 35 namespace { 36 __declspec(allocate(".CRT$XTW")) void *before_global_dtors = 0; 37 __declspec(allocate(".CRT$XTY")) void *after_global_dtors = 0; 38 39 void UnregisterGlobals() { 40 _initterm(&before_global_dtors, &after_global_dtors); 41 } 42 43 int ScheduleUnregisterGlobals() { return atexit(UnregisterGlobals); } 44 } // namespace 45 46 // We need to call 'atexit(UnregisterGlobals);' as early as possible, but after 47 // atexit() is initialized (.CRT$XIC). As this is executed before C++ 48 // initializers (think ctors for globals), UnregisterGlobals gets executed after 49 // dtors for C++ globals. 50 extern "C" __declspec(allocate(".CRT$XID")) int ( 51 *__asan_schedule_unregister_globals)() = ScheduleUnregisterGlobals; 52 WIN_FORCE_LINK(__asan_schedule_unregister_globals) 53 54 #endif // SANITIZER_DYNAMIC_RUNTIME_THUNK 55