| //===-- 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(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(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 |