Index: lib/asan/asan_globals_win.h =================================================================== --- lib/asan/asan_globals_win.h +++ lib/asan/asan_globals_win.h @@ -16,19 +16,9 @@ #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 +#include "sanitizer_common/sanitizer_win_defs.h" // 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")) +#define ASAN_LINK_GLOBALS_WIN() WIN_FORCE_LINK(__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 @@ -44,31 +44,18 @@ 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 ---------------- {{{ 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,52 @@ +//===-- 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 + +#if !defined(_MSC_VER) +#error "this file is Windows-only, and uses MSVC pragmas" +#endif + +#if defined(_WIN64) +#define WIN_SYM_PREFIX +#else +#define WIN_SYM_PREFIX "_" +#endif + +// ----------------- 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 #Name "=" \ + WIN_SYM_PREFIX #Default)) + +#define WIN_FORCE_LINK(Name) \ + __pragma(comment(linker, "/include:" WIN_SYM_PREFIX #Name)) + +#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"