1 //===-- asan_win_uar_thunk.cc ---------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file is a part of AddressSanitizer, an address sanity checker. 11 // 12 // This file defines things that need to be present in the application modules 13 // to interact with the ASan DLL runtime correctly and can't be implemented 14 // using the default "import library" generated when linking the DLL RTL. 15 // 16 // This includes: 17 // - forwarding the detect_stack_use_after_return runtime option 18 // - working around deficiencies of the MD runtime 19 // - installing a custom SEH handlerx 20 // 21 //===----------------------------------------------------------------------===// 22 23 // Only compile this code when buidling asan_dynamic_runtime_thunk.lib 24 // Using #ifdef rather than relying on Makefiles etc. 25 // simplifies the build procedure. 26 #ifdef ASAN_DYNAMIC_RUNTIME_THUNK 27 #define WIN32_LEAN_AND_MEAN 28 #include <windows.h> 29 30 // First, declare CRT sections we'll be using in this file 31 #pragma section(".CRT$XID", long, read) // NOLINT 32 #pragma section(".CRT$XIZ", long, read) // NOLINT 33 #pragma section(".CRT$XTW", long, read) // NOLINT 34 #pragma section(".CRT$XTY", long, read) // NOLINT 35 36 //////////////////////////////////////////////////////////////////////////////// 37 // Define a copy of __asan_option_detect_stack_use_after_return that should be 38 // used when linking an MD runtime with a set of object files on Windows. 39 // 40 // The ASan MD runtime dllexports '__asan_option_detect_stack_use_after_return', 41 // so normally we would just dllimport it. Unfortunately, the dllimport 42 // attribute adds __imp_ prefix to the symbol name of a variable. 43 // Since in general we don't know if a given TU is going to be used 44 // with a MT or MD runtime and we don't want to use ugly __imp_ names on Windows 45 // just to work around this issue, let's clone the a variable that is 46 // constant after initialization anyways. 47 extern "C" { 48 __declspec(dllimport) int __asan_should_detect_stack_use_after_return(); 49 int __asan_option_detect_stack_use_after_return = 50 __asan_should_detect_stack_use_after_return(); 51 } 52 53 //////////////////////////////////////////////////////////////////////////////// 54 // For some reason, the MD CRT doesn't call the C/C++ terminators during on DLL 55 // unload or on exit. ASan relies on LLVM global_dtors to call 56 // __asan_unregister_globals on these events, which unfortunately doesn't work 57 // with the MD runtime, see PR22545 for the details. 58 // To work around this, for each DLL we schedule a call to UnregisterGlobals 59 // using atexit() that calls a small subset of C terminators 60 // where LLVM global_dtors is placed. Fingers crossed, no other C terminators 61 // are there. 62 extern "C" int __cdecl atexit(void (__cdecl *f)(void)); 63 extern "C" void __cdecl _initterm(void *a, void *b); 64 65 namespace { 66 __declspec(allocate(".CRT$XTW")) void* before_global_dtors = 0; 67 __declspec(allocate(".CRT$XTY")) void* after_global_dtors = 0; 68 69 void UnregisterGlobals() { 70 _initterm(&before_global_dtors, &after_global_dtors); 71 } 72 73 int ScheduleUnregisterGlobals() { 74 return atexit(UnregisterGlobals); 75 } 76 77 // We need to call 'atexit(UnregisterGlobals);' as early as possible, but after 78 // atexit() is initialized (.CRT$XIC). As this is executed before C++ 79 // initializers (think ctors for globals), UnregisterGlobals gets executed after 80 // dtors for C++ globals. 81 __declspec(allocate(".CRT$XID")) 82 int (*__asan_schedule_unregister_globals)() = ScheduleUnregisterGlobals; 83 84 } // namespace 85 86 //////////////////////////////////////////////////////////////////////////////// 87 // ASan SEH handling. 88 // We need to set the ASan-specific SEH handler at the end of CRT initialization 89 // of each module (see also asan_win.cc). 90 extern "C" { 91 __declspec(dllimport) int __asan_set_seh_filter(); 92 static int SetSEHFilter() { return __asan_set_seh_filter(); } 93 94 // Unfortunately, putting a pointer to __asan_set_seh_filter into 95 // __asan_intercept_seh gets optimized out, so we have to use an extra function. 96 __declspec(allocate(".CRT$XIZ")) int (*__asan_seh_interceptor)() = SetSEHFilter; 97 } 98 99 #endif // ASAN_DYNAMIC_RUNTIME_THUNK 100