Index: lib/asan/CMakeLists.txt =================================================================== --- lib/asan/CMakeLists.txt +++ lib/asan/CMakeLists.txt @@ -77,7 +77,7 @@ add_compiler_rt_object_libraries(RTAsan_dynamic OS ${SANITIZER_COMMON_SUPPORTED_OS} ARCHS ${ASAN_SUPPORTED_ARCH} - SOURCES ${ASAN_SOURCES} ${ASAN_CXX_SOURCES} + SOURCES ${ASAN_SOURCES} ${ASAN_CXX_SOURCES} asan_win_coverage_interception.cc CFLAGS ${ASAN_DYNAMIC_CFLAGS} DEFS ${ASAN_DYNAMIC_DEFINITIONS}) Index: lib/asan/asan_win_coverage_interception.cc =================================================================== --- /dev/null +++ lib/asan/asan_win_coverage_interception.cc @@ -0,0 +1,84 @@ +//===-- asan_win_coverage_interception.cc ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This file is a part of Sanitizer Coverage for Windows. +// +// This module should be statically linked to the Asan dll library in order to +// delegate the calls of weak functions to the implementation in the main +// executable when possible. (Based on: asan_win_dll_thunk.cc) +//===----------------------------------------------------------------------===// + +#ifdef _WIN32 +#include "interception/interception.h" +#include "sanitizer_common/sanitizer_platform_interceptors.h" +#include "sanitizer_common/sanitizer_interface_internal.h" + +#ifdef _M_IX86 +#define WINAPI __stdcall +#else +#define WINAPI +#endif + +// Interception helper functions and macros. +extern "C" { +void *WINAPI GetModuleHandleA(const char *module_name); +void *WINAPI GetProcAddress(void *module, const char *proc_name); +void abort(); +} + +using __sanitizer::uptr; +using __sanitizer::u32; + +// Try to get a pointer to real_function in the main module and override +// dll_function with that pointer. If the function isn't found, nothing changes. +static void interceptWhenPossible(uptr dll_function, const char *real_function){ + uptr real = __interception::InternalGetProcAddress( + (void *)GetModuleHandleA(0), real_function); + if (real && !__interception::OverrideFunction((uptr)dll_function, real, 0)) + abort(); +} + +// Override default functions with implementation provided by users. +#define INTERCEPT_WEAK(Name) \ + interceptWhenPossible((uptr) WEAK_DEF_NAME(Name), #Name); + +static int coverage_init() { + // We need to intercept weak functions from Sanitizer Coverage in order to + // delegate the calls to the implementation in the main executable when + // non-defult implementations are provided. + INTERCEPT_WEAK(__sanitizer_cov_trace_cmp) + INTERCEPT_WEAK(__sanitizer_cov_trace_cmp1) + INTERCEPT_WEAK(__sanitizer_cov_trace_cmp2) + INTERCEPT_WEAK(__sanitizer_cov_trace_cmp4) + INTERCEPT_WEAK(__sanitizer_cov_trace_cmp8) + INTERCEPT_WEAK(__sanitizer_cov_trace_switch) + INTERCEPT_WEAK(__sanitizer_cov_trace_div4) + INTERCEPT_WEAK(__sanitizer_cov_trace_div8) + INTERCEPT_WEAK(__sanitizer_cov_trace_gep) + INTERCEPT_WEAK(__sanitizer_cov_trace_pc_indir) + INTERCEPT_WEAK(__sanitizer_cov_trace_pc_guard) + INTERCEPT_WEAK(__sanitizer_cov_trace_pc_guard_init) + // In DLLs, the callbacks are expected to return 0, + // otherwise CRT initialization fails. + return 0; +} + +#pragma section(".CRT$XIB", long, read) // NOLINT +__declspec(allocate(".CRT$XIB")) int (*__coverage_preinit)() = coverage_init; + +static void WINAPI coverage_thread_init(void *mod, unsigned long reason, + void *reserved) { + if (reason == /*DLL_PROCESS_ATTACH=*/1) coverage_init(); +} + +#pragma section(".CRT$XLAB", long, read) // NOLINT +__declspec(allocate(".CRT$XLAB")) void (WINAPI *__coverage_tls_init)(void *, + unsigned long, void *) = coverage_thread_init; + +#endif // _WIN32