[sanitizer] [asan] Use macros to simplify weak aliases on Windows.

This patch adds some useful macros for dealing with pragma directives on
Windows. Also, I add appropriate documentation for future users.

Differential Revision: https://reviews.llvm.org/D28525

llvm-svn: 292650
This commit is contained in:
Marcos Pividori 2017-01-20 21:09:36 +00:00
parent 68af279533
commit 74694b19e0
7 changed files with 77 additions and 70 deletions

View File

@ -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

View File

@ -19,7 +19,6 @@
#include <stdlib.h>
#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 @@ uptr __asan_get_shadow_memory_dynamic_address() {
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 @@ __declspec(allocate(".CRT$XLAB")) void (NTAPI *__asan_tls_init)(void *,
unsigned long, void *) = asan_thread_init;
#endif
ASAN_LINK_GLOBALS_WIN()
WIN_FORCE_LINK(__asan_dso_reg_hook)
// }}}
} // namespace __asan

View File

@ -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
@ -478,6 +478,6 @@ static void WINAPI asan_thread_init(void *mod, unsigned long reason,
__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

View File

@ -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 <windows.h>
@ -122,6 +122,6 @@ __declspec(allocate(".CRT$XCAB")) int (*__asan_seh_interceptor)() =
SetSEHFilter;
}
ASAN_LINK_GLOBALS_WIN()
WIN_FORCE_LINK(__asan_dso_reg_hook)
#endif // ASAN_DYNAMIC_RUNTIME_THUNK

View File

@ -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 @@ void GetMemoryProfile(fill_profile_f cb, uptr *stats, uptr stats_size) { }
// 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

View File

@ -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

View File

@ -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 @@ const char *__ubsan_default_options() { return ""; }
#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"