Index: lib/asan/asan_globals_win.h =================================================================== --- lib/asan/asan_globals_win.h +++ /dev/null @@ -1,34 +0,0 @@ -//===-- asan_globals_win.h --------------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// -// -// Interface to the Windows-specific global management code. Separated into a -// standalone header to allow inclusion from asan_win_dynamic_runtime_thunk, -// which defines symbols that clash with other sanitizer headers. -// -//===----------------------------------------------------------------------===// - -#ifndef ASAN_GLOBALS_WIN_H -#define ASAN_GLOBALS_WIN_H - -#if !defined(_MSC_VER) -#error "this file is Windows-only, and uses MSVC pragmas" -#endif - -#if defined(_WIN64) -#define SANITIZER_SYM_PREFIX -#else -#define SANITIZER_SYM_PREFIX "_" -#endif - -// Use this macro to force linking asan_globals_win.cc into the DSO. -#define ASAN_LINK_GLOBALS_WIN() \ - __pragma( \ - comment(linker, "/include:" SANITIZER_SYM_PREFIX "__asan_dso_reg_hook")) - -#endif // ASAN_GLOBALS_WIN_H Index: lib/asan/asan_win.cc =================================================================== --- lib/asan/asan_win.cc +++ lib/asan/asan_win.cc @@ -19,7 +19,6 @@ #include -#include "asan_globals_win.h" #include "asan_interceptors.h" #include "asan_internal.h" #include "asan_report.h" @@ -28,6 +27,7 @@ #include "asan_mapping.h" #include "sanitizer_common/sanitizer_libc.h" #include "sanitizer_common/sanitizer_mutex.h" +#include "sanitizer_common/sanitizer_win_defs.h" using namespace __asan; // NOLINT @@ -44,31 +44,17 @@ return __asan_shadow_memory_dynamic_address; } -// -------------------- A workaround for the absence of weak symbols ----- {{{ -// We don't have a direct equivalent of weak symbols when using MSVC, but we can -// use the /alternatename directive to tell the linker to default a specific -// symbol to a specific value, which works nicely for allocator hooks and -// __asan_default_options(). void __sanitizer_default_malloc_hook(void *ptr, uptr size) { } void __sanitizer_default_free_hook(void *ptr) { } const char* __asan_default_default_options() { return ""; } const char* __asan_default_default_suppressions() { return ""; } void __asan_default_on_error() {} -// 64-bit msvc will not prepend an underscore for symbols. -#ifdef _WIN64 -#pragma comment(linker, "/alternatename:__sanitizer_malloc_hook=__sanitizer_default_malloc_hook") // NOLINT -#pragma comment(linker, "/alternatename:__sanitizer_free_hook=__sanitizer_default_free_hook") // NOLINT -#pragma comment(linker, "/alternatename:__asan_default_options=__asan_default_default_options") // NOLINT -#pragma comment(linker, "/alternatename:__asan_default_suppressions=__asan_default_default_suppressions") // NOLINT -#pragma comment(linker, "/alternatename:__asan_on_error=__asan_default_on_error") // NOLINT -#else -#pragma comment(linker, "/alternatename:___sanitizer_malloc_hook=___sanitizer_default_malloc_hook") // NOLINT -#pragma comment(linker, "/alternatename:___sanitizer_free_hook=___sanitizer_default_free_hook") // NOLINT -#pragma comment(linker, "/alternatename:___asan_default_options=___asan_default_default_options") // NOLINT -#pragma comment(linker, "/alternatename:___asan_default_suppressions=___asan_default_default_suppressions") // NOLINT -#pragma comment(linker, "/alternatename:___asan_on_error=___asan_default_on_error") // NOLINT -#endif -// }}} + +WIN_WEAK_ALIAS(__sanitizer_malloc_hook, __sanitizer_default_malloc_hook) +WIN_WEAK_ALIAS(__sanitizer_free_hook, __sanitizer_default_free_hook) +WIN_WEAK_ALIAS(__asan_default_options, __asan_default_default_options) +WIN_WEAK_ALIAS(__asan_default_suppressions, __asan_default_default_suppressions) +WIN_WEAK_ALIAS(__asan_on_error, __asan_default_on_error) } // extern "C" // ---------------------- Windows-specific interceptors ---------------- {{{ @@ -368,7 +354,7 @@ unsigned long, void *) = asan_thread_init; #endif -ASAN_LINK_GLOBALS_WIN() +WIN_FORCE_LINK(__asan_dso_reg_hook) // }}} } // namespace __asan Index: lib/asan/asan_win_dll_thunk.cc =================================================================== --- lib/asan/asan_win_dll_thunk.cc +++ lib/asan/asan_win_dll_thunk.cc @@ -20,9 +20,9 @@ // simplifies the build procedure. #ifdef ASAN_DLL_THUNK #include "asan_init_version.h" -#include "asan_globals_win.h" #include "interception/interception.h" #include "sanitizer_common/sanitizer_platform_interceptors.h" +#include "sanitizer_common/sanitizer_win_defs.h" #ifdef _M_IX86 #define WINAPI __stdcall @@ -488,6 +488,6 @@ __declspec(allocate(".CRT$XLAB")) void (WINAPI *__asan_tls_init)(void *, unsigned long, void *) = asan_thread_init; -ASAN_LINK_GLOBALS_WIN() +WIN_FORCE_LINK(__asan_dso_reg_hook) #endif // ASAN_DLL_THUNK Index: lib/asan/asan_win_dynamic_runtime_thunk.cc =================================================================== --- lib/asan/asan_win_dynamic_runtime_thunk.cc +++ lib/asan/asan_win_dynamic_runtime_thunk.cc @@ -24,7 +24,7 @@ // Using #ifdef rather than relying on Makefiles etc. // simplifies the build procedure. #ifdef ASAN_DYNAMIC_RUNTIME_THUNK -#include "asan_globals_win.h" +#include "sanitizer_common/sanitizer_win_defs.h" #define WIN32_LEAN_AND_MEAN #include @@ -122,6 +122,6 @@ SetSEHFilter; } -ASAN_LINK_GLOBALS_WIN() +WIN_FORCE_LINK(__asan_dso_reg_hook) #endif // ASAN_DYNAMIC_RUNTIME_THUNK Index: lib/sanitizer_common/sanitizer_win.cc =================================================================== --- lib/sanitizer_common/sanitizer_win.cc +++ lib/sanitizer_common/sanitizer_win.cc @@ -30,6 +30,7 @@ #include "sanitizer_procmaps.h" #include "sanitizer_stacktrace.h" #include "sanitizer_symbolizer.h" +#include "sanitizer_win_defs.h" // A macro to tell the compiler that this part of the code cannot be reached, // if the compiler supports this feature. Since we're using this in @@ -946,11 +947,8 @@ // of null. extern "C" void __sanitizer_print_memory_profile(int top_percent) {} -#ifdef _WIN64 -#pragma comment(linker, "/alternatename:__sanitizer_print_memory_profile=__sanitizer_default_print_memory_profile") // NOLINT -#else -#pragma comment(linker, "/alternatename:___sanitizer_print_memory_profile=___sanitizer_default_print_memory_profile") // NOLINT -#endif +WIN_WEAK_ALIAS(__sanitizer_print_memory_profile, + __sanitizer_default_print_memory_profile) #endif #endif // _WIN32 Index: lib/sanitizer_common/sanitizer_win_defs.h =================================================================== --- /dev/null +++ lib/sanitizer_common/sanitizer_win_defs.h @@ -0,0 +1,59 @@ +//===-- sanitizer_win_defs.h ------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// Common definitions for Windows-specific code. +// +//===----------------------------------------------------------------------===// +#ifndef SANITIZER_WIN_DEFS_H +#define SANITIZER_WIN_DEFS_H + +#include "sanitizer_platform.h" +#if SANITIZER_WINDOWS + +#if defined(_WIN64) +#define WIN_SYM_PREFIX +#else +#define WIN_SYM_PREFIX "_" +#endif + +// Intermediate macro to ensure the parameter is expanded before stringified. +#define STRINGIFY(A) #A + +// ----------------- A workaround for the absence of weak symbols -------------- +// We don't have a direct equivalent of weak symbols when using MSVC, but we can +// use the /alternatename directive to tell the linker to default a specific +// symbol to a specific value. +// Take into account that the function will be marked as UNDEF in the symbol +// table of the resulting object file, even if we provided a default value, and +// the linker won't find the default implementation until it links with that +// object file. +// So, suppose we provide a default implementation "fundef" for "fun", and this +// is compiled into the object file "test.obj". +// If we have some code with references to "fun" and we link that code with +// "test.obj", it will work because the linker always link object files. +// But, if "test.obj" is included in a static library, like "test.lib", then the +// liker will only link to "test.obj" if necessary. If we only included the +// definition of "fun", it won't link to "test.obj" (from test.lib) because +// "fun" appears as UNDEF, so it doesn't resolve the symbol "fun", and this will +// result in a link error. +// So, a workaround is to force linkage with the modules that include weak +// definitions, with the following macro: WIN_FORCE_LINK() + +#define WIN_WEAK_ALIAS_(Name, Default) \ + __pragma(comment(linker, "/alternatename:" WIN_SYM_PREFIX STRINGIFY(Name) "=" \ + WIN_SYM_PREFIX STRINGIFY(Default))) + +#define WIN_WEAK_ALIAS(Name, Default) \ + WIN_WEAK_ALIAS_(Name, Default) + +#define WIN_FORCE_LINK(Name) \ + __pragma(comment(linker, "/include:" WIN_SYM_PREFIX STRINGIFY(Name))) + +#endif // SANITIZER_WINDOWS +#endif // SANITIZER_WIN_DEFS_H Index: lib/ubsan/ubsan_flags.cc =================================================================== --- lib/ubsan/ubsan_flags.cc +++ lib/ubsan/ubsan_flags.cc @@ -17,6 +17,7 @@ #include "sanitizer_common/sanitizer_common.h" #include "sanitizer_common/sanitizer_flags.h" #include "sanitizer_common/sanitizer_flag_parser.h" +#include "sanitizer_common/sanitizer_win_defs.h" namespace __ubsan { @@ -76,11 +77,8 @@ #if SANITIZER_WINDOWS const char *__ubsan_default_default_options() { return ""; } -# ifdef _WIN64 -# pragma comment(linker, "/alternatename:__ubsan_default_options=__ubsan_default_default_options") -# else -# pragma comment(linker, "/alternatename:___ubsan_default_options=___ubsan_default_default_options") -# endif + +WIN_WEAK_ALIAS(__ubsan_default_options, __ubsan_default_default_options) #endif } // extern "C"