Index: compiler-rt/trunk/lib/asan/CMakeLists.txt =================================================================== --- compiler-rt/trunk/lib/asan/CMakeLists.txt +++ compiler-rt/trunk/lib/asan/CMakeLists.txt @@ -176,6 +176,21 @@ set(VERSION_SCRIPT_FLAG) endif() + set(ASAN_DYNAMIC_WEAK_INTERCEPTION) + if (MSVC) + add_compiler_rt_object_libraries(AsanWeakInterception + ${SANITIZER_COMMON_SUPPORTED_OS} + ARCHS ${ASAN_SUPPORTED_ARCH} + SOURCES asan_win_weak_interception.cc + CFLAGS ${ASAN_CFLAGS} -DSANITIZER_DYNAMIC + DEFS ${ASAN_COMMON_DEFINITIONS}) + set(ASAN_DYNAMIC_WEAK_INTERCEPTION + AsanWeakInterception + UbsanWeakInterception + SancovWeakInterception + SanitizerCommonWeakInterception) + endif() + add_compiler_rt_runtime(clang_rt.asan SHARED ARCHS ${arch} @@ -187,6 +202,7 @@ # add_dependencies(clang_rt.asan-dynamic-${arch} clang_rt.asan-dynamic-${arch}-version-list) RTAsan_dynamic_version_script_dummy RTUbsan_cxx + ${ASAN_DYNAMIC_WEAK_INTERCEPTION} CFLAGS ${ASAN_DYNAMIC_CFLAGS} LINK_FLAGS ${ASAN_DYNAMIC_LINK_FLAGS} ${VERSION_SCRIPT_FLAG} Index: compiler-rt/trunk/lib/asan/asan_win_weak_interception.cc =================================================================== --- compiler-rt/trunk/lib/asan/asan_win_weak_interception.cc +++ compiler-rt/trunk/lib/asan/asan_win_weak_interception.cc @@ -0,0 +1,23 @@ +//===-- asan_win_weak_interception.cc -------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// This module should be included in Address Sanitizer when it is implemented as +// a shared library on Windows (dll), in order to delegate the calls of weak +// functions to the implementation in the main executable when a strong +// definition is provided. +//===----------------------------------------------------------------------===// +#ifdef SANITIZER_DYNAMIC +#include "sanitizer_common/sanitizer_win_weak_interception.h" +#include "asan_interface_internal.h" +// Check if strong definitions for weak functions are present in the main +// executable. If that is the case, override dll functions to point to strong +// implementations. +#define INTERFACE_FUNCTION(Name) +#define INTERFACE_WEAK_FUNCTION(Name) INTERCEPT_SANITIZER_WEAK_FUNCTION(Name) +#include "asan_interface.inc" +#endif // SANITIZER_DYNAMIC Index: compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt =================================================================== --- compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt +++ compiler-rt/trunk/lib/sanitizer_common/CMakeLists.txt @@ -188,6 +188,19 @@ DEFS ${SANITIZER_COMMON_DEFINITIONS}) if(MSVC) + add_compiler_rt_object_libraries(SanitizerCommonWeakInterception + ${SANITIZER_COMMON_SUPPORTED_OS} + ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH} + SOURCES sanitizer_win_weak_interception.cc + CFLAGS ${SANITIZER_CFLAGS} -DSANITIZER_DYNAMIC + DEFS ${SANITIZER_COMMON_DEFINITIONS}) + add_compiler_rt_object_libraries(SancovWeakInterception + ${SANITIZER_COMMON_SUPPORTED_OS} + ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH} + SOURCES sanitizer_coverage_win_weak_interception.cc + CFLAGS ${SANITIZER_CFLAGS} -DSANITIZER_DYNAMIC + DEFS ${SANITIZER_COMMON_DEFINITIONS}) + add_compiler_rt_object_libraries(SanitizerCommonDllThunk ${SANITIZER_COMMON_SUPPORTED_OS} ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH} Index: compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_win_weak_interception.cc =================================================================== --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_win_weak_interception.cc +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_coverage_win_weak_interception.cc @@ -0,0 +1,24 @@ +//===-- sanitizer_coverage_win_weak_interception.cc -----------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// This module should be included in Sanitizer Coverage when it implemented as a +// shared library on Windows (dll), in order to delegate the calls of weak +// functions to the implementation in the main executable when a strong +// definition is provided. +//===----------------------------------------------------------------------===// +#ifdef SANITIZER_DYNAMIC +#include "sanitizer_win_weak_interception.h" +#include "sanitizer_interface_internal.h" +#include "sancov_flags.h" +// Check if strong definitions for weak functions are present in the main +// executable. If that is the case, override dll functions to point to strong +// implementations. +#define INTERFACE_FUNCTION(Name) +#define INTERFACE_WEAK_FUNCTION(Name) INTERCEPT_SANITIZER_WEAK_FUNCTION(Name) +#include "sanitizer_coverage_interface.inc" +#endif // SANITIZER_DYNAMIC Index: compiler-rt/trunk/lib/sanitizer_common/sanitizer_win_weak_interception.h =================================================================== --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_win_weak_interception.h +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_win_weak_interception.h @@ -0,0 +1,33 @@ +//===-- sanitizer_win_weak_interception.h ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// This header provide helper macros to delegate calls of weak functions to the +// implementation in the main executable when a strong definition is present. +//===----------------------------------------------------------------------===// +#ifndef SANITIZER_WIN_WEAK_INTERCEPTION_H +#define SANITIZER_WIN_WEAK_INTERCEPTION_H +#include "sanitizer_internal_defs.h" + +namespace __sanitizer { +int interceptWhenPossible(uptr dll_function, const char *real_function); +} + +// ----------------- Function interception helper macros -------------------- // +// Weak functions, could be redefined in the main executable, but that is not +// necessary, so we shouldn't die if we can not find a reference. +#define INTERCEPT_WEAK(Name) interceptWhenPossible((uptr) Name, #Name); + +#define INTERCEPT_SANITIZER_WEAK_FUNCTION(Name) \ + static int intercept_##Name() { \ + return __sanitizer::interceptWhenPossible((__sanitizer::uptr) Name, #Name);\ + } \ + __pragma(section(".WEAK$M", long, read)) \ + __declspec(allocate(".WEAK$M")) int (*__weak_intercept_##Name)() = \ + intercept_##Name; + +#endif // SANITIZER_WIN_WEAK_INTERCEPTION_H Index: compiler-rt/trunk/lib/sanitizer_common/sanitizer_win_weak_interception.cc =================================================================== --- compiler-rt/trunk/lib/sanitizer_common/sanitizer_win_weak_interception.cc +++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_win_weak_interception.cc @@ -0,0 +1,82 @@ +//===-- sanitizer_win_weak_interception.cc --------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// This module should be included in the sanitizer when it is implemented as a +// shared library on Windows (dll), in order to delegate the calls of weak +// functions to the implementation in the main executable when a strong +// definition is provided. +//===----------------------------------------------------------------------===// + +#include "sanitizer_common/sanitizer_platform.h" +#if SANITIZER_WINDOWS && SANITIZER_DYNAMIC +#include "sanitizer_win_weak_interception.h" +#include "sanitizer_allocator_interface.h" +#include "sanitizer_interface_internal.h" +#include "sanitizer_win_defs.h" +#include "interception/interception.h" + +extern "C" { +void *WINAPI GetModuleHandleA(const char *module_name); +void abort(); +} + +namespace __sanitizer { +// 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. +int 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(); + return 0; +} +} // namespace __sanitizer + +// Include Sanitizer Common interface. +#define INTERFACE_FUNCTION(Name) +#define INTERFACE_WEAK_FUNCTION(Name) INTERCEPT_SANITIZER_WEAK_FUNCTION(Name) +#include "sanitizer_common_interface.inc" + +#pragma section(".WEAK$A", read) // NOLINT +#pragma section(".WEAK$Z", read) // NOLINT + +typedef void (*InterceptCB)(); +extern "C" { +__declspec(allocate(".WEAK$A")) InterceptCB __start_weak_list; +__declspec(allocate(".WEAK$Z")) InterceptCB __stop_weak_list; +} + +static int weak_intercept_init() { + static bool flag = false; + // weak_interception_init is expected to be called by only one thread. + if (flag) return 0; + flag = true; + + for (InterceptCB *it = &__start_weak_list; it < &__stop_weak_list; ++it) + if (*it) + (*it)(); + + // 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 (*__weak_intercept_preinit)() = + weak_intercept_init; + +static void WINAPI weak_intercept_thread_init(void *mod, unsigned long reason, + void *reserved) { + if (reason == /*DLL_PROCESS_ATTACH=*/1) weak_intercept_init(); +} + +#pragma section(".CRT$XLAB", long, read) // NOLINT +__declspec(allocate(".CRT$XLAB")) void(WINAPI *__weak_intercept_tls_init)( + void *, unsigned long, void *) = weak_intercept_thread_init; + +#endif // SANITIZER_WINDOWS && SANITIZER_DYNAMIC Index: compiler-rt/trunk/lib/ubsan/CMakeLists.txt =================================================================== --- compiler-rt/trunk/lib/ubsan/CMakeLists.txt +++ compiler-rt/trunk/lib/ubsan/CMakeLists.txt @@ -91,6 +91,13 @@ SOURCES ${UBSAN_CXX_SOURCES} CFLAGS ${UBSAN_CXXFLAGS}) if (WIN32) + add_compiler_rt_object_libraries(UbsanWeakInterception + ${SANITIZER_COMMON_SUPPORTED_OS} + ARCHS ${UBSAN_SUPPORTED_ARCH} + SOURCES ubsan_win_weak_interception.cc + CFLAGS ${UBSAN_CFLAGS} -DSANITIZER_DYNAMIC + DEFS ${UBSAN_COMMON_DEFINITIONS}) + add_compiler_rt_object_libraries(UbsanDllThunk ${SANITIZER_COMMON_SUPPORTED_OS} ARCHS ${UBSAN_SUPPORTED_ARCH} Index: compiler-rt/trunk/lib/ubsan/ubsan_win_weak_interception.cc =================================================================== --- compiler-rt/trunk/lib/ubsan/ubsan_win_weak_interception.cc +++ compiler-rt/trunk/lib/ubsan/ubsan_win_weak_interception.cc @@ -0,0 +1,23 @@ +//===-- ubsan_win_weak_interception.cc ------------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// This module should be included in Ubsan when it is implemented as a shared +// library on Windows (dll), in order to delegate the calls of weak functions to +// the implementation in the main executable when a strong definition is +// provided. +//===----------------------------------------------------------------------===// +#ifdef SANITIZER_DYNAMIC +#include "sanitizer_common/sanitizer_win_weak_interception.h" +#include "ubsan_flags.h" +// Check if strong definitions for weak functions are present in the main +// executable. If that is the case, override dll functions to point to strong +// implementations. +#define INTERFACE_FUNCTION(Name) +#define INTERFACE_WEAK_FUNCTION(Name) INTERCEPT_SANITIZER_WEAK_FUNCTION(Name) +#include "ubsan_interface.inc" +#endif // SANITIZER_DYNAMIC