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$XCAB", 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. 47extern "C" { 48__declspec(dllimport) int __asan_should_detect_stack_use_after_return(); 49int __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. 62extern "C" int __cdecl atexit(void (__cdecl *f)(void)); 63extern "C" void __cdecl _initterm(void *a, void *b); 64 65namespace { 66__declspec(allocate(".CRT$XTW")) void* before_global_dtors = 0; 67__declspec(allocate(".CRT$XTY")) void* after_global_dtors = 0; 68 69void UnregisterGlobals() { 70 _initterm(&before_global_dtors, &after_global_dtors); 71} 72 73int 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")) 82int (*__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). 90extern "C" { 91__declspec(dllimport) int __asan_set_seh_filter(); 92static 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$XCAB")) int (*__asan_seh_interceptor)() = 97 SetSEHFilter; 98} 99 100#endif // ASAN_DYNAMIC_RUNTIME_THUNK 101