Index: lib/asan/CMakeLists.txt =================================================================== --- lib/asan/CMakeLists.txt +++ lib/asan/CMakeLists.txt @@ -76,7 +76,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.cc CFLAGS ${ASAN_DYNAMIC_CFLAGS} DEFS ${ASAN_DYNAMIC_DEFINITIONS}) Index: lib/asan/asan_win_coverage.cc =================================================================== --- /dev/null +++ lib/asan/asan_win_coverage.cc @@ -0,0 +1,125 @@ +//===-- asan_win_coverage.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 file defines a family of thunks that should be statically linked into +// the Asan library in order to delegate the calls 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; + +// We need to intercept some functions from Sanitizer Coverage in order to +// delegate the calls to the implementation in the main executable when +// non-defult implementation is provided. + +// 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 overrideWhenPossible(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(); +} + +// Use macro+template magic to automatically generate the list of hooks. +// Each hook at line LINE defines a template class with a static +// FunctionInterceptor::Execute() method intercepting the hook. +// The default implementation of FunctionInterceptor is to call +// the Execute() method corresponding to the previous line. +template +struct FunctionInterceptor { + static void Execute() { FunctionInterceptor::Execute(); } +}; + +// There shouldn't be any hooks with negative definition line number. +template<> +struct FunctionInterceptor<0> { + static void Execute() {} +}; + +#define INTERCEPT_WHEN_POSSIBLE(dll_function, real_function) \ + template <> struct FunctionInterceptor<__LINE__> { \ + static void Execute() { \ + overrideWhenPossible((uptr)dll_function, real_function); \ + FunctionInterceptor<__LINE__ - 1>::Execute(); \ + } \ + }; + +// Implementation provided by users includes the suffix "_impl". +#define COVERAGE_WEAK_FUNCTION(name) \ + INTERCEPT_WHEN_POSSIBLE(name, #name "_impl") + +// INTERCEPT_HOOKS must be used after the last INTERCEPT_WHEN_POSSIBLE. +#define INTERCEPT_HOOKS FunctionInterceptor<__LINE__>::Execute + +static void InterceptHooks(); +// }}} + +// -------------- Sanitizer Coverage weak interface functions ------------------ + +COVERAGE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp) +COVERAGE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp1) +COVERAGE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp2) +COVERAGE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp4) +COVERAGE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp8) +COVERAGE_WEAK_FUNCTION(__sanitizer_cov_trace_switch) +COVERAGE_WEAK_FUNCTION(__sanitizer_cov_trace_div4) +COVERAGE_WEAK_FUNCTION(__sanitizer_cov_trace_div8) +COVERAGE_WEAK_FUNCTION(__sanitizer_cov_trace_gep) +COVERAGE_WEAK_FUNCTION(__sanitizer_cov_trace_pc_indir) +COVERAGE_WEAK_FUNCTION(__sanitizer_cov_trace_pc_guard) +COVERAGE_WEAK_FUNCTION(__sanitizer_cov_trace_pc_guard_init) + +// Must be after all the interceptor declarations due to the way INTERCEPT_HOOKS +// is defined. +void InterceptHooks() { + INTERCEPT_HOOKS(); +} + +static int coverage_init() { + InterceptHooks(); + // 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 Index: lib/sanitizer_common/sanitizer_coverage_libcdep.cc =================================================================== --- lib/sanitizer_common/sanitizer_coverage_libcdep.cc +++ lib/sanitizer_common/sanitizer_coverage_libcdep.cc @@ -1016,8 +1016,8 @@ uptr __sanitizer_update_counter_bitset_and_clear_counters(u8 *bitset) { return coverage_data.Update8bitCounterBitsetAndClearCounters(bitset); } + // Default empty implementations (weak). Users should redefine them. -#if !SANITIZER_WINDOWS // weak does not work on Windows. SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void __sanitizer_cov_trace_cmp() {} SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE @@ -1038,5 +1038,5 @@ void __sanitizer_cov_trace_gep() {} SANITIZER_INTERFACE_ATTRIBUTE SANITIZER_WEAK_ATTRIBUTE void __sanitizer_cov_trace_pc_indir() {} -#endif // !SANITIZER_WINDOWS + } // extern "C" Index: lib/sanitizer_common/sanitizer_interface_internal.h =================================================================== --- lib/sanitizer_common/sanitizer_interface_internal.h +++ lib/sanitizer_common/sanitizer_interface_internal.h @@ -69,6 +69,32 @@ int __sanitizer_get_module_and_offset_for_pc( __sanitizer::uptr pc, char *module_path, __sanitizer::uptr module_path_len, __sanitizer::uptr *pc_offset); - } // extern "C" + + SANITIZER_INTERFACE_ATTRIBUTE + void __sanitizer_cov_trace_cmp(); + SANITIZER_INTERFACE_ATTRIBUTE + void __sanitizer_cov_trace_cmp1(); + SANITIZER_INTERFACE_ATTRIBUTE + void __sanitizer_cov_trace_cmp2(); + SANITIZER_INTERFACE_ATTRIBUTE + void __sanitizer_cov_trace_cmp4(); + SANITIZER_INTERFACE_ATTRIBUTE + void __sanitizer_cov_trace_cmp8(); + SANITIZER_INTERFACE_ATTRIBUTE + void __sanitizer_cov_trace_switch(); + SANITIZER_INTERFACE_ATTRIBUTE + void __sanitizer_cov_trace_div4(); + SANITIZER_INTERFACE_ATTRIBUTE + void __sanitizer_cov_trace_div8(); + SANITIZER_INTERFACE_ATTRIBUTE + void __sanitizer_cov_trace_gep(); + SANITIZER_INTERFACE_ATTRIBUTE + void __sanitizer_cov_trace_pc_indir(); + SANITIZER_INTERFACE_ATTRIBUTE + void __sanitizer_cov_trace_pc_guard(__sanitizer::u32* guard); + SANITIZER_INTERFACE_ATTRIBUTE + void __sanitizer_cov_trace_pc_guard_init(__sanitizer::u32* start, __sanitizer::u32* end); + +} // extern "C" #endif // SANITIZER_INTERFACE_INTERNAL_H