diff options
author | Charlie Barto <chbarto@microsoft.com> | 2024-05-29 17:52:54 -0700 |
---|---|---|
committer | Charlie Barto <chbarto@microsoft.com> | 2024-05-29 17:52:54 -0700 |
commit | 10436aede261db5260e0e11a4aa66565ba975848 (patch) | |
tree | 07757ddd669d72b65ba2d4c0becbce20ba06bab5 /compiler-rt | |
parent | ce2927a396c506cbf06ea39eff8f226fd8d46b94 (diff) | |
download | llvm-10436aede261db5260e0e11a4aa66565ba975848.zip llvm-10436aede261db5260e0e11a4aa66565ba975848.tar.gz llvm-10436aede261db5260e0e11a4aa66565ba975848.tar.bz2 |
Revert "[asan][windows] Eliminate the static asan runtime on windows (#81677)"
This reverts commit 246234ac70faa1e3281a2bb83dfc4dd206a7d59c.
Diffstat (limited to 'compiler-rt')
53 files changed, 1044 insertions, 1262 deletions
diff --git a/compiler-rt/CMakeLists.txt b/compiler-rt/CMakeLists.txt index 158fa27..6ce451e 100644 --- a/compiler-rt/CMakeLists.txt +++ b/compiler-rt/CMakeLists.txt @@ -378,12 +378,8 @@ if("${COMPILER_RT_DEFAULT_TARGET_ARCH}" MATCHES "s390x") endif() if(MSVC) - - # asan on windows only supports the release dll version of the runtimes, in the interest of - # only having one asan dll to support/test. Having asan statically linked - # with the runtime might be possible, but it multiplies the number of scenerios to test. - # the program USING sanitizers can use whatever version of the runtime it wants to. - set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreadedDLL) + # FIXME: In fact, sanitizers should support both /MT and /MD, see PR20214. + set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreaded) # Remove any /M[DT][d] flags, and strip any definitions of _DEBUG. # Since we're using CMAKE_MSVC_RUNTIME_LIBRARY (CMP0091 set to NEW), diff --git a/compiler-rt/lib/asan/CMakeLists.txt b/compiler-rt/lib/asan/CMakeLists.txt index f992419..463ea23 100644 --- a/compiler-rt/lib/asan/CMakeLists.txt +++ b/compiler-rt/lib/asan/CMakeLists.txt @@ -32,20 +32,6 @@ set(ASAN_SOURCES asan_win.cpp ) -if(WIN32) - set(ASAN_DYNAMIC_RUNTIME_THUNK_SOURCES - asan_globals_win.cpp - asan_win_common_runtime_thunk.cpp - asan_win_dynamic_runtime_thunk.cpp - ) - set(ASAN_STATIC_RUNTIME_THUNK_SOURCES - asan_globals_win.cpp - asan_malloc_win_thunk.cpp - asan_win_common_runtime_thunk.cpp - asan_win_static_runtime_thunk.cpp - ) -endif() - if (NOT WIN32 AND NOT APPLE) list(APPEND ASAN_SOURCES asan_interceptors_vfork.S @@ -150,7 +136,7 @@ append_list_if(MINGW "${MINGW_LIBRARIES}" ASAN_DYNAMIC_LIBS) add_compiler_rt_object_libraries(RTAsan_dynamic OS ${SANITIZER_COMMON_SUPPORTED_OS} ARCHS ${ASAN_SUPPORTED_ARCH} - SOURCES ${ASAN_SOURCES} + SOURCES ${ASAN_SOURCES} ${ASAN_CXX_SOURCES} ADDITIONAL_HEADERS ${ASAN_HEADERS} CFLAGS ${ASAN_DYNAMIC_CFLAGS} DEFS ${ASAN_DYNAMIC_DEFINITIONS}) @@ -235,52 +221,46 @@ else() RTSanitizerCommonSymbolizerInternal RTLSanCommon RTUbsan) - if (NOT WIN32) - add_compiler_rt_runtime(clang_rt.asan - STATIC - ARCHS ${ASAN_SUPPORTED_ARCH} - OBJECT_LIBS RTAsan_preinit - RTAsan - ${ASAN_COMMON_RUNTIME_OBJECT_LIBS} - CFLAGS ${ASAN_CFLAGS} - DEFS ${ASAN_COMMON_DEFINITIONS} - PARENT_TARGET asan) - add_compiler_rt_runtime(clang_rt.asan_cxx - STATIC - ARCHS ${ASAN_SUPPORTED_ARCH} - OBJECT_LIBS RTAsan_cxx - RTUbsan_cxx - CFLAGS ${ASAN_CFLAGS} - DEFS ${ASAN_COMMON_DEFINITIONS} - PARENT_TARGET asan) + add_compiler_rt_runtime(clang_rt.asan + STATIC + ARCHS ${ASAN_SUPPORTED_ARCH} + OBJECT_LIBS RTAsan_preinit + RTAsan + ${ASAN_COMMON_RUNTIME_OBJECT_LIBS} + CFLAGS ${ASAN_CFLAGS} + DEFS ${ASAN_COMMON_DEFINITIONS} + PARENT_TARGET asan) - add_compiler_rt_runtime(clang_rt.asan_static - STATIC - ARCHS ${ASAN_SUPPORTED_ARCH} - OBJECT_LIBS RTAsan_static - CFLAGS ${ASAN_CFLAGS} - DEFS ${ASAN_COMMON_DEFINITIONS} - PARENT_TARGET asan) + add_compiler_rt_runtime(clang_rt.asan_cxx + STATIC + ARCHS ${ASAN_SUPPORTED_ARCH} + OBJECT_LIBS RTAsan_cxx + RTUbsan_cxx + CFLAGS ${ASAN_CFLAGS} + DEFS ${ASAN_COMMON_DEFINITIONS} + PARENT_TARGET asan) - add_compiler_rt_runtime(clang_rt.asan-preinit - STATIC - ARCHS ${ASAN_SUPPORTED_ARCH} - OBJECT_LIBS RTAsan_preinit - CFLAGS ${ASAN_CFLAGS} - DEFS ${ASAN_COMMON_DEFINITIONS} - PARENT_TARGET asan) - endif() + add_compiler_rt_runtime(clang_rt.asan_static + STATIC + ARCHS ${ASAN_SUPPORTED_ARCH} + OBJECT_LIBS RTAsan_static + CFLAGS ${ASAN_CFLAGS} + DEFS ${ASAN_COMMON_DEFINITIONS} + PARENT_TARGET asan) + + add_compiler_rt_runtime(clang_rt.asan-preinit + STATIC + ARCHS ${ASAN_SUPPORTED_ARCH} + OBJECT_LIBS RTAsan_preinit + CFLAGS ${ASAN_CFLAGS} + DEFS ${ASAN_COMMON_DEFINITIONS} + PARENT_TARGET asan) foreach(arch ${ASAN_SUPPORTED_ARCH}) if (COMPILER_RT_HAS_VERSION_SCRIPT) - if(WIN32) - set(SANITIZER_RT_VERSION_LIST_LIBS clang_rt.asan-${arch}) - else() - set(SANITIZER_RT_VERSION_LIST_LIBS clang_rt.asan-${arch} clang_rt.asan_cxx-${arch}) - endif() add_sanitizer_rt_version_list(clang_rt.asan-dynamic-${arch} - LIBS ${SANITIZER_RT_VERSION_LIST_LIBS} + LIBS clang_rt.asan-${arch} clang_rt.asan_cxx-${arch} EXTRA asan.syms.extra) set(VERSION_SCRIPT_FLAG -Wl,--version-script,${CMAKE_CURRENT_BINARY_DIR}/clang_rt.asan-dynamic-${arch}.vers) @@ -298,11 +278,25 @@ else() endif() set(ASAN_DYNAMIC_WEAK_INTERCEPTION) + if (WIN32) + add_compiler_rt_object_libraries(AsanWeakInterception + ${SANITIZER_COMMON_SUPPORTED_OS} + ARCHS ${arch} + SOURCES + asan_win_weak_interception.cpp + 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} OBJECT_LIBS ${ASAN_COMMON_RUNTIME_OBJECT_LIBS} - RTAsan_cxx RTAsan_dynamic # The only purpose of RTAsan_dynamic_version_script_dummy is to # carry a dependency of the shared runtime on the version script. @@ -330,12 +324,36 @@ else() endif() if (WIN32) + add_compiler_rt_object_libraries(AsanDllThunk + ${SANITIZER_COMMON_SUPPORTED_OS} + ARCHS ${arch} + SOURCES asan_globals_win.cpp + asan_win_dll_thunk.cpp + CFLAGS ${ASAN_CFLAGS} -DSANITIZER_DLL_THUNK + DEFS ${ASAN_COMMON_DEFINITIONS}) + + add_compiler_rt_runtime(clang_rt.asan_dll_thunk + STATIC + ARCHS ${arch} + OBJECT_LIBS AsanDllThunk + UbsanDllThunk + SancovDllThunk + SanitizerCommonDllThunk + SOURCES $<TARGET_OBJECTS:RTInterception.${arch}> + PARENT_TARGET asan) + set(DYNAMIC_RUNTIME_THUNK_CFLAGS "-DSANITIZER_DYNAMIC_RUNTIME_THUNK") + if(MSVC) + list(APPEND DYNAMIC_RUNTIME_THUNK_CFLAGS "-Zl") + elseif(CMAKE_C_COMPILER_ID MATCHES Clang) + list(APPEND DYNAMIC_RUNTIME_THUNK_CFLAGS "-nodefaultlibs") + endif() add_compiler_rt_object_libraries(AsanDynamicRuntimeThunk ${SANITIZER_COMMON_SUPPORTED_OS} ARCHS ${arch} - SOURCES ${ASAN_DYNAMIC_RUNTIME_THUNK_SOURCES} + SOURCES asan_globals_win.cpp + asan_win_dynamic_runtime_thunk.cpp CFLAGS ${ASAN_CFLAGS} ${DYNAMIC_RUNTIME_THUNK_CFLAGS} DEFS ${ASAN_COMMON_DEFINITIONS}) @@ -343,35 +361,12 @@ else() STATIC ARCHS ${arch} OBJECT_LIBS AsanDynamicRuntimeThunk - UbsanRuntimeThunk - SancovRuntimeThunk - SanitizerRuntimeThunk + UbsanDynamicRuntimeThunk + SancovDynamicRuntimeThunk + SanitizerCommonDynamicRuntimeThunk CFLAGS ${ASAN_CFLAGS} ${DYNAMIC_RUNTIME_THUNK_CFLAGS} DEFS ${ASAN_COMMON_DEFINITIONS} PARENT_TARGET asan) - - # mingw does not support static linkage of the CRT - if(NOT MINGW) - set(STATIC_RUNTIME_THUNK_CFLAGS "-DSANITIZER_STATIC_RUNTIME_THUNK") - - add_compiler_rt_object_libraries(AsanStaticRuntimeThunk - ${SANITIZER_COMMON_SUPPORTED_OS} - ARCHS ${arch} - SOURCES ${ASAN_STATIC_RUNTIME_THUNK_SOURCES} - CFLAGS ${ASAN_DYNAMIC_CFLAGS} ${STATIC_RUNTIME_THUNK_CFLAGS} - DEFS ${ASAN_DYNAMIC_DEFINITIONS}) - - add_compiler_rt_runtime(clang_rt.asan_static_runtime_thunk - STATIC - ARCHS ${arch} - OBJECT_LIBS AsanStaticRuntimeThunk - UbsanRuntimeThunk - SancovRuntimeThunk - SanitizerRuntimeThunk - CFLAGS ${ASAN_DYNAMIC_CFLAGS} ${STATIC_RUNTIME_THUNK_CFLAGS} - DEFS ${ASAN_DYNAMIC_DEFINITIONS} - PARENT_TARGET asan) - endif() endif() endforeach() endif() diff --git a/compiler-rt/lib/asan/asan_flags.cpp b/compiler-rt/lib/asan/asan_flags.cpp index 56deb1b..2398984 100644 --- a/compiler-rt/lib/asan/asan_flags.cpp +++ b/compiler-rt/lib/asan/asan_flags.cpp @@ -11,16 +11,14 @@ // ASan flag parsing logic. //===----------------------------------------------------------------------===// -#include "asan_flags.h" - #include "asan_activation.h" +#include "asan_flags.h" #include "asan_interface_internal.h" #include "asan_stack.h" #include "lsan/lsan_common.h" #include "sanitizer_common/sanitizer_common.h" -#include "sanitizer_common/sanitizer_flag_parser.h" #include "sanitizer_common/sanitizer_flags.h" -#include "sanitizer_common/sanitizer_win_interception.h" +#include "sanitizer_common/sanitizer_flag_parser.h" #include "ubsan/ubsan_flags.h" #include "ubsan/ubsan_platform.h" @@ -49,21 +47,7 @@ static void RegisterAsanFlags(FlagParser *parser, Flags *f) { #undef ASAN_FLAG } -static void DisplayHelpMessages(FlagParser *parser) { - // TODO(eugenis): dump all flags at verbosity>=2? - if (Verbosity()) { - ReportUnrecognizedFlags(); - } - - if (common_flags()->help) { - parser->PrintFlagDescriptions(); - } -} - -static void InitializeDefaultFlags() { - Flags *f = flags(); - FlagParser asan_parser; - +void InitializeFlags() { // Set the default values and prepare for parsing ASan and common flags. SetCommonFlagsDefaults(); { @@ -76,8 +60,10 @@ static void InitializeDefaultFlags() { cf.exitcode = 1; OverrideCommonFlags(cf); } + Flags *f = flags(); f->SetDefaults(); + FlagParser asan_parser; RegisterAsanFlags(&asan_parser, f); RegisterCommonFlags(&asan_parser); @@ -140,12 +126,13 @@ static void InitializeDefaultFlags() { InitializeCommonFlags(); - // TODO(samsonov): print all of the flags (ASan, LSan, common). - DisplayHelpMessages(&asan_parser); -} + // TODO(eugenis): dump all flags at verbosity>=2? + if (Verbosity()) ReportUnrecognizedFlags(); -static void ProcessFlags() { - Flags *f = flags(); + if (common_flags()->help) { + // TODO(samsonov): print all of the flags (ASan, LSan, common). + asan_parser.PrintFlagDescriptions(); + } // Flag validation: if (!CAN_SANITIZE_LEAKS && common_flags()->detect_leaks) { @@ -212,67 +199,6 @@ static void ProcessFlags() { } } -void InitializeFlags() { - InitializeDefaultFlags(); - ProcessFlags(); - -#if SANITIZER_WINDOWS - // On Windows, weak symbols are emulated by having the user program - // register which weak functions are defined. - // The ASAN DLL will initialize flags prior to user module initialization, - // so __asan_default_options will not point to the user definition yet. - // We still want to ensure we capture when options are passed via - // __asan_default_options, so we add a callback to be run - // when it is registered with the runtime. - - // There is theoretically time between the initial ProcessFlags and - // registering the weak callback where a weak function could be added and we - // would miss it, but in practice, InitializeFlags will always happen under - // the loader lock (if built as a DLL) and so will any calls to - // __sanitizer_register_weak_function. - AddRegisterWeakFunctionCallback( - reinterpret_cast<uptr>(__asan_default_options), []() { - FlagParser asan_parser; - - RegisterAsanFlags(&asan_parser, flags()); - RegisterCommonFlags(&asan_parser); - asan_parser.ParseString(__asan_default_options()); - - DisplayHelpMessages(&asan_parser); - ProcessFlags(); - }); - -# if CAN_SANITIZE_UB - AddRegisterWeakFunctionCallback( - reinterpret_cast<uptr>(__ubsan_default_options), []() { - FlagParser ubsan_parser; - - __ubsan::RegisterUbsanFlags(&ubsan_parser, __ubsan::flags()); - RegisterCommonFlags(&ubsan_parser); - ubsan_parser.ParseString(__ubsan_default_options()); - - // To match normal behavior, do not print UBSan help. - ProcessFlags(); - }); -# endif - -# if CAN_SANITIZE_LEAKS - AddRegisterWeakFunctionCallback( - reinterpret_cast<uptr>(__lsan_default_options), []() { - FlagParser lsan_parser; - - __lsan::RegisterLsanFlags(&lsan_parser, __lsan::flags()); - RegisterCommonFlags(&lsan_parser); - lsan_parser.ParseString(__lsan_default_options()); - - // To match normal behavior, do not print LSan help. - ProcessFlags(); - }); -# endif - -#endif -} - } // namespace __asan SANITIZER_INTERFACE_WEAK_DEF(const char*, __asan_default_options, void) { diff --git a/compiler-rt/lib/asan/asan_globals_win.cpp b/compiler-rt/lib/asan/asan_globals_win.cpp index 8267f07..19af88a 100644 --- a/compiler-rt/lib/asan/asan_globals_win.cpp +++ b/compiler-rt/lib/asan/asan_globals_win.cpp @@ -28,9 +28,7 @@ static void call_on_globals(void (*hook)(__asan_global *, uptr)) { __asan_global *end = &__asan_globals_end; uptr bytediff = (uptr)end - (uptr)start; if (bytediff % sizeof(__asan_global) != 0) { -# if defined(SANITIZER_DLL_THUNK) || \ - defined(SANITIZER_DYNAMIC_RUNTIME_THUNK) || \ - defined(SANITIZER_STATIC_RUNTIME_THUNK) +#if defined(SANITIZER_DLL_THUNK) || defined(SANITIZER_DYNAMIC_RUNTIME_THUNK) __debugbreak(); #else CHECK("corrupt asan global array"); diff --git a/compiler-rt/lib/asan/asan_malloc_win.cpp b/compiler-rt/lib/asan/asan_malloc_win.cpp index 3278f07..7e1d04c 100644 --- a/compiler-rt/lib/asan/asan_malloc_win.cpp +++ b/compiler-rt/lib/asan/asan_malloc_win.cpp @@ -58,69 +58,97 @@ using namespace __asan; // MD: Memory allocation functions are defined in the CRT .dll, // so we have to intercept them before they are called for the first time. +#if ASAN_DYNAMIC +# define ALLOCATION_FUNCTION_ATTRIBUTE +#else +# define ALLOCATION_FUNCTION_ATTRIBUTE SANITIZER_INTERFACE_ATTRIBUTE +#endif + extern "C" { -__declspec(noinline) size_t _msize(void *ptr) { +ALLOCATION_FUNCTION_ATTRIBUTE +size_t _msize(void *ptr) { GET_CURRENT_PC_BP_SP; (void)sp; return asan_malloc_usable_size(ptr, pc, bp); } -__declspec(noinline) size_t _msize_base(void *ptr) { return _msize(ptr); } +ALLOCATION_FUNCTION_ATTRIBUTE +size_t _msize_base(void *ptr) { + return _msize(ptr); +} -__declspec(noinline) void free(void *ptr) { +ALLOCATION_FUNCTION_ATTRIBUTE +void free(void *ptr) { GET_STACK_TRACE_FREE; return asan_free(ptr, &stack, FROM_MALLOC); } -__declspec(noinline) void _free_dbg(void *ptr, int) { free(ptr); } +ALLOCATION_FUNCTION_ATTRIBUTE +void _free_dbg(void *ptr, int) { + free(ptr); +} -__declspec(noinline) void _free_base(void *ptr) { free(ptr); } +ALLOCATION_FUNCTION_ATTRIBUTE +void _free_base(void *ptr) { + free(ptr); +} -__declspec(noinline) void *malloc(size_t size) { +ALLOCATION_FUNCTION_ATTRIBUTE +void *malloc(size_t size) { GET_STACK_TRACE_MALLOC; return asan_malloc(size, &stack); } -__declspec(noinline) void *_malloc_base(size_t size) { return malloc(size); } +ALLOCATION_FUNCTION_ATTRIBUTE +void *_malloc_base(size_t size) { + return malloc(size); +} -__declspec(noinline) void *_malloc_dbg(size_t size, int, const char *, int) { +ALLOCATION_FUNCTION_ATTRIBUTE +void *_malloc_dbg(size_t size, int, const char *, int) { return malloc(size); } -__declspec(noinline) void *calloc(size_t nmemb, size_t size) { +ALLOCATION_FUNCTION_ATTRIBUTE +void *calloc(size_t nmemb, size_t size) { GET_STACK_TRACE_MALLOC; return asan_calloc(nmemb, size, &stack); } -__declspec(noinline) void *_calloc_base(size_t nmemb, size_t size) { +ALLOCATION_FUNCTION_ATTRIBUTE +void *_calloc_base(size_t nmemb, size_t size) { return calloc(nmemb, size); } -__declspec(noinline) void *_calloc_dbg(size_t nmemb, size_t size, int, - const char *, int) { +ALLOCATION_FUNCTION_ATTRIBUTE +void *_calloc_dbg(size_t nmemb, size_t size, int, const char *, int) { return calloc(nmemb, size); } -__declspec(noinline) void *_calloc_impl(size_t nmemb, size_t size, - int *errno_tmp) { +ALLOCATION_FUNCTION_ATTRIBUTE +void *_calloc_impl(size_t nmemb, size_t size, int *errno_tmp) { return calloc(nmemb, size); } -__declspec(noinline) void *realloc(void *ptr, size_t size) { +ALLOCATION_FUNCTION_ATTRIBUTE +void *realloc(void *ptr, size_t size) { GET_STACK_TRACE_MALLOC; return asan_realloc(ptr, size, &stack); } -__declspec(noinline) void *_realloc_dbg(void *ptr, size_t size, int) { +ALLOCATION_FUNCTION_ATTRIBUTE +void *_realloc_dbg(void *ptr, size_t size, int) { UNREACHABLE("_realloc_dbg should not exist!"); return 0; } -__declspec(noinline) void *_realloc_base(void *ptr, size_t size) { +ALLOCATION_FUNCTION_ATTRIBUTE +void *_realloc_base(void *ptr, size_t size) { return realloc(ptr, size); } -__declspec(noinline) void *_recalloc(void *p, size_t n, size_t elem_size) { +ALLOCATION_FUNCTION_ATTRIBUTE +void *_recalloc(void *p, size_t n, size_t elem_size) { if (!p) return calloc(n, elem_size); const size_t size = n * elem_size; @@ -138,41 +166,23 @@ __declspec(noinline) void *_recalloc(void *p, size_t n, size_t elem_size) { return new_alloc; } -__declspec(noinline) void *_recalloc_base(void *p, size_t n, size_t elem_size) { +ALLOCATION_FUNCTION_ATTRIBUTE +void *_recalloc_base(void *p, size_t n, size_t elem_size) { return _recalloc(p, n, elem_size); } -__declspec(noinline) void *_expand(void *memblock, size_t size) { +ALLOCATION_FUNCTION_ATTRIBUTE +void *_expand(void *memblock, size_t size) { // _expand is used in realloc-like functions to resize the buffer if possible. // We don't want memory to stand still while resizing buffers, so return 0. return 0; } -__declspec(noinline) void *_expand_dbg(void *memblock, size_t size) { +ALLOCATION_FUNCTION_ATTRIBUTE +void *_expand_dbg(void *memblock, size_t size) { return _expand(memblock, size); } -__declspec(dllexport) size_t __cdecl __asan_msize(void *ptr) { - return _msize(ptr); -} -__declspec(dllexport) void __cdecl __asan_free(void *const ptr) { free(ptr); } -__declspec(dllexport) void *__cdecl __asan_malloc(const size_t size) { - return malloc(size); -} -__declspec(dllexport) void *__cdecl __asan_calloc(const size_t nmemb, - const size_t size) { - return calloc(nmemb, size); -} -__declspec(dllexport) void *__cdecl __asan_realloc(void *const ptr, - const size_t size) { - return realloc(ptr, size); -} -__declspec(dllexport) void *__cdecl __asan_recalloc(void *const ptr, - const size_t nmemb, - const size_t size) { - return _recalloc(ptr, nmemb, size); -} - // TODO(timurrrr): Might want to add support for _aligned_* allocation // functions to detect a bit more bugs. Those functions seem to wrap malloc(). @@ -477,6 +487,7 @@ static void TryToOverrideFunction(const char *fname, uptr new_func) { } void ReplaceSystemMalloc() { +#if defined(ASAN_DYNAMIC) TryToOverrideFunction("free", (uptr)free); TryToOverrideFunction("_free_base", (uptr)free); TryToOverrideFunction("malloc", (uptr)malloc); @@ -532,6 +543,8 @@ void ReplaceSystemMalloc() { // allocation API will be directed to ASan's heap. We don't currently // intercept all calls to HeapAlloc. If we did, we would have to check on // HeapFree whether the pointer came from ASan of from the system. + +#endif // defined(ASAN_DYNAMIC) } } // namespace __asan diff --git a/compiler-rt/lib/asan/asan_malloc_win_thunk.cpp b/compiler-rt/lib/asan/asan_malloc_win_thunk.cpp deleted file mode 100644 index abf515b..0000000 --- a/compiler-rt/lib/asan/asan_malloc_win_thunk.cpp +++ /dev/null @@ -1,229 +0,0 @@ -//===-- asan_malloc_win_thunk.cpp
-//-----------------------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file is a part of AddressSanitizer, an address sanity checker.
-//
-// Windows-specific malloc interception.
-// This is included statically for projects statically linking
-// with the C Runtime (/MT, /MTd) in order to provide ASAN-aware
-// versions of the C allocation functions.
-//===----------------------------------------------------------------------===//
-
-#ifdef SANITIZER_STATIC_RUNTIME_THUNK
-# include "..\sanitizer_common\sanitizer_allocator_interface.h"
-// #include "asan_win_thunk_common.h"
-
-// Preserve stack traces with noinline.
-# define STATIC_MALLOC_INTERFACE __declspec(noinline)
-
-extern "C" {
-__declspec(dllimport) size_t __cdecl __asan_msize(void *ptr);
-__declspec(dllimport) void __cdecl __asan_free(void *const ptr);
-__declspec(dllimport) void *__cdecl __asan_malloc(const size_t size);
-__declspec(dllimport) void *__cdecl __asan_calloc(const size_t nmemb,
- const size_t size);
-__declspec(dllimport) void *__cdecl __asan_realloc(void *const ptr,
- const size_t size);
-__declspec(dllimport) void *__cdecl __asan_recalloc(void *const ptr,
- const size_t nmemb,
- const size_t size);
-
-// Avoid tailcall optimization to preserve stack frames.
-# pragma optimize("", off)
-
-// _msize
-STATIC_MALLOC_INTERFACE size_t _msize(void *ptr) { return __asan_msize(ptr); }
-
-STATIC_MALLOC_INTERFACE size_t _msize_base(void *ptr) {
- return __asan_msize(ptr);
-}
-
-STATIC_MALLOC_INTERFACE size_t _msize_dbg(void *ptr) {
- return __asan_msize(ptr);
-}
-
-// free
-STATIC_MALLOC_INTERFACE void free(void *const ptr) { return __asan_free(ptr); }
-
-STATIC_MALLOC_INTERFACE void _free_base(void *const ptr) {
- return __asan_free(ptr);
-}
-
-STATIC_MALLOC_INTERFACE void _free_dbg(void *const ptr) {
- return __asan_free(ptr);
-}
-
-// malloc
-STATIC_MALLOC_INTERFACE void *malloc(const size_t size) {
- return __asan_malloc(size);
-}
-
-STATIC_MALLOC_INTERFACE void *_malloc_base(const size_t size) {
- return __asan_malloc(size);
-}
-
-STATIC_MALLOC_INTERFACE void *_malloc_dbg(const size_t size) {
- return __asan_malloc(size);
-}
-
-// calloc
-STATIC_MALLOC_INTERFACE void *calloc(const size_t nmemb, const size_t size) {
- return __asan_calloc(nmemb, size);
-}
-
-STATIC_MALLOC_INTERFACE void *_calloc_base(const size_t nmemb,
- const size_t size) {
- return __asan_calloc(nmemb, size);
-}
-
-STATIC_MALLOC_INTERFACE void *_calloc_impl(const size_t nmemb,
- const size_t size,
- int *const errno_tmp) {
- // Provided by legacy msvcrt.
- (void)errno_tmp;
-
- return __asan_calloc(nmemb, size);
-}
-
-STATIC_MALLOC_INTERFACE void *_calloc_dbg(const size_t nmemb, const size_t size,
- int, const char *, int) {
- return __asan_calloc(nmemb, size);
-}
-
-// realloc
-STATIC_MALLOC_INTERFACE void *realloc(void *const ptr, const size_t size) {
- return __asan_realloc(ptr, size);
-}
-
-STATIC_MALLOC_INTERFACE void *_realloc_base(void *const ptr,
- const size_t size) {
- return __asan_realloc(ptr, size);
-}
-
-STATIC_MALLOC_INTERFACE void *_realloc_dbg(void *const ptr, const size_t size,
- int, const char *, int) {
- return __asan_realloc(ptr, size);
-}
-
-// recalloc
-STATIC_MALLOC_INTERFACE void *_recalloc(void *const ptr, const size_t nmemb,
- const size_t size) {
- return __asan_recalloc(ptr, nmemb, size);
-}
-
-STATIC_MALLOC_INTERFACE void *_recalloc_base(void *const ptr,
- const size_t nmemb,
- const size_t size) {
- return __asan_recalloc(ptr, nmemb, size);
-}
-
-STATIC_MALLOC_INTERFACE void *_recalloc_dbg(void *const ptr, const size_t nmemb,
- const size_t size, int,
- const char *, int) {
- return __asan_recalloc(ptr, nmemb, size);
-}
-
-// expand
-STATIC_MALLOC_INTERFACE void *_expand(void *, size_t) {
- // _expand is used in realloc-like functions to resize the buffer if possible.
- // We don't want memory to stand still while resizing buffers, so return 0.
- return nullptr;
-}
-
-STATIC_MALLOC_INTERFACE void *_expand_dbg(void *, size_t, int, const char *,
- int) {
- return nullptr;
-}
-
-// We need to provide symbols for all the debug CRT functions if we decide to
-// provide any. Most of these functions make no sense under ASan and so we
-// make them no-ops.
-long _CrtSetBreakAlloc(long const) { return ~0; }
-
-void _CrtSetDbgBlockType(void *const, int const) { return; }
-
-typedef int(__cdecl *CRT_ALLOC_HOOK)(int, void *, size_t, int, long,
- const unsigned char *, int);
-
-CRT_ALLOC_HOOK _CrtGetAllocHook() { return nullptr; }
-
-CRT_ALLOC_HOOK _CrtSetAllocHook(CRT_ALLOC_HOOK const hook) { return hook; }
-
-int _CrtCheckMemory() { return 1; }
-
-int _CrtSetDbgFlag(int const new_bits) { return new_bits; }
-
-typedef void (*CrtDoForAllClientObjectsCallback)(void *, void *);
-
-void _CrtDoForAllClientObjects(CrtDoForAllClientObjectsCallback const,
- void *const) {
- return;
-}
-
-int _CrtIsValidPointer(void const *const p, unsigned int const, int const) {
- return p != nullptr;
-}
-
-int _CrtIsValidHeapPointer(void const *const block) {
- if (!block) {
- return 0;
- }
-
- return __sanitizer_get_ownership(block);
-}
-
-int _CrtIsMemoryBlock(void const *const, unsigned const, long *const,
- char **const, int *const) {
- return 0;
-}
-
-int _CrtReportBlockType(void const *const) { return -1; }
-
-typedef void(__cdecl *CRT_DUMP_CLIENT)(void *, size_t);
-
-CRT_DUMP_CLIENT _CrtGetDumpClient() { return nullptr; }
-
-CRT_DUMP_CLIENT _CrtSetDumpClient(CRT_DUMP_CLIENT new_client) {
- return new_client;
-}
-
-void _CrtMemCheckpoint(void *const) { return; }
-
-int _CrtMemDifference(void *const, void const *const, void const *const) {
- return 0;
-}
-
-void _CrtMemDumpAllObjectsSince(void const *const) { return; }
-
-int _CrtDumpMemoryLeaks() { return 0; }
-
-void _CrtMemDumpStatistics(void const *const) { return; }
-
-int _crtDbgFlag{0};
-long _crtBreakAlloc{-1};
-CRT_DUMP_CLIENT _pfnDumpClient{nullptr};
-
-int *__p__crtDbgFlag() { return &_crtDbgFlag; }
-
-long *__p__crtBreakAlloc() { return &_crtBreakAlloc; }
-
-// TODO: These were added upstream but conflict with definitions in ucrtbased.
-// int _CrtDbgReport(int, const char *, int, const char *, const char *, ...) {
-// ShowStatsAndAbort();
-// }
-//
-// int _CrtDbgReportW(int reportType, const wchar_t *, int, const wchar_t *,
-// const wchar_t *, ...) {
-// ShowStatsAndAbort();
-// }
-//
-// int _CrtSetReportMode(int, int) { return 0; }
-
-} // extern "C"
-#endif // SANITIZER_STATIC_RUNTIME_THUNK
diff --git a/compiler-rt/lib/asan/asan_win_common_runtime_thunk.cpp b/compiler-rt/lib/asan/asan_win_common_runtime_thunk.cpp deleted file mode 100644 index d2c9e66..0000000 --- a/compiler-rt/lib/asan/asan_win_common_runtime_thunk.cpp +++ /dev/null @@ -1,112 +0,0 @@ -//===-- asan_win_common_runtime_thunk.cpp --------------------------- -----===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file is a part of AddressSanitizer, an address sanity checker.
-//
-// This file defines things that need to be present in the application modules
-// to interact with the ASan DLL runtime correctly and can't be implemented
-// using the default "import library" generated when linking the DLL.
-//
-// This includes:
-// - Cloning shadow memory dynamic address from ASAN DLL
-// - Creating weak aliases to default implementation imported from asan dll
-// - Forwarding the detect_stack_use_after_return runtime option
-// - installing a custom SEH handler
-//
-//===----------------------------------------------------------------------===//
-
-#if defined(SANITIZER_DYNAMIC_RUNTIME_THUNK) || \
- defined(SANITIZER_STATIC_RUNTIME_THUNK)
-# define SANITIZER_IMPORT_INTERFACE 1
-# define WIN32_LEAN_AND_MEAN
-# include "asan_win_common_runtime_thunk.h"
-
-# include <windows.h>
-
-# include "sanitizer_common/sanitizer_win_defs.h"
-# include "sanitizer_common/sanitizer_win_thunk_interception.h"
-
-// Define weak alias for all weak functions imported from asan dll.
-# define INTERFACE_FUNCTION(Name)
-# define INTERFACE_WEAK_FUNCTION(Name) REGISTER_WEAK_FUNCTION(Name)
-# include "asan_interface.inc"
-
-////////////////////////////////////////////////////////////////////////////////
-// Define a copy of __asan_option_detect_stack_use_after_return that should be
-// used when linking an MD runtime with a set of object files on Windows.
-//
-// The ASan MD runtime dllexports '__asan_option_detect_stack_use_after_return',
-// so normally we would just dllimport it. Unfortunately, the dllimport
-// attribute adds __imp_ prefix to the symbol name of a variable.
-// Since in general we don't know if a given TU is going to be used
-// with a MT or MD runtime and we don't want to use ugly __imp_ names on Windows
-// just to work around this issue, let's clone the variable that is constant
-// after initialization anyways.
-
-extern "C" {
-__declspec(dllimport) int __asan_should_detect_stack_use_after_return();
-int __asan_option_detect_stack_use_after_return;
-
-__declspec(dllimport) void *__asan_get_shadow_memory_dynamic_address();
-void *__asan_shadow_memory_dynamic_address;
-
-static void __asan_initialize_cloned_variables() {
- __asan_option_detect_stack_use_after_return =
- __asan_should_detect_stack_use_after_return();
- __asan_shadow_memory_dynamic_address =
- __asan_get_shadow_memory_dynamic_address();
-}
-}
-
-static int asan_thunk_init() {
- __asan_initialize_cloned_variables();
-
-# ifdef SANITIZER_STATIC_RUNTIME_THUNK
- __asan_initialize_static_thunk();
-# endif
-
- return 0;
-}
-
-static void WINAPI asan_thread_init(void *mod, unsigned long reason,
- void *reserved) {
- if (reason == DLL_PROCESS_ATTACH) {
- asan_thunk_init();
- }
-}
-
-// Our cloned variables must be initialized before C/C++ constructors. If TLS
-// is used, our .CRT$XLAB initializer will run first. If not, our .CRT$XIB
-// initializer is needed as a backup.
-extern "C" __declspec(allocate(".CRT$XIB")) int (*__asan_thunk_init)() =
- asan_thunk_init;
-WIN_FORCE_LINK(__asan_thunk_init);
-
-extern "C" __declspec(allocate(".CRT$XLAB")) void(WINAPI *__asan_tls_init)(
- void *, unsigned long, void *) = asan_thread_init;
-WIN_FORCE_LINK(__asan_tls_init);
-
-////////////////////////////////////////////////////////////////////////////////
-// ASan SEH handling.
-// We need to set the ASan-specific SEH handler at the end of CRT initialization
-// of each module (see also asan_win.cpp).
-extern "C" {
-__declspec(dllimport) int __asan_set_seh_filter();
-static int SetSEHFilter() { return __asan_set_seh_filter(); }
-
-// Unfortunately, putting a pointer to __asan_set_seh_filter into
-// __asan_intercept_seh gets optimized out, so we have to use an extra function.
-extern "C" __declspec(allocate(".CRT$XCAB")) int (*__asan_seh_interceptor)() =
- SetSEHFilter;
-WIN_FORCE_LINK(__asan_seh_interceptor);
-}
-
-WIN_FORCE_LINK(__asan_dso_reg_hook)
-
-#endif // defined(SANITIZER_DYNAMIC_RUNTIME_THUNK) ||
- // defined(SANITIZER_STATIC_RUNTIME_THUNK)
diff --git a/compiler-rt/lib/asan/asan_win_common_runtime_thunk.h b/compiler-rt/lib/asan/asan_win_common_runtime_thunk.h deleted file mode 100644 index 66285eb..0000000 --- a/compiler-rt/lib/asan/asan_win_common_runtime_thunk.h +++ /dev/null @@ -1,38 +0,0 @@ -//===-- asan_win_common_runtime_thunk.h -------------------------*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file is a part of AddressSanitizer, an address sanity checker.
-//
-// This file defines things that need to be present in the application modules
-// to interact with the ASan DLL runtime correctly and can't be implemented
-// using the default "import library" generated when linking the DLL.
-//
-//===----------------------------------------------------------------------===//
-
-#if defined(SANITIZER_STATIC_RUNTIME_THUNK) || \
- defined(SANITIZER_DYNAMIC_RUNTIME_THUNK)
-# include "sanitizer_common/sanitizer_win_defs.h"
-
-# pragma section(".CRT$XIB", long, \
- read) // C initializer (during C init before dyninit)
-# pragma section(".CRT$XID", long, \
- read) // First C initializer after CRT initializers
-# pragma section(".CRT$XCAB", long, \
- read) // First C++ initializer after startup initializers
-
-# pragma section(".CRT$XTW", long, read) // First ASAN globals terminator
-# pragma section(".CRT$XTY", long, read) // Last ASAN globals terminator
-
-# pragma section(".CRT$XLAB", long, read) // First TLS initializer
-
-# ifdef SANITIZER_STATIC_RUNTIME_THUNK
-extern "C" void __asan_initialize_static_thunk();
-# endif
-
-#endif // defined(SANITIZER_STATIC_RUNTIME_THUNK) ||
- // defined(SANITIZER_DYNAMIC_RUNTIME_THUNK)
\ No newline at end of file diff --git a/compiler-rt/lib/asan/asan_win_dll_thunk.cpp b/compiler-rt/lib/asan/asan_win_dll_thunk.cpp new file mode 100644 index 0000000..35871a9 --- /dev/null +++ b/compiler-rt/lib/asan/asan_win_dll_thunk.cpp @@ -0,0 +1,165 @@ +//===-- asan_win_dll_thunk.cpp --------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file is a part of AddressSanitizer, an address sanity checker. +// +// This file defines a family of thunks that should be statically linked into +// the DLLs that have ASan instrumentation in order to delegate the calls to the +// shared runtime that lives in the main binary. +// See https://github.com/google/sanitizers/issues/209 for the details. +//===----------------------------------------------------------------------===// + +#ifdef SANITIZER_DLL_THUNK +#include "asan_init_version.h" +#include "interception/interception.h" +#include "sanitizer_common/sanitizer_win_defs.h" +#include "sanitizer_common/sanitizer_win_dll_thunk.h" +#include "sanitizer_common/sanitizer_platform_interceptors.h" + +// ASan own interface functions. +#define INTERFACE_FUNCTION(Name) INTERCEPT_SANITIZER_FUNCTION(Name) +#define INTERFACE_WEAK_FUNCTION(Name) INTERCEPT_SANITIZER_WEAK_FUNCTION(Name) +#include "asan_interface.inc" + +// Memory allocation functions. +INTERCEPT_WRAP_V_W(free) +INTERCEPT_WRAP_V_W(_free_base) +INTERCEPT_WRAP_V_WW(_free_dbg) + +INTERCEPT_WRAP_W_W(malloc) +INTERCEPT_WRAP_W_W(_malloc_base) +INTERCEPT_WRAP_W_WWWW(_malloc_dbg) + +INTERCEPT_WRAP_W_WW(calloc) +INTERCEPT_WRAP_W_WW(_calloc_base) +INTERCEPT_WRAP_W_WWWWW(_calloc_dbg) +INTERCEPT_WRAP_W_WWW(_calloc_impl) + +INTERCEPT_WRAP_W_WW(realloc) +INTERCEPT_WRAP_W_WW(_realloc_base) +INTERCEPT_WRAP_W_WWW(_realloc_dbg) +INTERCEPT_WRAP_W_WWW(_recalloc) +INTERCEPT_WRAP_W_WWW(_recalloc_base) + +INTERCEPT_WRAP_W_W(_msize) +INTERCEPT_WRAP_W_W(_msize_base) +INTERCEPT_WRAP_W_W(_expand) +INTERCEPT_WRAP_W_W(_expand_dbg) + +// TODO(timurrrr): Might want to add support for _aligned_* allocation +// functions to detect a bit more bugs. Those functions seem to wrap malloc(). + +// TODO(timurrrr): Do we need to add _Crt* stuff here? (see asan_malloc_win.cpp) + +# if defined(_MSC_VER) && !defined(__clang__) +// Disable warnings such as: 'void memchr(void)': incorrect number of arguments +// for intrinsic function, expected '3' arguments. +# pragma warning(push) +# pragma warning(disable : 4392) +# endif + +INTERCEPT_LIBRARY_FUNCTION(atoi); +INTERCEPT_LIBRARY_FUNCTION(atol); +INTERCEPT_LIBRARY_FUNCTION(atoll); +INTERCEPT_LIBRARY_FUNCTION(frexp); +INTERCEPT_LIBRARY_FUNCTION(longjmp); +#if SANITIZER_INTERCEPT_MEMCHR +INTERCEPT_LIBRARY_FUNCTION(memchr); +#endif +INTERCEPT_LIBRARY_FUNCTION(memcmp); +INTERCEPT_LIBRARY_FUNCTION(memcpy); +INTERCEPT_LIBRARY_FUNCTION(memmove); +INTERCEPT_LIBRARY_FUNCTION(memset); +INTERCEPT_LIBRARY_FUNCTION(strcat); +INTERCEPT_LIBRARY_FUNCTION(strchr); +INTERCEPT_LIBRARY_FUNCTION(strcmp); +INTERCEPT_LIBRARY_FUNCTION(strcpy); +INTERCEPT_LIBRARY_FUNCTION(strcspn); +INTERCEPT_LIBRARY_FUNCTION(_strdup); +INTERCEPT_LIBRARY_FUNCTION(strlen); +INTERCEPT_LIBRARY_FUNCTION(strncat); +INTERCEPT_LIBRARY_FUNCTION(strncmp); +INTERCEPT_LIBRARY_FUNCTION(strncpy); +INTERCEPT_LIBRARY_FUNCTION(strnlen); +INTERCEPT_LIBRARY_FUNCTION(strpbrk); +INTERCEPT_LIBRARY_FUNCTION(strrchr); +INTERCEPT_LIBRARY_FUNCTION(strspn); +INTERCEPT_LIBRARY_FUNCTION(strstr); +INTERCEPT_LIBRARY_FUNCTION(strtok); +INTERCEPT_LIBRARY_FUNCTION(strtol); +INTERCEPT_LIBRARY_FUNCTION(strtoll); +INTERCEPT_LIBRARY_FUNCTION(wcslen); +INTERCEPT_LIBRARY_FUNCTION(wcsnlen); + +# if defined(_MSC_VER) && !defined(__clang__) +# pragma warning(pop) +# endif + +#ifdef _WIN64 +INTERCEPT_LIBRARY_FUNCTION(__C_specific_handler); +#else +INTERCEPT_LIBRARY_FUNCTION(_except_handler3); +// _except_handler4 checks -GS cookie which is different for each module, so we +// can't use INTERCEPT_LIBRARY_FUNCTION(_except_handler4). +INTERCEPTOR(int, _except_handler4, void *a, void *b, void *c, void *d) { + __asan_handle_no_return(); + return REAL(_except_handler4)(a, b, c, d); +} +#endif + +// Windows specific functions not included in asan_interface.inc. +INTERCEPT_WRAP_W_V(__asan_should_detect_stack_use_after_return) +INTERCEPT_WRAP_W_V(__asan_get_shadow_memory_dynamic_address) +INTERCEPT_WRAP_W_W(__asan_unhandled_exception_filter) + +using namespace __sanitizer; + +extern "C" { +int __asan_option_detect_stack_use_after_return; +uptr __asan_shadow_memory_dynamic_address; +} // extern "C" + +static int asan_dll_thunk_init() { + typedef void (*fntype)(); + static fntype fn = 0; + // asan_dll_thunk_init is expected to be called by only one thread. + if (fn) return 0; + + // Ensure all interception was executed. + __dll_thunk_init(); + + fn = (fntype) dllThunkGetRealAddrOrDie("__asan_init"); + fn(); + __asan_option_detect_stack_use_after_return = + (__asan_should_detect_stack_use_after_return() != 0); + __asan_shadow_memory_dynamic_address = + (uptr)__asan_get_shadow_memory_dynamic_address(); + +#ifndef _WIN64 + INTERCEPT_FUNCTION(_except_handler4); +#endif + // In DLLs, the callbacks are expected to return 0, + // otherwise CRT initialization fails. + return 0; +} + +#pragma section(".CRT$XIB", long, read) +__declspec(allocate(".CRT$XIB")) int (*__asan_preinit)() = asan_dll_thunk_init; + +static void WINAPI asan_thread_init(void *mod, unsigned long reason, + void *reserved) { + if (reason == /*DLL_PROCESS_ATTACH=*/1) asan_dll_thunk_init(); +} + +#pragma section(".CRT$XLAB", long, read) +__declspec(allocate(".CRT$XLAB")) void (WINAPI *__asan_tls_init)(void *, + unsigned long, void *) = asan_thread_init; + +WIN_FORCE_LINK(__asan_dso_reg_hook) + +#endif // SANITIZER_DLL_THUNK diff --git a/compiler-rt/lib/asan/asan_win_dynamic_runtime_thunk.cpp b/compiler-rt/lib/asan/asan_win_dynamic_runtime_thunk.cpp index 421fe65..f0b5ec9 100644 --- a/compiler-rt/lib/asan/asan_win_dynamic_runtime_thunk.cpp +++ b/compiler-rt/lib/asan/asan_win_dynamic_runtime_thunk.cpp @@ -8,17 +8,76 @@ // // This file is a part of AddressSanitizer, an address sanity checker. // -// This file defines things that need to be present for application modules -// that are dynamic linked with the C Runtime. +// This file defines things that need to be present in the application modules +// to interact with the ASan DLL runtime correctly and can't be implemented +// using the default "import library" generated when linking the DLL RTL. +// +// This includes: +// - creating weak aliases to default implementation imported from asan dll. +// - forwarding the detect_stack_use_after_return runtime option +// - working around deficiencies of the MD runtime +// - installing a custom SEH handler // //===----------------------------------------------------------------------===// #ifdef SANITIZER_DYNAMIC_RUNTIME_THUNK -# define WIN32_LEAN_AND_MEAN -# include <windows.h> +#define SANITIZER_IMPORT_INTERFACE 1 +#include "sanitizer_common/sanitizer_win_defs.h" +#define WIN32_LEAN_AND_MEAN +#include <windows.h> + +// Define weak alias for all weak functions imported from asan dll. +#define INTERFACE_FUNCTION(Name) +#define INTERFACE_WEAK_FUNCTION(Name) WIN_WEAK_IMPORT_DEF(Name) +#include "asan_interface.inc" + +// First, declare CRT sections we'll be using in this file +#pragma section(".CRT$XIB", long, read) +#pragma section(".CRT$XID", long, read) +#pragma section(".CRT$XCAB", long, read) +#pragma section(".CRT$XTW", long, read) +#pragma section(".CRT$XTY", long, read) +#pragma section(".CRT$XLAB", long, read) + +//////////////////////////////////////////////////////////////////////////////// +// Define a copy of __asan_option_detect_stack_use_after_return that should be +// used when linking an MD runtime with a set of object files on Windows. +// +// The ASan MD runtime dllexports '__asan_option_detect_stack_use_after_return', +// so normally we would just dllimport it. Unfortunately, the dllimport +// attribute adds __imp_ prefix to the symbol name of a variable. +// Since in general we don't know if a given TU is going to be used +// with a MT or MD runtime and we don't want to use ugly __imp_ names on Windows +// just to work around this issue, let's clone the variable that is constant +// after initialization anyways. +extern "C" { +__declspec(dllimport) int __asan_should_detect_stack_use_after_return(); +int __asan_option_detect_stack_use_after_return; + +__declspec(dllimport) void* __asan_get_shadow_memory_dynamic_address(); +void* __asan_shadow_memory_dynamic_address; +} + +static int InitializeClonedVariables() { + __asan_option_detect_stack_use_after_return = + __asan_should_detect_stack_use_after_return(); + __asan_shadow_memory_dynamic_address = + __asan_get_shadow_memory_dynamic_address(); + return 0; +} + +static void NTAPI asan_thread_init(void *mod, unsigned long reason, + void *reserved) { + if (reason == DLL_PROCESS_ATTACH) InitializeClonedVariables(); +} -# include "asan_win_common_runtime_thunk.h" -# include "sanitizer_common/sanitizer_win_defs.h" +// Our cloned variables must be initialized before C/C++ constructors. If TLS +// is used, our .CRT$XLAB initializer will run first. If not, our .CRT$XIB +// initializer is needed as a backup. +__declspec(allocate(".CRT$XIB")) int (*__asan_initialize_cloned_variables)() = + InitializeClonedVariables; +__declspec(allocate(".CRT$XLAB")) void (NTAPI *__asan_tls_init)(void *, + unsigned long, void *) = asan_thread_init; //////////////////////////////////////////////////////////////////////////////// // For some reason, the MD CRT doesn't call the C/C++ terminators during on DLL @@ -29,26 +88,43 @@ // using atexit() that calls a small subset of C terminators // where LLVM global_dtors is placed. Fingers crossed, no other C terminators // are there. -extern "C" int __cdecl atexit(void(__cdecl *f)(void)); +extern "C" int __cdecl atexit(void (__cdecl *f)(void)); extern "C" void __cdecl _initterm(void *a, void *b); namespace { -__declspec(allocate(".CRT$XTW")) void *before_global_dtors = 0; -__declspec(allocate(".CRT$XTY")) void *after_global_dtors = 0; +__declspec(allocate(".CRT$XTW")) void* before_global_dtors = 0; +__declspec(allocate(".CRT$XTY")) void* after_global_dtors = 0; void UnregisterGlobals() { _initterm(&before_global_dtors, &after_global_dtors); } -int ScheduleUnregisterGlobals() { return atexit(UnregisterGlobals); } +int ScheduleUnregisterGlobals() { + return atexit(UnregisterGlobals); +} } // namespace // We need to call 'atexit(UnregisterGlobals);' as early as possible, but after // atexit() is initialized (.CRT$XIC). As this is executed before C++ // initializers (think ctors for globals), UnregisterGlobals gets executed after // dtors for C++ globals. -extern "C" __declspec(allocate(".CRT$XID")) int ( - *__asan_schedule_unregister_globals)() = ScheduleUnregisterGlobals; -WIN_FORCE_LINK(__asan_schedule_unregister_globals) +__declspec(allocate(".CRT$XID")) +int (*__asan_schedule_unregister_globals)() = ScheduleUnregisterGlobals; + +//////////////////////////////////////////////////////////////////////////////// +// ASan SEH handling. +// We need to set the ASan-specific SEH handler at the end of CRT initialization +// of each module (see also asan_win.cpp). +extern "C" { +__declspec(dllimport) int __asan_set_seh_filter(); +static int SetSEHFilter() { return __asan_set_seh_filter(); } + +// Unfortunately, putting a pointer to __asan_set_seh_filter into +// __asan_intercept_seh gets optimized out, so we have to use an extra function. +__declspec(allocate(".CRT$XCAB")) int (*__asan_seh_interceptor)() = + SetSEHFilter; +} + +WIN_FORCE_LINK(__asan_dso_reg_hook) -#endif // SANITIZER_DYNAMIC_RUNTIME_THUNK +#endif // SANITIZER_DYNAMIC_RUNTIME_THUNK diff --git a/compiler-rt/lib/asan/asan_win_static_runtime_thunk.cpp b/compiler-rt/lib/asan/asan_win_static_runtime_thunk.cpp deleted file mode 100644 index dec50a5..0000000 --- a/compiler-rt/lib/asan/asan_win_static_runtime_thunk.cpp +++ /dev/null @@ -1,110 +0,0 @@ -//===-- asan_win_static_runtime_thunk.cpp ---------------------------------===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file is a part of AddressSanitizer, an address sanity checker.
-//
-// This file defines a family of thunks that should be statically linked into
-// modules that are statically linked with the C Runtime in order to delegate
-// the calls to the ASAN runtime DLL.
-// See https://github.com/google/sanitizers/issues/209 for the details.
-//===----------------------------------------------------------------------===//
-
-#ifdef SANITIZER_STATIC_RUNTIME_THUNK
-# include "asan_init_version.h"
-# include "asan_interface_internal.h"
-# include "asan_win_common_runtime_thunk.h"
-# include "sanitizer_common/sanitizer_platform_interceptors.h"
-# include "sanitizer_common/sanitizer_win_defs.h"
-# include "sanitizer_common/sanitizer_win_thunk_interception.h"
-
-# if defined(_MSC_VER) && !defined(__clang__)
-// Disable warnings such as: 'void memchr(void)': incorrect number of arguments
-// for intrinsic function, expected '3' arguments.
-# pragma warning(push)
-# pragma warning(disable : 4392)
-# endif
-
-# define INTERCEPT_LIBRARY_FUNCTION_ASAN(X) \
- INTERCEPT_LIBRARY_FUNCTION(X, "__asan_wrap_" #X)
-
-INTERCEPT_LIBRARY_FUNCTION_ASAN(atoi);
-INTERCEPT_LIBRARY_FUNCTION_ASAN(atol);
-INTERCEPT_LIBRARY_FUNCTION_ASAN(atoll);
-INTERCEPT_LIBRARY_FUNCTION_ASAN(frexp);
-INTERCEPT_LIBRARY_FUNCTION_ASAN(longjmp);
-# if SANITIZER_INTERCEPT_MEMCHR
-INTERCEPT_LIBRARY_FUNCTION_ASAN(memchr);
-# endif
-INTERCEPT_LIBRARY_FUNCTION_ASAN(memcmp);
-INTERCEPT_LIBRARY_FUNCTION_ASAN(memcpy);
-# ifndef _WIN64
-// memmove and memcpy share an implementation on amd64
-INTERCEPT_LIBRARY_FUNCTION_ASAN(memmove);
-# endif
-INTERCEPT_LIBRARY_FUNCTION_ASAN(memset);
-INTERCEPT_LIBRARY_FUNCTION_ASAN(strcat);
-INTERCEPT_LIBRARY_FUNCTION_ASAN(strchr);
-INTERCEPT_LIBRARY_FUNCTION_ASAN(strcmp);
-INTERCEPT_LIBRARY_FUNCTION_ASAN(strcpy);
-INTERCEPT_LIBRARY_FUNCTION_ASAN(strcspn);
-INTERCEPT_LIBRARY_FUNCTION_ASAN(_strdup);
-INTERCEPT_LIBRARY_FUNCTION_ASAN(strlen);
-INTERCEPT_LIBRARY_FUNCTION_ASAN(strncat);
-INTERCEPT_LIBRARY_FUNCTION_ASAN(strncmp);
-INTERCEPT_LIBRARY_FUNCTION_ASAN(strncpy);
-INTERCEPT_LIBRARY_FUNCTION_ASAN(strnlen);
-INTERCEPT_LIBRARY_FUNCTION_ASAN(strpbrk);
-// INTERCEPT_LIBRARY_FUNCTION_ASAN(strrchr);
-INTERCEPT_LIBRARY_FUNCTION_ASAN(strspn);
-INTERCEPT_LIBRARY_FUNCTION_ASAN(strstr);
-INTERCEPT_LIBRARY_FUNCTION_ASAN(strtok);
-INTERCEPT_LIBRARY_FUNCTION_ASAN(strtol);
-INTERCEPT_LIBRARY_FUNCTION_ASAN(wcslen);
-INTERCEPT_LIBRARY_FUNCTION_ASAN(wcsnlen);
-
-# if defined(_MSC_VER) && !defined(__clang__)
-# pragma warning(pop)
-# endif
-
-# ifdef _WIN64
-INTERCEPT_LIBRARY_FUNCTION_ASAN(__C_specific_handler);
-# else
-extern "C" void abort();
-INTERCEPT_LIBRARY_FUNCTION_ASAN(_except_handler3);
-// _except_handler4 checks -GS cookie which is different for each module, so we
-// can't use INTERCEPT_LIBRARY_FUNCTION_ASAN(_except_handler4), need to apply
-// manually
-extern "C" int _except_handler4(void *, void *, void *, void *);
-static int (*real_except_handler4)(void *, void *, void *,
- void *) = &_except_handler4;
-static int intercept_except_handler4(void *a, void *b, void *c, void *d) {
- __asan_handle_no_return();
- return real_except_handler4(a, b, c, d);
-}
-# endif
-
-// Windows specific functions not included in asan_interface.inc.
-// INTERCEPT_WRAP_W_V(__asan_should_detect_stack_use_after_return)
-// INTERCEPT_WRAP_W_V(__asan_get_shadow_memory_dynamic_address)
-// INTERCEPT_WRAP_W_W(__asan_unhandled_exception_filter)
-
-extern "C" void __asan_initialize_static_thunk() {
-# ifndef _WIN64
- if (real_except_handler4 == &_except_handler4) {
- // Single threaded, no need for synchronization.
- if (!__sanitizer_override_function_by_addr(
- reinterpret_cast<__sanitizer::uptr>(&intercept_except_handler4),
- reinterpret_cast<__sanitizer::uptr>(&_except_handler4),
- reinterpret_cast<__sanitizer::uptr*>(&real_except_handler4))) {
- abort();
- }
- }
-# endif
-}
-
-#endif // SANITIZER_DLL_THUNK
diff --git a/compiler-rt/lib/asan/tests/CMakeLists.txt b/compiler-rt/lib/asan/tests/CMakeLists.txt index 9c1db7c..bda47bd 100644 --- a/compiler-rt/lib/asan/tests/CMakeLists.txt +++ b/compiler-rt/lib/asan/tests/CMakeLists.txt @@ -203,7 +203,7 @@ function(add_asan_tests arch test_runtime) CFLAGS ${ASAN_UNITTEST_INSTRUMENTED_CFLAGS} -D_MT -D_DLL SOURCES ${ASAN_INST_TEST_SOURCES} LINK_FLAGS ${ASAN_DYNAMIC_UNITTEST_INSTRUMENTED_LINK_FLAGS} - -D_MT -D_DLL -Wl,-nodefaultlib:libcmt,-defaultlib:msvcrt,-defaultlib:oldnames + -Wl,-nodefaultlib:libcmt,-defaultlib:msvcrt,-defaultlib:oldnames ) else() diff --git a/compiler-rt/lib/profile/CMakeLists.txt b/compiler-rt/lib/profile/CMakeLists.txt index ef23492..45e5164 100644 --- a/compiler-rt/lib/profile/CMakeLists.txt +++ b/compiler-rt/lib/profile/CMakeLists.txt @@ -111,12 +111,6 @@ if(COMPILER_RT_TARGET_HAS_UNAME) -DCOMPILER_RT_HAS_UNAME=1) endif() -if(MSVC) - # profile historically has only been supported with the static runtime - # on windows - set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreaded) -endif() - # We don't use the C++ Standard Library here, so avoid including it by mistake. append_list_if(COMPILER_RT_HAS_NOSTDINCXX_FLAG -nostdinc++ EXTRA_FLAGS) # XRay uses C++ standard library headers. diff --git a/compiler-rt/lib/sanitizer_common/CMakeLists.txt b/compiler-rt/lib/sanitizer_common/CMakeLists.txt index 41c3888..66f2d25 100644 --- a/compiler-rt/lib/sanitizer_common/CMakeLists.txt +++ b/compiler-rt/lib/sanitizer_common/CMakeLists.txt @@ -42,7 +42,6 @@ set(SANITIZER_SOURCES_NOTERMINATION sanitizer_thread_registry.cpp sanitizer_type_traits.cpp sanitizer_win.cpp - sanitizer_win_interception.cpp ) set(SANITIZER_SOURCES @@ -207,8 +206,8 @@ set(SANITIZER_IMPL_HEADERS sanitizer_vector.h sanitizer_win.h sanitizer_win_defs.h - sanitizer_win_interception.h - sanitizer_win_thunk_interception.h + sanitizer_win_dll_thunk.h + sanitizer_win_weak_interception.h ) include_directories(..) @@ -302,23 +301,57 @@ add_compiler_rt_object_libraries(RTSanitizerCommonSymbolizerNoHooks DEFS ${SANITIZER_COMMON_DEFINITIONS}) if(WIN32) - set(RUNTIME_THUNK_CFLAGS -DSANITIZER_DYNAMIC_RUNTIME_THUNK -DSANITIZER_STATIC_RUNTIME_THUNK) - append_list_if(MSVC /Zl RUNTIME_THUNK_CFLAGS) - add_compiler_rt_object_libraries(SanitizerRuntimeThunk + add_compiler_rt_object_libraries(SanitizerCommonWeakInterception ${SANITIZER_COMMON_SUPPORTED_OS} ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH} SOURCES - sanitizer_win_thunk_interception.cpp - CFLAGS ${SANITIZER_CFLAGS} ${RUNTIME_THUNK_CFLAGS} + sanitizer_win_weak_interception.cpp + 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.cpp + CFLAGS ${SANITIZER_CFLAGS} -DSANITIZER_DYNAMIC + DEFS ${SANITIZER_COMMON_DEFINITIONS}) + + add_compiler_rt_object_libraries(SanitizerCommonDllThunk + ${SANITIZER_COMMON_SUPPORTED_OS} + ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH} + SOURCES + sanitizer_win_dll_thunk.cpp + CFLAGS ${SANITIZER_CFLAGS} -DSANITIZER_DLL_THUNK + DEFS ${SANITIZER_COMMON_DEFINITIONS}) + add_compiler_rt_object_libraries(SancovDllThunk + ${SANITIZER_COMMON_SUPPORTED_OS} + ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH} + SOURCES + sanitizer_coverage_win_dll_thunk.cpp + sanitizer_coverage_win_sections.cpp + CFLAGS ${SANITIZER_CFLAGS} -DSANITIZER_DLL_THUNK DEFS ${SANITIZER_COMMON_DEFINITIONS}) - add_compiler_rt_object_libraries(SancovRuntimeThunk + set(DYNAMIC_RUNTIME_THUNK_CFLAGS "-DSANITIZER_DYNAMIC_RUNTIME_THUNK") + if(MSVC) + list(APPEND DYNAMIC_RUNTIME_THUNK_CFLAGS "-Zl") + elseif(CMAKE_C_COMPILER_ID MATCHES Clang) + list(APPEND DYNAMIC_RUNTIME_THUNK_CFLAGS "-nodefaultlibs") + endif() + add_compiler_rt_object_libraries(SanitizerCommonDynamicRuntimeThunk + ${SANITIZER_COMMON_SUPPORTED_OS} + ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH} + SOURCES + sanitizer_win_dynamic_runtime_thunk.cpp + CFLAGS ${SANITIZER_CFLAGS} ${DYNAMIC_RUNTIME_THUNK_CFLAGS} + DEFS ${SANITIZER_COMMON_DEFINITIONS}) + add_compiler_rt_object_libraries(SancovDynamicRuntimeThunk ${SANITIZER_COMMON_SUPPORTED_OS} ARCHS ${SANITIZER_COMMON_SUPPORTED_ARCH} SOURCES - sanitizer_coverage_win_runtime_thunk.cpp + sanitizer_coverage_win_dynamic_runtime_thunk.cpp sanitizer_coverage_win_sections.cpp - CFLAGS ${SANITIZER_CFLAGS} ${RUNTIME_THUNK_CFLAGS} + CFLAGS ${SANITIZER_CFLAGS} ${DYNAMIC_RUNTIME_THUNK_CFLAGS} DEFS ${SANITIZER_COMMON_DEFINITIONS}) endif() diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common_interface.inc b/compiler-rt/lib/sanitizer_common/sanitizer_common_interface.inc index 11f1d96..557207f 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_common_interface.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_common_interface.inc @@ -50,9 +50,3 @@ INTERFACE_WEAK_FUNCTION(__sanitizer_malloc_hook) INTERFACE_FUNCTION(__sanitizer_internal_memcpy) INTERFACE_FUNCTION(__sanitizer_internal_memmove) INTERFACE_FUNCTION(__sanitizer_internal_memset) - -#if SANITIZER_WINDOWS -INTERFACE_FUNCTION(__sanitizer_override_function) -INTERFACE_FUNCTION(__sanitizer_override_function_by_addr) -INTERFACE_FUNCTION(__sanitizer_register_weak_function) -#endif diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_coverage_win_dll_thunk.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_coverage_win_dll_thunk.cpp new file mode 100644 index 0000000..d0bf8a4 --- /dev/null +++ b/compiler-rt/lib/sanitizer_common/sanitizer_coverage_win_dll_thunk.cpp @@ -0,0 +1,20 @@ +//===-- sanitizer_coverage_win_dll_thunk.cpp ------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines a family of thunks that should be statically linked into +// the DLLs that have instrumentation in order to delegate the calls to the +// shared runtime that lives in the main binary. +// See https://github.com/google/sanitizers/issues/209 for the details. +//===----------------------------------------------------------------------===// +#ifdef SANITIZER_DLL_THUNK +#include "sanitizer_win_dll_thunk.h" +// Sanitizer Coverage interface functions. +#define INTERFACE_FUNCTION(Name) INTERCEPT_SANITIZER_FUNCTION(Name) +#define INTERFACE_WEAK_FUNCTION(Name) INTERCEPT_SANITIZER_WEAK_FUNCTION(Name) +#include "sanitizer_coverage_interface.inc" +#endif // SANITIZER_DLL_THUNK diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_coverage_win_runtime_thunk.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_coverage_win_dynamic_runtime_thunk.cpp index 2819446..0bdf0c5 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_coverage_win_runtime_thunk.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_coverage_win_dynamic_runtime_thunk.cpp @@ -1,4 +1,4 @@ -//===-- sanitizer_coverage_win_runtime_thunk.cpp --------------------------===// +//===-- sanitizer_coverage_win_dynamic_runtime_thunk.cpp ------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -10,20 +10,17 @@ // to interact with Sanitizer Coverage, when it is included in a dll. // //===----------------------------------------------------------------------===// -#if defined(SANITIZER_DYNAMIC_RUNTIME_THUNK) || \ - defined(SANITIZER_STATIC_RUNTIME_THUNK) -# define SANITIZER_IMPORT_INTERFACE 1 -# include "sanitizer_win_defs.h" -# include "sanitizer_win_thunk_interception.h" +#ifdef SANITIZER_DYNAMIC_RUNTIME_THUNK +#define SANITIZER_IMPORT_INTERFACE 1 +#include "sanitizer_win_defs.h" // Define weak alias for all weak functions imported from sanitizer coverage. -# define INTERFACE_FUNCTION(Name) -# define INTERFACE_WEAK_FUNCTION(Name) REGISTER_WEAK_FUNCTION(Name) -# include "sanitizer_coverage_interface.inc" -#endif // defined(SANITIZER_DYNAMIC_RUNTIME_THUNK) || - // defined(SANITIZER_STATIC_RUNTIME_THUNK) +#define INTERFACE_FUNCTION(Name) +#define INTERFACE_WEAK_FUNCTION(Name) WIN_WEAK_IMPORT_DEF(Name) +#include "sanitizer_coverage_interface.inc" +#endif // SANITIZER_DYNAMIC_RUNTIME_THUNK namespace __sanitizer { // Add one, otherwise unused, external symbol to this object file so that the // Visual C++ linker includes it and reads the .drective section. void ForceWholeArchiveIncludeForSanCov() {} -} // namespace __sanitizer +} diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_coverage_win_weak_interception.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_coverage_win_weak_interception.cpp new file mode 100644 index 0000000..5526398 --- /dev/null +++ b/compiler-rt/lib/sanitizer_common/sanitizer_coverage_win_weak_interception.cpp @@ -0,0 +1,23 @@ +//===-- sanitizer_coverage_win_weak_interception.cpp ----------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// 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 diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_win_dll_thunk.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_win_dll_thunk.cpp new file mode 100644 index 0000000..1562c16 --- /dev/null +++ b/compiler-rt/lib/sanitizer_common/sanitizer_win_dll_thunk.cpp @@ -0,0 +1,101 @@ +//===-- sanitizer_win_dll_thunk.cpp ---------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// This file defines a family of thunks that should be statically linked into +// the DLLs that have instrumentation in order to delegate the calls to the +// shared runtime that lives in the main binary. +// See https://github.com/google/sanitizers/issues/209 for the details. +//===----------------------------------------------------------------------===// + +#ifdef SANITIZER_DLL_THUNK +#include "sanitizer_win_defs.h" +#include "sanitizer_win_dll_thunk.h" +#include "interception/interception.h" + +extern "C" { +void *WINAPI GetModuleHandleA(const char *module_name); +void abort(); +} + +namespace __sanitizer { +uptr dllThunkGetRealAddrOrDie(const char *name) { + uptr ret = + __interception::InternalGetProcAddress((void *)GetModuleHandleA(0), name); + if (!ret) + abort(); + return ret; +} + +int dllThunkIntercept(const char* main_function, uptr dll_function) { + uptr wrapper = dllThunkGetRealAddrOrDie(main_function); + if (!__interception::OverrideFunction(dll_function, wrapper, 0)) + abort(); + return 0; +} + +int dllThunkInterceptWhenPossible(const char* main_function, + const char* default_function, uptr dll_function) { + uptr wrapper = __interception::InternalGetProcAddress( + (void *)GetModuleHandleA(0), main_function); + if (!wrapper) + wrapper = dllThunkGetRealAddrOrDie(default_function); + if (!__interception::OverrideFunction(dll_function, wrapper, 0)) + abort(); + return 0; +} +} // namespace __sanitizer + +// Include Sanitizer Common interface. +#define INTERFACE_FUNCTION(Name) INTERCEPT_SANITIZER_FUNCTION(Name) +#define INTERFACE_WEAK_FUNCTION(Name) INTERCEPT_SANITIZER_WEAK_FUNCTION(Name) +#include "sanitizer_common_interface.inc" + +#pragma section(".DLLTH$A", read) +#pragma section(".DLLTH$Z", read) + +typedef void (*DllThunkCB)(); +extern "C" { +__declspec(allocate(".DLLTH$A")) DllThunkCB __start_dll_thunk; +__declspec(allocate(".DLLTH$Z")) DllThunkCB __stop_dll_thunk; +} + +// Disable compiler warnings that show up if we declare our own version +// of a compiler intrinsic (e.g. strlen). +#pragma warning(disable: 4391) +#pragma warning(disable: 4392) + +extern "C" int __dll_thunk_init() { + static bool flag = false; + // __dll_thunk_init is expected to be called by only one thread. + if (flag) return 0; + flag = true; + + for (DllThunkCB *it = &__start_dll_thunk; it < &__stop_dll_thunk; ++it) + if (*it) + (*it)(); + + // In DLLs, the callbacks are expected to return 0, + // otherwise CRT initialization fails. + return 0; +} + +// We want to call dll_thunk_init before C/C++ initializers / constructors are +// executed, otherwise functions like memset might be invoked. +#pragma section(".CRT$XIB", long, read) +__declspec(allocate(".CRT$XIB")) int (*__dll_thunk_preinit)() = + __dll_thunk_init; + +static void WINAPI dll_thunk_thread_init(void *mod, unsigned long reason, + void *reserved) { + if (reason == /*DLL_PROCESS_ATTACH=*/1) __dll_thunk_init(); +} + +#pragma section(".CRT$XLAB", long, read) +__declspec(allocate(".CRT$XLAB")) void (WINAPI *__dll_thunk_tls_init)(void *, + unsigned long, void *) = dll_thunk_thread_init; + +#endif // SANITIZER_DLL_THUNK diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_win_dll_thunk.h b/compiler-rt/lib/sanitizer_common/sanitizer_win_dll_thunk.h new file mode 100644 index 0000000..639d91a --- /dev/null +++ b/compiler-rt/lib/sanitizer_common/sanitizer_win_dll_thunk.h @@ -0,0 +1,181 @@ +//===-- sanitizer_win_dll_thunk.h -----------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// This header provide helper macros to delegate calls to the shared runtime +// that lives in the main executable. It should be included to dll_thunks that +// will be linked to the dlls, when the sanitizer is a static library included +// in the main executable. +//===----------------------------------------------------------------------===// +#ifndef SANITIZER_WIN_DLL_THUNK_H +#define SANITIZER_WIN_DLL_THUNK_H +#include "sanitizer_internal_defs.h" + +namespace __sanitizer { +uptr dllThunkGetRealAddrOrDie(const char *name); + +int dllThunkIntercept(const char* main_function, uptr dll_function); + +int dllThunkInterceptWhenPossible(const char* main_function, + const char* default_function, uptr dll_function); +} + +extern "C" int __dll_thunk_init(); + +// ----------------- Function interception helper macros -------------------- // +// Override dll_function with main_function from main executable. +#define INTERCEPT_OR_DIE(main_function, dll_function) \ + static int intercept_##dll_function() { \ + return __sanitizer::dllThunkIntercept(main_function, (__sanitizer::uptr) \ + dll_function); \ + } \ + __pragma(section(".DLLTH$M", long, read)) \ + __declspec(allocate(".DLLTH$M")) int (*__dll_thunk_##dll_function)() = \ + intercept_##dll_function; + +// Try to override dll_function with main_function from main executable. +// If main_function is not present, override dll_function with default_function. +#define INTERCEPT_WHEN_POSSIBLE(main_function, default_function, dll_function) \ + static int intercept_##dll_function() { \ + return __sanitizer::dllThunkInterceptWhenPossible(main_function, \ + default_function, (__sanitizer::uptr)dll_function); \ + } \ + __pragma(section(".DLLTH$M", long, read)) \ + __declspec(allocate(".DLLTH$M")) int (*__dll_thunk_##dll_function)() = \ + intercept_##dll_function; + +// -------------------- Function interception macros ------------------------ // +// Special case of hooks -- ASan own interface functions. Those are only called +// after __asan_init, thus an empty implementation is sufficient. +#define INTERCEPT_SANITIZER_FUNCTION(name) \ + extern "C" __declspec(noinline) void name() { \ + volatile int prevent_icf = (__LINE__ << 8) ^ __COUNTER__; \ + static const char function_name[] = #name; \ + for (const char* ptr = &function_name[0]; *ptr; ++ptr) \ + prevent_icf ^= *ptr; \ + (void)prevent_icf; \ + __debugbreak(); \ + } \ + INTERCEPT_OR_DIE(#name, name) + +// Special case of hooks -- 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. Instead, when the function is not present in the main executable +// we consider the default impl provided by asan library. +#define INTERCEPT_SANITIZER_WEAK_FUNCTION(name) \ + extern "C" __declspec(noinline) void name() { \ + volatile int prevent_icf = (__LINE__ << 8) ^ __COUNTER__; \ + static const char function_name[] = #name; \ + for (const char* ptr = &function_name[0]; *ptr; ++ptr) \ + prevent_icf ^= *ptr; \ + (void)prevent_icf; \ + __debugbreak(); \ + } \ + INTERCEPT_WHEN_POSSIBLE(#name, STRINGIFY(WEAK_EXPORT_NAME(name)), name) + +// We can't define our own version of strlen etc. because that would lead to +// link-time or even type mismatch errors. Instead, we can declare a function +// just to be able to get its address. Me may miss the first few calls to the +// functions since it can be called before __dll_thunk_init, but that would lead +// to false negatives in the startup code before user's global initializers, +// which isn't a big deal. +#define INTERCEPT_LIBRARY_FUNCTION(name) \ + extern "C" void name(); \ + INTERCEPT_OR_DIE(STRINGIFY(WRAP(name)), name) + +// Use these macros for functions that could be called before __dll_thunk_init() +// is executed and don't lead to errors if defined (free, malloc, etc). +#define INTERCEPT_WRAP_V_V(name) \ + extern "C" void name() { \ + typedef decltype(name) *fntype; \ + static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \ + fn(); \ + } \ + INTERCEPT_OR_DIE(#name, name); + +#define INTERCEPT_WRAP_V_W(name) \ + extern "C" void name(void *arg) { \ + typedef decltype(name) *fntype; \ + static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \ + fn(arg); \ + } \ + INTERCEPT_OR_DIE(#name, name); + +#define INTERCEPT_WRAP_V_WW(name) \ + extern "C" void name(void *arg1, void *arg2) { \ + typedef decltype(name) *fntype; \ + static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \ + fn(arg1, arg2); \ + } \ + INTERCEPT_OR_DIE(#name, name); + +#define INTERCEPT_WRAP_V_WWW(name) \ + extern "C" void name(void *arg1, void *arg2, void *arg3) { \ + typedef decltype(name) *fntype; \ + static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \ + fn(arg1, arg2, arg3); \ + } \ + INTERCEPT_OR_DIE(#name, name); + +#define INTERCEPT_WRAP_W_V(name) \ + extern "C" void *name() { \ + typedef decltype(name) *fntype; \ + static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \ + return fn(); \ + } \ + INTERCEPT_OR_DIE(#name, name); + +#define INTERCEPT_WRAP_W_W(name) \ + extern "C" void *name(void *arg) { \ + typedef decltype(name) *fntype; \ + static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \ + return fn(arg); \ + } \ + INTERCEPT_OR_DIE(#name, name); + +#define INTERCEPT_WRAP_W_WW(name) \ + extern "C" void *name(void *arg1, void *arg2) { \ + typedef decltype(name) *fntype; \ + static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \ + return fn(arg1, arg2); \ + } \ + INTERCEPT_OR_DIE(#name, name); + +#define INTERCEPT_WRAP_W_WWW(name) \ + extern "C" void *name(void *arg1, void *arg2, void *arg3) { \ + typedef decltype(name) *fntype; \ + static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \ + return fn(arg1, arg2, arg3); \ + } \ + INTERCEPT_OR_DIE(#name, name); + +#define INTERCEPT_WRAP_W_WWWW(name) \ + extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4) { \ + typedef decltype(name) *fntype; \ + static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \ + return fn(arg1, arg2, arg3, arg4); \ + } \ + INTERCEPT_OR_DIE(#name, name); + +#define INTERCEPT_WRAP_W_WWWWW(name) \ + extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4, \ + void *arg5) { \ + typedef decltype(name) *fntype; \ + static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \ + return fn(arg1, arg2, arg3, arg4, arg5); \ + } \ + INTERCEPT_OR_DIE(#name, name); + +#define INTERCEPT_WRAP_W_WWWWWW(name) \ + extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4, \ + void *arg5, void *arg6) { \ + typedef decltype(name) *fntype; \ + static fntype fn = (fntype)__sanitizer::dllThunkGetRealAddrOrDie(#name); \ + return fn(arg1, arg2, arg3, arg4, arg5, arg6); \ + } \ + INTERCEPT_OR_DIE(#name, name); + +#endif // SANITIZER_WIN_DLL_THUNK_H diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_win_dynamic_runtime_thunk.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_win_dynamic_runtime_thunk.cpp new file mode 100644 index 0000000..87c032c --- /dev/null +++ b/compiler-rt/lib/sanitizer_common/sanitizer_win_dynamic_runtime_thunk.cpp @@ -0,0 +1,26 @@ +//===-- santizer_win_dynamic_runtime_thunk.cpp ----------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines things that need to be present in the application modules +// to interact with Sanitizer Common, when it is included in a dll. +// +//===----------------------------------------------------------------------===// +#ifdef SANITIZER_DYNAMIC_RUNTIME_THUNK +#define SANITIZER_IMPORT_INTERFACE 1 +#include "sanitizer_win_defs.h" +// Define weak alias for all weak functions imported from sanitizer common. +#define INTERFACE_FUNCTION(Name) +#define INTERFACE_WEAK_FUNCTION(Name) WIN_WEAK_IMPORT_DEF(Name) +#include "sanitizer_common_interface.inc" +#endif // SANITIZER_DYNAMIC_RUNTIME_THUNK + +namespace __sanitizer { +// Add one, otherwise unused, external symbol to this object file so that the +// Visual C++ linker includes it and reads the .drective section. +void ForceWholeArchiveIncludeForSanitizerCommon() {} +} diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_win_immortalize.h b/compiler-rt/lib/sanitizer_common/sanitizer_win_immortalize.h deleted file mode 100644 index 808cd2f..0000000 --- a/compiler-rt/lib/sanitizer_common/sanitizer_win_immortalize.h +++ /dev/null @@ -1,71 +0,0 @@ -//===-- sanitizer_win_immortalize.h ---------------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// -// This file is shared between AddressSanitizer, and interception. -// -// Windows-specific thread-safe and pre-CRT global initialization safe -// infrastructure to create an object whose destructor is never called. -//===----------------------------------------------------------------------===// -#if SANITIZER_WINDOWS -# pragma once -// Requires including sanitizer_placement_new.h (which is not allowed to be -// included in headers). - -# include "sanitizer_win_defs.h" -// These types are required to satisfy XFG which requires that the names of the -// types for indirect calls to be correct as well as the name of the original -// type for any typedefs. - -// TODO: There must be a better way to do this -# ifndef _WINDOWS_ -typedef void* PVOID; -typedef int BOOL; -typedef union _RTL_RUN_ONCE { - PVOID ptr; -} INIT_ONCE, *PINIT_ONCE; - -extern "C" { -__declspec(dllimport) int WINAPI InitOnceExecuteOnce( - PINIT_ONCE, BOOL(WINAPI*)(PINIT_ONCE, PVOID, PVOID*), void*, void*); -} -# endif - -namespace __sanitizer { -template <class Ty> -BOOL WINAPI immortalize_impl(PINIT_ONCE, PVOID storage_ptr, PVOID*) noexcept { - // Ty must provide a placement new operator - new (storage_ptr) Ty(); - return 1; -} - -template <class Ty, typename Arg> -BOOL WINAPI immortalize_impl(PINIT_ONCE, PVOID storage_ptr, - PVOID* param) noexcept { - // Ty must provide a placement new operator - new (storage_ptr) Ty(*((Arg*)param)); - return 1; -} - -template <class Ty> -Ty& immortalize() { // return a reference to an object that will live forever - static INIT_ONCE flag; - alignas(Ty) static unsigned char storage[sizeof(Ty)]; - InitOnceExecuteOnce(&flag, immortalize_impl<Ty>, &storage, nullptr); - return reinterpret_cast<Ty&>(storage); -} - -template <class Ty, typename Arg> -Ty& immortalize( - Arg arg) { // return a reference to an object that will live forever - static INIT_ONCE flag; - alignas(Ty) static unsigned char storage[sizeof(Ty)]; - InitOnceExecuteOnce(&flag, immortalize_impl<Ty, Arg>, &storage, &arg); - return reinterpret_cast<Ty&>(storage); -} -} // namespace __sanitizer -#endif // SANITIZER_WINDOWS diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_win_interception.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_win_interception.cpp deleted file mode 100644 index 75a1545..0000000 --- a/compiler-rt/lib/sanitizer_common/sanitizer_win_interception.cpp +++ /dev/null @@ -1,156 +0,0 @@ -//===-- sanitizer_win_interception.cpp -------------------- --*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Windows-specific export surface to provide interception for parts of the
-// runtime that are always statically linked, both for overriding user-defined
-// functions as well as registering weak functions that the ASAN runtime should
-// use over defaults.
-//
-//===----------------------------------------------------------------------===//
-
-#include "sanitizer_platform.h"
-#if SANITIZER_WINDOWS
-# include <stddef.h>
-
-# include "interception/interception.h"
-# include "sanitizer_addrhashmap.h"
-# include "sanitizer_common.h"
-# include "sanitizer_internal_defs.h"
-# include "sanitizer_placement_new.h"
-# include "sanitizer_win_immortalize.h"
-# include "sanitizer_win_interception.h"
-
-using namespace __sanitizer;
-
-extern "C" void *__ImageBase;
-
-namespace __sanitizer {
-
-static uptr GetSanitizerDllExport(const char *export_name) {
- const uptr function_address =
- __interception::InternalGetProcAddress(&__ImageBase, export_name);
- if (function_address == 0) {
- Report("ERROR: Failed to find sanitizer DLL export '%s'\n", export_name);
- CHECK("Failed to find sanitizer DLL export" && 0);
- }
- return function_address;
-}
-
-struct WeakCallbackList {
- explicit constexpr WeakCallbackList(RegisterWeakFunctionCallback cb)
- : callback(cb), next(nullptr) {}
-
- static void *operator new(size_t size) { return InternalAlloc(size); }
-
- static void operator delete(void *p) { InternalFree(p); }
-
- RegisterWeakFunctionCallback callback;
- WeakCallbackList *next;
-};
-using WeakCallbackMap = AddrHashMap<WeakCallbackList *, 11>;
-
-static WeakCallbackMap *GetWeakCallbackMap() {
- return &immortalize<WeakCallbackMap>();
-}
-
-void AddRegisterWeakFunctionCallback(uptr export_address,
- RegisterWeakFunctionCallback cb) {
- WeakCallbackMap::Handle h_find_or_create(GetWeakCallbackMap(), export_address,
- false, true);
- CHECK(h_find_or_create.exists());
- if (h_find_or_create.created()) {
- *h_find_or_create = new WeakCallbackList(cb);
- } else {
- (*h_find_or_create)->next = new WeakCallbackList(cb);
- }
-}
-
-static void RunWeakFunctionCallbacks(uptr export_address) {
- WeakCallbackMap::Handle h_find(GetWeakCallbackMap(), export_address, false,
- false);
- if (!h_find.exists()) {
- return;
- }
-
- WeakCallbackList *list = *h_find;
- do {
- list->callback();
- } while ((list = list->next));
-}
-
-} // namespace __sanitizer
-
-extern "C" __declspec(dllexport) bool __cdecl __sanitizer_override_function(
- const char *export_name, const uptr user_function,
- uptr *const old_user_function) {
- CHECK(export_name);
- CHECK(user_function);
-
- const uptr sanitizer_function = GetSanitizerDllExport(export_name);
-
- const bool function_overridden = __interception::OverrideFunction(
- user_function, sanitizer_function, old_user_function);
- if (!function_overridden) {
- Report(
- "ERROR: Failed to override local function at '%p' with sanitizer "
- "function '%s'\n",
- user_function, export_name);
- CHECK("Failed to replace local function with sanitizer version." && 0);
- }
-
- return function_overridden;
-}
-
-extern "C"
- __declspec(dllexport) bool __cdecl __sanitizer_override_function_by_addr(
- const uptr source_function, const uptr target_function,
- uptr *const old_target_function) {
- CHECK(source_function);
- CHECK(target_function);
-
- const bool function_overridden = __interception::OverrideFunction(
- target_function, source_function, old_target_function);
- if (!function_overridden) {
- Report(
- "ERROR: Failed to override function at '%p' with function at "
- "'%p'\n",
- target_function, source_function);
- CHECK("Failed to apply function override." && 0);
- }
-
- return function_overridden;
-}
-
-extern "C"
- __declspec(dllexport) bool __cdecl __sanitizer_register_weak_function(
- const char *export_name, const uptr user_function,
- uptr *const old_user_function) {
- CHECK(export_name);
- CHECK(user_function);
-
- const uptr sanitizer_function = GetSanitizerDllExport(export_name);
-
- const bool function_overridden = __interception::OverrideFunction(
- sanitizer_function, user_function, old_user_function);
- if (!function_overridden) {
- Report(
- "ERROR: Failed to register local function at '%p' to be used in "
- "place of sanitizer function '%s'\n.",
- user_function, export_name);
- CHECK("Failed to register weak function." && 0);
- }
-
- // Note that thread-safety of RunWeakFunctionCallbacks in InitializeFlags
- // depends on __sanitizer_register_weak_functions being called during the
- // loader lock.
- RunWeakFunctionCallbacks(sanitizer_function);
-
- return function_overridden;
-}
-
-#endif // SANITIZER_WINDOWS
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_win_interception.h b/compiler-rt/lib/sanitizer_common/sanitizer_win_interception.h deleted file mode 100644 index 70ae3d6..0000000 --- a/compiler-rt/lib/sanitizer_common/sanitizer_win_interception.h +++ /dev/null @@ -1,32 +0,0 @@ -//===-- sanitizer_win_interception.h ---------------------- --*- C++ -*-===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// Windows-specific export surface to provide interception for parts of the
-// runtime that are always statically linked, both for overriding user-defined
-// functions as well as registering weak functions that the ASAN runtime should
-// use over defaults.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef SANITIZER_WIN_INTERCEPTION_H
-#define SANITIZER_WIN_INTERCEPTION_H
-
-#include "sanitizer_platform.h"
-#if SANITIZER_WINDOWS
-
-# include "sanitizer_common.h"
-# include "sanitizer_internal_defs.h"
-
-namespace __sanitizer {
-using RegisterWeakFunctionCallback = void (*)();
-void AddRegisterWeakFunctionCallback(uptr export_address,
- RegisterWeakFunctionCallback cb);
-} // namespace __sanitizer
-
-#endif // SANITIZER_WINDOWS
-#endif // SANITIZER_WIN_INTERCEPTION_H
\ No newline at end of file diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_win_thunk_interception.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_win_thunk_interception.cpp deleted file mode 100644 index 13db886..0000000 --- a/compiler-rt/lib/sanitizer_common/sanitizer_win_thunk_interception.cpp +++ /dev/null @@ -1,110 +0,0 @@ -//===-- sanitizer_win_thunk_interception.cpp ----------------------- -----===//
-//
-// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
-// See https://llvm.org/LICENSE.txt for license information.
-// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
-//
-//===----------------------------------------------------------------------===//
-//
-// This file defines things that need to be present in the application modules
-// to interact with sanitizer DLL correctly and cannot be implemented using the
-// default "import library" generated when linking the DLL.
-//
-// This includes the common infrastructure required to intercept local functions
-// that must be replaced with sanitizer-aware versions, as well as the
-// registration of weak functions with the sanitizer DLL. With this in-place,
-// other sanitizer components can simply write to the .INTR and .WEAK sections.
-//
-//===----------------------------------------------------------------------===//
-
-#if defined(SANITIZER_STATIC_RUNTIME_THUNK) || \
- defined(SANITIZER_DYNAMIC_RUNTIME_THUNK)
-# include "sanitizer_win_thunk_interception.h"
-
-extern "C" void abort();
-
-namespace __sanitizer {
-
-int override_function(const char *export_name, const uptr user_function) {
- if (!__sanitizer_override_function(export_name, user_function)) {
- abort();
- }
-
- return 0;
-}
-
-int register_weak(const char *export_name, const uptr user_function) {
- if (!__sanitizer_register_weak_function(export_name, user_function)) {
- abort();
- }
-
- return 0;
-}
-
-void initialize_thunks(const sanitizer_thunk *first,
- const sanitizer_thunk *last) {
- for (const sanitizer_thunk *it = first; it < last; ++it) {
- if (*it) {
- (*it)();
- }
- }
-}
-} // namespace __sanitizer
-
-# define INTERFACE_FUNCTION(Name)
-# define INTERFACE_WEAK_FUNCTION(Name) REGISTER_WEAK_FUNCTION(Name)
-# include "sanitizer_common_interface.inc"
-
-# pragma section(".INTR$A", read) // intercept begin
-# pragma section(".INTR$Z", read) // intercept end
-# pragma section(".WEAK$A", read) // weak begin
-# pragma section(".WEAK$Z", read) // weak end
-
-extern "C" {
-__declspec(allocate(
- ".INTR$A")) sanitizer_thunk __sanitizer_intercept_thunk_begin;
-__declspec(allocate(".INTR$Z")) sanitizer_thunk __sanitizer_intercept_thunk_end;
-
-__declspec(allocate(
- ".WEAK$A")) sanitizer_thunk __sanitizer_register_weak_thunk_begin;
-__declspec(allocate(
- ".WEAK$Z")) sanitizer_thunk __sanitizer_register_weak_thunk_end;
-}
-
-extern "C" int __sanitizer_thunk_init() {
- // __sanitizer_static_thunk_init is expected to be called by only one thread.
- static bool flag = false;
- if (flag) {
- return 0;
- }
- flag = true;
-
- __sanitizer::initialize_thunks(&__sanitizer_intercept_thunk_begin,
- &__sanitizer_intercept_thunk_end);
- __sanitizer::initialize_thunks(&__sanitizer_register_weak_thunk_begin,
- &__sanitizer_register_weak_thunk_end);
-
- // In DLLs, the callbacks are expected to return 0,
- // otherwise CRT initialization fails.
- return 0;
-}
-
-// We want to call dll_thunk_init before C/C++ initializers / constructors are
-// executed, otherwise functions like memset might be invoked.
-# pragma section(".CRT$XIB", long, read)
-__declspec(allocate(".CRT$XIB")) int (*__sanitizer_thunk_init_ptr)() =
- __sanitizer_thunk_init;
-
-static void WINAPI sanitizer_thunk_thread_init(void *mod, unsigned long reason,
- void *reserved) {
- if (reason == /*DLL_PROCESS_ATTACH=*/1)
- __sanitizer_thunk_init();
-}
-
-# pragma section(".CRT$XLAB", long, read)
-__declspec(allocate(".CRT$XLAB")) void(
- WINAPI *__sanitizer_thunk_thread_init_ptr)(void *, unsigned long, void *) =
- sanitizer_thunk_thread_init;
-
-#endif // defined(SANITIZER_STATIC_RUNTIME_THUNK) ||
- // defined(SANITIZER_DYNAMIC_RUNTIME_THUNK)
\ No newline at end of file diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_win_thunk_interception.h b/compiler-rt/lib/sanitizer_common/sanitizer_win_thunk_interception.h deleted file mode 100644 index 70177d6..0000000 --- a/compiler-rt/lib/sanitizer_common/sanitizer_win_thunk_interception.h +++ /dev/null @@ -1,81 +0,0 @@ -//===-- sanitizer_win_thunk_interception.h ------------------------- -----===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// -// This header provide helper macros and functions to delegate calls to the -// shared runtime that lives in the sanitizer DLL. -//===----------------------------------------------------------------------===// - -#ifndef SANITIZER_WIN_THUNK_INTERCEPTION_H -#define SANITIZER_WIN_THUNK_INTERCEPTION_H -#include <stdint.h> - -#include "sanitizer_internal_defs.h" - -extern "C" { -__declspec(dllimport) bool __cdecl __sanitizer_override_function( - const char *export_name, __sanitizer::uptr user_function, - __sanitizer::uptr *old_function = nullptr); -__declspec(dllimport) bool __cdecl __sanitizer_override_function_by_addr( - __sanitizer::uptr source_function, __sanitizer::uptr target_function, - __sanitizer::uptr *old_target_function = nullptr); -__declspec(dllimport) bool __cdecl __sanitizer_register_weak_function( - const char *export_name, __sanitizer::uptr user_function, - __sanitizer::uptr *old_function = nullptr); -} - -using sanitizer_thunk = int (*)(); - -namespace __sanitizer { -int override_function(const char *export_name, uptr user_function); -int register_weak(const char *export_name, uptr user_function); -void initialize_thunks(const sanitizer_thunk *begin, - const sanitizer_thunk *end); -} // namespace __sanitizer - -// -------------------- Function interception macros ------------------------ // -// We can't define our own version of strlen etc. because that would lead to -// link-time or even type mismatch errors. Instead, we can declare a function -// just to be able to get its address. Me may miss the first few calls to the -// functions since it can be called before __dll_thunk_init, but that would lead -// to false negatives in the startup code before user's global initializers, -// which isn't a big deal. -// Use .INTR segment to register function pointers that are iterated over during -// startup that will replace local_function with sanitizer_export. - -#define INTERCEPT_LIBRARY_FUNCTION(local_function, sanitizer_export) \ - extern "C" void local_function(); \ - static int intercept_##local_function() { \ - return __sanitizer::override_function( \ - sanitizer_export, \ - reinterpret_cast<__sanitizer::uptr>(local_function)); \ - } \ - __pragma(section(".INTR$M", long, read)) __declspec(allocate( \ - ".INTR$M")) int (*__sanitizer_static_thunk_##local_function)() = \ - intercept_##local_function; - -// ------------------ Weak symbol registration macros ---------------------- // -// Use .WEAK segment to register function pointers that are iterated over during -// startup that will replace sanitizer_export with local_function - -#define REGISTER_WEAK_FUNCTION(local_function) \ - extern "C" void local_function(); \ - extern "C" void WEAK_EXPORT_NAME(local_function)(); \ - WIN_WEAK_IMPORT_DEF(local_function) \ - __attribute__((optnone)) static int register_weak_##local_function() { \ - if ((uintptr_t) & local_function != (uintptr_t) & \ - WEAK_EXPORT_NAME(local_function)) { \ - return __sanitizer::register_weak( \ - SANITIZER_STRINGIFY(WEAK_EXPORT_NAME(local_function)), \ - reinterpret_cast<__sanitizer::uptr>(local_function)); \ - } \ - return 0; \ - } \ - __pragma(section(".WEAK$M", long, read)) __declspec(allocate( \ - ".WEAK$M")) int (*__sanitizer_register_weak_##local_function)() = \ - register_weak_##local_function; - -#endif // SANITIZER_WIN_STATIC_RUNTIME_THUNK_H diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_win_weak_interception.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_win_weak_interception.cpp new file mode 100644 index 0000000..b14bbf7 --- /dev/null +++ b/compiler-rt/lib/sanitizer_common/sanitizer_win_weak_interception.cpp @@ -0,0 +1,94 @@ +//===-- sanitizer_win_weak_interception.cpp -------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// 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_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 + +// Declare weak hooks. +extern "C" { +void __sanitizer_on_print(const char *str); +void __sanitizer_weak_hook_memcmp(uptr called_pc, const void *s1, + const void *s2, uptr n, int result); +void __sanitizer_weak_hook_strcmp(uptr called_pc, const char *s1, + const char *s2, int result); +void __sanitizer_weak_hook_strncmp(uptr called_pc, const char *s1, + const char *s2, uptr n, int result); +void __sanitizer_weak_hook_strstr(uptr called_pc, const char *s1, + const char *s2, char *result); +} + +// 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) +#pragma section(".WEAK$Z", read) + +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) +__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) +__declspec(allocate(".CRT$XLAB")) void(WINAPI *__weak_intercept_tls_init)( + void *, unsigned long, void *) = weak_intercept_thread_init; + +#endif // SANITIZER_WINDOWS && SANITIZER_DYNAMIC diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_win_weak_interception.h b/compiler-rt/lib/sanitizer_common/sanitizer_win_weak_interception.h new file mode 100644 index 0000000..5e4d8b8 --- /dev/null +++ b/compiler-rt/lib/sanitizer_common/sanitizer_win_weak_interception.h @@ -0,0 +1,32 @@ +//===-- sanitizer_win_weak_interception.h ---------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// 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 diff --git a/compiler-rt/lib/ubsan/CMakeLists.txt b/compiler-rt/lib/ubsan/CMakeLists.txt index 5d45a53..db0b33f 100644 --- a/compiler-rt/lib/ubsan/CMakeLists.txt +++ b/compiler-rt/lib/ubsan/CMakeLists.txt @@ -159,12 +159,33 @@ else() CFLAGS ${UBSAN_CXXFLAGS}) if (WIN32) - set(RUNTIME_THUNK_CFLAGS -DSANITIZER_DYNAMIC_RUNTIME_THUNK -DSANITIZER_STATIC_RUNTIME_THUNK) - add_compiler_rt_object_libraries(UbsanRuntimeThunk + add_compiler_rt_object_libraries(UbsanWeakInterception ${SANITIZER_COMMON_SUPPORTED_OS} ARCHS ${UBSAN_SUPPORTED_ARCH} SOURCES - ubsan_win_runtime_thunk.cpp + ubsan_win_weak_interception.cpp + CFLAGS ${UBSAN_CFLAGS} -DSANITIZER_DYNAMIC + DEFS ${UBSAN_COMMON_DEFINITIONS}) + + add_compiler_rt_object_libraries(UbsanDllThunk + ${SANITIZER_COMMON_SUPPORTED_OS} + ARCHS ${UBSAN_SUPPORTED_ARCH} + SOURCES + ubsan_win_dll_thunk.cpp + CFLAGS ${UBSAN_CFLAGS} -DSANITIZER_DLL_THUNK + DEFS ${UBSAN_COMMON_DEFINITIONS}) + + set(DYNAMIC_RUNTIME_THUNK_CFLAGS "-DSANITIZER_DYNAMIC_RUNTIME_THUNK") + if(MSVC) + list(APPEND DYNAMIC_RUNTIME_THUNK_CFLAGS "-Zl") + elseif(CMAKE_C_COMPILER_ID MATCHES Clang) + list(APPEND DYNAMIC_RUNTIME_THUNK_CFLAGS "-nodefaultlibs") + endif() + add_compiler_rt_object_libraries(UbsanDynamicRuntimeThunk + ${SANITIZER_COMMON_SUPPORTED_OS} + ARCHS ${UBSAN_SUPPORTED_ARCH} + SOURCES + ubsan_win_dynamic_runtime_thunk.cpp CFLAGS ${UBSAN_CFLAGS} ${DYNAMIC_RUNTIME_THUNK_CFLAGS} DEFS ${UBSAN_COMMON_DEFINITIONS}) endif() diff --git a/compiler-rt/lib/ubsan/ubsan_win_dll_thunk.cpp b/compiler-rt/lib/ubsan/ubsan_win_dll_thunk.cpp new file mode 100644 index 0000000..5ac7fc3 --- /dev/null +++ b/compiler-rt/lib/ubsan/ubsan_win_dll_thunk.cpp @@ -0,0 +1,20 @@ +//===-- ubsan_win_dll_thunk.cpp -------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file defines a family of thunks that should be statically linked into +// the DLLs that have instrumentation in order to delegate the calls to the +// shared runtime that lives in the main binary. +// See https://github.com/google/sanitizers/issues/209 for the details. +//===----------------------------------------------------------------------===// +#ifdef SANITIZER_DLL_THUNK +#include "sanitizer_common/sanitizer_win_dll_thunk.h" +// Ubsan interface functions. +#define INTERFACE_FUNCTION(Name) INTERCEPT_SANITIZER_FUNCTION(Name) +#define INTERFACE_WEAK_FUNCTION(Name) INTERCEPT_SANITIZER_WEAK_FUNCTION(Name) +#include "ubsan_interface.inc" +#endif // SANITIZER_DLL_THUNK diff --git a/compiler-rt/lib/ubsan/ubsan_win_runtime_thunk.cpp b/compiler-rt/lib/ubsan/ubsan_win_dynamic_runtime_thunk.cpp index 5ca7d6f..00722b4 100644 --- a/compiler-rt/lib/ubsan/ubsan_win_runtime_thunk.cpp +++ b/compiler-rt/lib/ubsan/ubsan_win_dynamic_runtime_thunk.cpp @@ -1,4 +1,4 @@ -//===-- ubsan_win_runtime_thunk.cpp ----------------------------- --===// +//===-- ubsan_win_dynamic_runtime_thunk.cpp -------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -10,14 +10,11 @@ // to interact with Ubsan, when it is included in a dll. // //===----------------------------------------------------------------------===// -#if defined(SANITIZER_DYNAMIC_RUNTIME_THUNK) || \ - defined(SANITIZER_STATIC_RUNTIME_THUNK) +#ifdef SANITIZER_DYNAMIC_RUNTIME_THUNK #define SANITIZER_IMPORT_INTERFACE 1 #include "sanitizer_common/sanitizer_win_defs.h" -#include "sanitizer_common/sanitizer_win_thunk_interception.h" // Define weak alias for all weak functions imported from ubsan. #define INTERFACE_FUNCTION(Name) -#define INTERFACE_WEAK_FUNCTION(Name) REGISTER_WEAK_FUNCTION(Name) +#define INTERFACE_WEAK_FUNCTION(Name) WIN_WEAK_IMPORT_DEF(Name) #include "ubsan_interface.inc" -#endif // defined(SANITIZER_DYNAMIC_RUNTIME_THUNK) || - // defined(SANITIZER_STATIC_RUNTIME_THUNK) +#endif // SANITIZER_DYNAMIC_RUNTIME_THUNK diff --git a/compiler-rt/lib/ubsan/ubsan_win_weak_interception.cpp b/compiler-rt/lib/ubsan/ubsan_win_weak_interception.cpp new file mode 100644 index 0000000..01db0c0 --- /dev/null +++ b/compiler-rt/lib/ubsan/ubsan_win_weak_interception.cpp @@ -0,0 +1,23 @@ +//===-- ubsan_win_weak_interception.cpp -----------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// 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" +#include "ubsan_monitor.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 diff --git a/compiler-rt/test/asan/TestCases/Darwin/interface_symbols_darwin.cpp b/compiler-rt/test/asan/TestCases/Darwin/interface_symbols_darwin.cpp index 59dca32..2cedbc7 100644 --- a/compiler-rt/test/asan/TestCases/Darwin/interface_symbols_darwin.cpp +++ b/compiler-rt/test/asan/TestCases/Darwin/interface_symbols_darwin.cpp @@ -35,9 +35,6 @@ // RUN: %p/../../../../lib/sanitizer_common/sanitizer_coverage_interface.inc \ // RUN: | grep -e "INTERFACE_\(WEAK_\)\?FUNCTION" \ // RUN: | grep -v "__sanitizer_weak_hook" \ -// RUN: | grep -v "__sanitizer_override_function" \ -// RUN: | grep -v "__sanitizer_override_function_by_addr" \ -// RUN: | grep -v "__sanitizer_register_weak_function" \ // RUN: | sed -e "s/.*(//" -e "s/).*//" > %t.imports // // RUN: cat %t.imports | sort | uniq > %t.imports-sorted diff --git a/compiler-rt/test/asan/TestCases/Linux/interface_symbols_linux.cpp b/compiler-rt/test/asan/TestCases/Linux/interface_symbols_linux.cpp index 2d72949..ce1255c 100644 --- a/compiler-rt/test/asan/TestCases/Linux/interface_symbols_linux.cpp +++ b/compiler-rt/test/asan/TestCases/Linux/interface_symbols_linux.cpp @@ -21,9 +21,6 @@ // RUN: %p/../../../../lib/sanitizer_common/sanitizer_coverage_interface.inc \ // RUN: | grep -e "INTERFACE_\(WEAK_\)\?FUNCTION" \ // RUN: | grep -v "__sanitizer_weak_hook" \ -// RUN: | grep -v "__sanitizer_override_function" \ -// RUN: | grep -v "__sanitizer_override_function_by_addr" \ -// RUN: | grep -v "__sanitizer_register_weak_function" \ // RUN: | sed -e "s/.*(//" -e "s/).*//" > %t.imports // // RUN: cat %t.imports | sort | uniq > %t.imports-sorted diff --git a/compiler-rt/test/asan/TestCases/Windows/double_free.cpp b/compiler-rt/test/asan/TestCases/Windows/double_free.cpp index 71c45e7..e288b40 100644 --- a/compiler-rt/test/asan/TestCases/Windows/double_free.cpp +++ b/compiler-rt/test/asan/TestCases/Windows/double_free.cpp @@ -9,13 +9,13 @@ int main() { free(x); // CHECK: AddressSanitizer: attempting double-free on [[ADDR:0x[0-9a-f]+]] // CHECK-NEXT: {{#0 .* free }} - // CHECK: {{ #[1-3] .* main .*double_free.cpp}}:[[@LINE-3]] + // CHECK: {{ #[1-2] .* main .*double_free.cpp}}:[[@LINE-3]] // CHECK: [[ADDR]] is located 0 bytes inside of 168-byte region // CHECK-LABEL: freed by thread T0 here: // CHECK-NEXT: {{#0 .* free }} - // CHECK: {{ #[1-3] .* main .*double_free.cpp}}:[[@LINE-8]] + // CHECK: {{ #[1-2] .* main .*double_free.cpp}}:[[@LINE-8]] // CHECK-LABEL: previously allocated by thread T0 here: // CHECK-NEXT: {{#0 .* malloc }} - // CHECK: {{ #[1-3] .* main .*double_free.cpp}}:[[@LINE-12]] + // CHECK: {{ #[1-2] .* main .*double_free.cpp}}:[[@LINE-12]] return 0; } diff --git a/compiler-rt/test/asan/TestCases/Windows/free_hook_realloc.cpp b/compiler-rt/test/asan/TestCases/Windows/free_hook_realloc.cpp index 297218b..11e8c99 100644 --- a/compiler-rt/test/asan/TestCases/Windows/free_hook_realloc.cpp +++ b/compiler-rt/test/asan/TestCases/Windows/free_hook_realloc.cpp @@ -5,6 +5,9 @@ // FIXME: merge this with the common free_hook_realloc test when we can run // common tests on Windows. +// FIXME: Doesn't work with DLLs +// XFAIL: win32-dynamic-asan + #include <stdlib.h> #include <io.h> #include <sanitizer/allocator_interface.h> diff --git a/compiler-rt/test/asan/TestCases/Windows/malloc_left_oob.cpp b/compiler-rt/test/asan/TestCases/Windows/malloc_left_oob.cpp index e5de226..7ea95d2 100644 --- a/compiler-rt/test/asan/TestCases/Windows/malloc_left_oob.cpp +++ b/compiler-rt/test/asan/TestCases/Windows/malloc_left_oob.cpp @@ -12,6 +12,6 @@ int main() { // CHECK: [[ADDR]] is located 1 bytes before 42-byte region // CHECK: allocated by thread T0 here: // CHECK-NEXT: {{#0 .* malloc }} - // CHECK: {{ #[1-3] .* main .*malloc_left_oob.cpp}}:[[@LINE-8]] + // CHECK: {{ #[1-2] .* main .*malloc_left_oob.cpp}}:[[@LINE-8]] free(buffer); } diff --git a/compiler-rt/test/asan/TestCases/Windows/malloc_right_oob.cpp b/compiler-rt/test/asan/TestCases/Windows/malloc_right_oob.cpp index 6007345..1495632 100644 --- a/compiler-rt/test/asan/TestCases/Windows/malloc_right_oob.cpp +++ b/compiler-rt/test/asan/TestCases/Windows/malloc_right_oob.cpp @@ -12,6 +12,6 @@ int main() { // CHECK: [[ADDR]] is located 0 bytes after 42-byte region // CHECK: allocated by thread T0 here: // CHECK-NEXT: {{#0 .* malloc }} - // CHECK: {{ #[1-3] .* main .*malloc_right_oob.cpp}}:[[@LINE-8]] + // CHECK: {{ #[1-2] .* main .*malloc_right_oob.cpp}}:[[@LINE-8]] free(buffer); } diff --git a/compiler-rt/test/asan/TestCases/Windows/malloc_uaf.cpp b/compiler-rt/test/asan/TestCases/Windows/malloc_uaf.cpp index 59a944c..d1eac7e 100644 --- a/compiler-rt/test/asan/TestCases/Windows/malloc_uaf.cpp +++ b/compiler-rt/test/asan/TestCases/Windows/malloc_uaf.cpp @@ -13,8 +13,8 @@ int main() { // CHECK: [[ADDR]] is located 0 bytes inside of 42-byte region // CHECK: freed by thread T0 here: // CHECK-NEXT: {{#0 .* free }} - // CHECK: {{ #[1-3] .* main .*malloc_uaf.cpp}}:[[@LINE-8]] + // CHECK: {{ #[1-2] .* main .*malloc_uaf.cpp}}:[[@LINE-8]] // CHECK: previously allocated by thread T0 here: // CHECK-NEXT: {{#0 .* malloc }} - // CHECK: {{ #[1-3] .* main .*malloc_uaf.cpp}}:[[@LINE-12]] + // CHECK: {{ #[1-2] .* main .*malloc_uaf.cpp}}:[[@LINE-12]] } diff --git a/compiler-rt/test/asan/TestCases/Windows/msvc/dll_and_lib.cpp b/compiler-rt/test/asan/TestCases/Windows/msvc/dll_and_lib.cpp index 175bdef..96fae6b 100644 --- a/compiler-rt/test/asan/TestCases/Windows/msvc/dll_and_lib.cpp +++ b/compiler-rt/test/asan/TestCases/Windows/msvc/dll_and_lib.cpp @@ -1,9 +1,10 @@ // Just make sure we can link an implib into another DLL // This used to fail between r212699 and r212814. // RUN: %clang_cl_asan -DCONFIG=1 %s -c -Fo%t.1.obj -// RUN: lld-link /nologo /DLL /OUT:%t.1.dll %t.1.obj %asan_lib %asan_thunk +// RUN: lld-link /nologo /DLL /OUT:%t.1.dll %t.1.obj %asan_dll_thunk // RUN: %clang_cl_asan -DCONFIG=2 %s -c -Fo%t.2.obj -// RUN: lld-link /nologo /DLL /OUT:%t.2.dll %t.2.obj %t.1.lib %asan_lib %asan_thunk +// RUN: lld-link /nologo /DLL /OUT:%t.2.dll %t.2.obj %t.1.lib %asan_dll_thunk +// REQUIRES: asan-static-runtime // REQUIRES: lld-available #if CONFIG==1 diff --git a/compiler-rt/test/asan/TestCases/Windows/msvc/dll_large_function.cpp b/compiler-rt/test/asan/TestCases/Windows/msvc/dll_large_function.cpp index f0c3dea..788488d 100644 --- a/compiler-rt/test/asan/TestCases/Windows/msvc/dll_large_function.cpp +++ b/compiler-rt/test/asan/TestCases/Windows/msvc/dll_large_function.cpp @@ -3,7 +3,8 @@ // from the DLL. We simulate the large function with // -mllvm -asan-instrumentation-with-call-threshold=0. // RUN: %clang_cl_asan %s -c -Fo%t.obj -mllvm -asan-instrumentation-with-call-threshold=0 -// RUN: lld-link /nologo /DLL /OUT:%t.dll %t.obj %asan_lib %asan_thunk +// RUN: lld-link /nologo /DLL /OUT:%t.dll %t.obj %asan_dll_thunk +// REQUIRES: asan-static-runtime // REQUIRES: lld-available void f(long* foo, long* bar) { diff --git a/compiler-rt/test/asan/TestCases/Windows/realloc_left_oob.cpp b/compiler-rt/test/asan/TestCases/Windows/realloc_left_oob.cpp index f1fd139..ebde5f1 100644 --- a/compiler-rt/test/asan/TestCases/Windows/realloc_left_oob.cpp +++ b/compiler-rt/test/asan/TestCases/Windows/realloc_left_oob.cpp @@ -12,6 +12,6 @@ int main() { // CHECK: [[ADDR]] is located 1 bytes before 42-byte region // CHECK: allocated by thread T0 here: // CHECK-NEXT: {{#0 .* realloc }} - // CHECK: {{ #[1-3] .* main .*realloc_left_oob.cpp}}:[[@LINE-8]] + // CHECK: {{ #[1-2] .* main .*realloc_left_oob.cpp}}:[[@LINE-8]] free(buffer); } diff --git a/compiler-rt/test/asan/TestCases/Windows/realloc_right_oob.cpp b/compiler-rt/test/asan/TestCases/Windows/realloc_right_oob.cpp index ea674f5..281efed 100644 --- a/compiler-rt/test/asan/TestCases/Windows/realloc_right_oob.cpp +++ b/compiler-rt/test/asan/TestCases/Windows/realloc_right_oob.cpp @@ -12,6 +12,6 @@ int main() { // CHECK: [[ADDR]] is located 0 bytes after 42-byte region // CHECK: allocated by thread T0 here: // CHECK-NEXT: {{#0 .* realloc }} - // CHECK: {{ #[1-3] .* main .*realloc_right_oob.cpp}}:[[@LINE-8]] + // CHECK: {{ #[1-2] .* main .*realloc_right_oob.cpp}}:[[@LINE-8]] free(buffer); } diff --git a/compiler-rt/test/asan/TestCases/Windows/realloc_uaf.cpp b/compiler-rt/test/asan/TestCases/Windows/realloc_uaf.cpp index 7d9c41e..6ff2217 100644 --- a/compiler-rt/test/asan/TestCases/Windows/realloc_uaf.cpp +++ b/compiler-rt/test/asan/TestCases/Windows/realloc_uaf.cpp @@ -13,8 +13,8 @@ int main() { // CHECK: [[ADDR]] is located 0 bytes inside of 42-byte region // CHECK: freed by thread T0 here: // CHECK-NEXT: {{#0 .* free }} - // CHECK: {{ #[1-3] .* main .*realloc_uaf.cpp}}:[[@LINE-8]] + // CHECK: {{ #[1-2] .* main .*realloc_uaf.cpp}}:[[@LINE-8]] // CHECK: previously allocated by thread T0 here: // CHECK-NEXT: {{#0 .* realloc }} - // CHECK: {{ #[1-3] .* main .*realloc_uaf.cpp}}:[[@LINE-12]] + // CHECK: {{ #[1-2] .* main .*realloc_uaf.cpp}}:[[@LINE-12]] } diff --git a/compiler-rt/test/asan/TestCases/Windows/symbols_path.cpp b/compiler-rt/test/asan/TestCases/Windows/symbols_path.cpp index 05437ab..be99c89 100644 --- a/compiler-rt/test/asan/TestCases/Windows/symbols_path.cpp +++ b/compiler-rt/test/asan/TestCases/Windows/symbols_path.cpp @@ -17,6 +17,6 @@ int main() { // CHECK: [[ADDR]] is located 1 bytes before 42-byte region // CHECK: allocated by thread T0 here: // CHECK-NEXT: {{#0 .* malloc}} - // CHECK: {{ #[1-3] .* main .*symbols_path.cpp}}:[[@LINE-8]] + // CHECK: {{ #[1-2] .* main .*symbols_path.cpp}}:[[@LINE-8]] free(buffer); } diff --git a/compiler-rt/test/asan/TestCases/Windows/unsymbolized.cpp b/compiler-rt/test/asan/TestCases/Windows/unsymbolized.cpp index 00428b8..0eb1e9e 100644 --- a/compiler-rt/test/asan/TestCases/Windows/unsymbolized.cpp +++ b/compiler-rt/test/asan/TestCases/Windows/unsymbolized.cpp @@ -4,7 +4,7 @@ // RUN: rm -f %t.pdb // RUN: %clangxx_asan -c -O2 %s -o %t.obj -// RUN: lld-link /nologo /OUT:%t.exe %t.obj -defaultlib:libcmt -nodefaultlib:msvcrt -defaultlib:oldnames %asan_static_runtime_thunk %asan_lib +// RUN: lld-link /nologo /OUT:%t.exe %t.obj %asan_lib %asan_cxx_lib // RUN: not %run %t.exe 2>&1 | FileCheck %s // REQUIRES: lld-available diff --git a/compiler-rt/test/asan/TestCases/Windows/use_after_realloc.cpp b/compiler-rt/test/asan/TestCases/Windows/use_after_realloc.cpp index 35947b3..4c32c63 100644 --- a/compiler-rt/test/asan/TestCases/Windows/use_after_realloc.cpp +++ b/compiler-rt/test/asan/TestCases/Windows/use_after_realloc.cpp @@ -15,9 +15,9 @@ int main() { // CHECK: [[ADDR]] is located 0 bytes inside of 32-byte region // CHECK: freed by thread T0 here: // CHECK-NEXT: {{#0 .* realloc }} - // CHECK: {{ #[1-3] .* main .*use_after_realloc.cpp}}:[[@LINE-9]] + // CHECK: {{ #[1-2] .* main .*use_after_realloc.cpp}}:[[@LINE-9]] // CHECK: previously allocated by thread T0 here: // CHECK-NEXT: {{#0 .* realloc }} - // CHECK: {{ #[1-3] .* main .*use_after_realloc.cpp}}:[[@LINE-14]] + // CHECK: {{ #[1-2] .* main .*use_after_realloc.cpp}}:[[@LINE-14]] free(buffer); } diff --git a/compiler-rt/test/asan/TestCases/debug_double_free.cpp b/compiler-rt/test/asan/TestCases/debug_double_free.cpp index 8a2ce40..de5ac7b 100644 --- a/compiler-rt/test/asan/TestCases/debug_double_free.cpp +++ b/compiler-rt/test/asan/TestCases/debug_double_free.cpp @@ -4,6 +4,9 @@ #include <stdio.h> #include <stdlib.h> +// FIXME: Doesn't work with DLLs +// XFAIL: win32-dynamic-asan + // If we use %p with MSVC, it comes out all upper case. Use %08x to get // lowercase hex. #ifdef _MSC_VER diff --git a/compiler-rt/test/asan/TestCases/debug_report.cpp b/compiler-rt/test/asan/TestCases/debug_report.cpp index 855642b..617b7ee 100644 --- a/compiler-rt/test/asan/TestCases/debug_report.cpp +++ b/compiler-rt/test/asan/TestCases/debug_report.cpp @@ -6,6 +6,9 @@ #include <stdio.h> #include <stdlib.h> +// FIXME: Doesn't work with DLLs +// XFAIL: win32-dynamic-asan + int main() { // Disable stderr buffering. Needed on Windows. setvbuf(stderr, NULL, _IONBF, 0); diff --git a/compiler-rt/test/asan/TestCases/default_options.cpp b/compiler-rt/test/asan/TestCases/default_options.cpp index 845e8a5..526dab6 100644 --- a/compiler-rt/test/asan/TestCases/default_options.cpp +++ b/compiler-rt/test/asan/TestCases/default_options.cpp @@ -1,7 +1,11 @@ // RUN: %clangxx_asan -O2 %s -o %t // RUN: %run %t 2>&1 | FileCheck %s +// FIXME: Doesn't work with DLLs +// XFAIL: win32-dynamic-asan + const char *kAsanDefaultOptions = "verbosity=1 help=1"; + // Required for dyld macOS 12.0+ #if (__APPLE__) __attribute__((weak)) diff --git a/compiler-rt/test/asan/TestCases/on_error_callback.cpp b/compiler-rt/test/asan/TestCases/on_error_callback.cpp index c38a36f0..f65a8f1 100644 --- a/compiler-rt/test/asan/TestCases/on_error_callback.cpp +++ b/compiler-rt/test/asan/TestCases/on_error_callback.cpp @@ -1,5 +1,8 @@ // RUN: %clangxx_asan -O2 %s -o %t && not %run %t 2>&1 | FileCheck %s +// FIXME: Doesn't work with DLLs +// XFAIL: win32-dynamic-asan + #include <stdio.h> #include <stdlib.h> diff --git a/compiler-rt/test/asan/TestCases/report_error_summary.cpp b/compiler-rt/test/asan/TestCases/report_error_summary.cpp index 9e024e3..d565d2a 100644 --- a/compiler-rt/test/asan/TestCases/report_error_summary.cpp +++ b/compiler-rt/test/asan/TestCases/report_error_summary.cpp @@ -1,5 +1,8 @@ // RUN: %clangxx_asan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s +// FIXME: Doesn't work with DLLs +// XFAIL: win32-dynamic-asan + #include <stdio.h> // Required for ld64 macOS 12.0+ diff --git a/compiler-rt/test/asan/lit.cfg.py b/compiler-rt/test/asan/lit.cfg.py index 05ed7e8..83b3cbe 100644 --- a/compiler-rt/test/asan/lit.cfg.py +++ b/compiler-rt/test/asan/lit.cfg.py @@ -130,11 +130,6 @@ if config.asan_dynamic: config.compiler_rt_libdir, "libclang_rt.asan_{}_dynamic.dylib".format(config.apple_platform), ) - elif config.host_os == "Windows": - shared_libasan_path = os.path.join( - config.compiler_rt_libdir, - "clang_rt.asan_dynamic-{}.lib".format(config.target_suffix), - ) else: lit_config.warning( "%shared_libasan substitution not set but dynamic ASan is available." @@ -183,22 +178,8 @@ if platform.system() == "Windows": base_lib = os.path.join( config.compiler_rt_libdir, "clang_rt.asan%%s%s.lib" % config.target_suffix ) - config.substitutions.append(("%asan_lib", base_lib % "_dynamic")) - if config.asan_dynamic: - config.substitutions.append( - ("%asan_thunk", base_lib % "_dynamic_runtime_thunk") - ) - else: - config.substitutions.append( - ("%asan_thunk", base_lib % "_static_runtime_thunk") - ) + config.substitutions.append(("%asan_lib", base_lib % "")) config.substitutions.append(("%asan_cxx_lib", base_lib % "_cxx")) - config.substitutions.append( - ("%asan_dynamic_runtime_thunk", base_lib % "_dynamic_runtime_thunk") - ) - config.substitutions.append( - ("%asan_static_runtime_thunk", base_lib % "_static_runtime_thunk") - ) config.substitutions.append(("%asan_dll_thunk", base_lib % "_dll_thunk")) else: # To make some of these tests work on MinGW target without changing their @@ -281,7 +262,7 @@ if ( # Add the RT libdir to PATH directly so that we can successfully run the gtest # binary to list its tests. -if config.host_os == "Windows": +if config.host_os == "Windows" and config.asan_dynamic: os.environ["PATH"] = os.path.pathsep.join( [config.compiler_rt_libdir, os.environ.get("PATH", "")] ) |