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#include <windows.h> 28 29// First, declare CRT sections we'll be using in this file 30#pragma section(".CRT$XID", long, read) // NOLINT 31#pragma section(".CRT$XIZ", long, read) // NOLINT 32#pragma section(".CRT$XTW", long, read) // NOLINT 33#pragma section(".CRT$XTY", long, read) // NOLINT 34 35//////////////////////////////////////////////////////////////////////////////// 36// Define a copy of __asan_option_detect_stack_use_after_return that should be 37// used when linking an MD runtime with a set of object files on Windows. 38// 39// The ASan MD runtime dllexports '__asan_option_detect_stack_use_after_return', 40// so normally we would just dllimport it. Unfortunately, the dllimport 41// attribute adds __imp_ prefix to the symbol name of a variable. 42// Since in general we don't know if a given TU is going to be used 43// with a MT or MD runtime and we don't want to use ugly __imp_ names on Windows 44// just to work around this issue, let's clone the a variable that is 45// constant after initialization anyways. 46extern "C" { 47__declspec(dllimport) int __asan_should_detect_stack_use_after_return(); 48int __asan_option_detect_stack_use_after_return = 49 __asan_should_detect_stack_use_after_return(); 50} 51 52//////////////////////////////////////////////////////////////////////////////// 53// For some reason, the MD CRT doesn't call the C/C++ terminators during on DLL 54// unload or on exit. ASan relies on LLVM global_dtors to call 55// __asan_unregister_globals on these events, which unfortunately doesn't work 56// with the MD runtime, see PR22545 for the details. 57// To work around this, for each DLL we schedule a call to UnregisterGlobals 58// using atexit() that calls a small subset of C terminators 59// where LLVM global_dtors is placed. Fingers crossed, no other C terminators 60// are there. 61extern "C" void __cdecl _initterm(void *a, void *b); 62 63namespace { 64__declspec(allocate(".CRT$XTW")) void* before_global_dtors = 0; 65__declspec(allocate(".CRT$XTY")) void* after_global_dtors = 0; 66 67void UnregisterGlobals() { 68 _initterm(&before_global_dtors, &after_global_dtors); 69} 70 71int ScheduleUnregisterGlobals() { 72 return atexit(UnregisterGlobals); 73} 74 75// We need to call 'atexit(UnregisterGlobals);' as early as possible, but after 76// atexit() is initialized (.CRT$XIC). As this is executed before C++ 77// initializers (think ctors for globals), UnregisterGlobals gets executed after 78// dtors for C++ globals. 79__declspec(allocate(".CRT$XID")) 80int (*__asan_schedule_unregister_globals)() = ScheduleUnregisterGlobals; 81 82} // namespace 83 84//////////////////////////////////////////////////////////////////////////////// 85// ASan SEH handling. 86// We need to set the ASan-specific SEH handler at the end of CRT initialization 87// of each module (see also asan_win.cc). 88extern "C" { 89__declspec(dllimport) int __asan_set_seh_filter(); 90static int SetSEHFilter() { return __asan_set_seh_filter(); } 91 92// Unfortunately, putting a pointer to __asan_set_seh_filter into 93// __asan_intercept_seh gets optimized out, so we have to use an extra function. 94__declspec(allocate(".CRT$XIZ")) int (*__asan_seh_interceptor)() = SetSEHFilter; 95} 96 97#endif // ASAN_DYNAMIC_RUNTIME_THUNK 98