xref: /freebsd/contrib/llvm-project/compiler-rt/lib/asan/asan_win_dll_thunk.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
168d75effSDimitry Andric //===-- asan_win_dll_thunk.cpp --------------------------------------------===//
268d75effSDimitry Andric //
368d75effSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
468d75effSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
568d75effSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
668d75effSDimitry Andric //
768d75effSDimitry Andric //===----------------------------------------------------------------------===//
868d75effSDimitry Andric //
968d75effSDimitry Andric // This file is a part of AddressSanitizer, an address sanity checker.
1068d75effSDimitry Andric //
1168d75effSDimitry Andric // This file defines a family of thunks that should be statically linked into
1268d75effSDimitry Andric // the DLLs that have ASan instrumentation in order to delegate the calls to the
1368d75effSDimitry Andric // shared runtime that lives in the main binary.
1468d75effSDimitry Andric // See https://github.com/google/sanitizers/issues/209 for the details.
1568d75effSDimitry Andric //===----------------------------------------------------------------------===//
1668d75effSDimitry Andric 
1768d75effSDimitry Andric #ifdef SANITIZER_DLL_THUNK
1868d75effSDimitry Andric #include "asan_init_version.h"
1968d75effSDimitry Andric #include "interception/interception.h"
2068d75effSDimitry Andric #include "sanitizer_common/sanitizer_win_defs.h"
2168d75effSDimitry Andric #include "sanitizer_common/sanitizer_win_dll_thunk.h"
2268d75effSDimitry Andric #include "sanitizer_common/sanitizer_platform_interceptors.h"
2368d75effSDimitry Andric 
2468d75effSDimitry Andric // ASan own interface functions.
2568d75effSDimitry Andric #define INTERFACE_FUNCTION(Name) INTERCEPT_SANITIZER_FUNCTION(Name)
2668d75effSDimitry Andric #define INTERFACE_WEAK_FUNCTION(Name) INTERCEPT_SANITIZER_WEAK_FUNCTION(Name)
2768d75effSDimitry Andric #include "asan_interface.inc"
2868d75effSDimitry Andric 
2968d75effSDimitry Andric // Memory allocation functions.
3068d75effSDimitry Andric INTERCEPT_WRAP_V_W(free)
3168d75effSDimitry Andric INTERCEPT_WRAP_V_W(_free_base)
3268d75effSDimitry Andric INTERCEPT_WRAP_V_WW(_free_dbg)
3368d75effSDimitry Andric 
3468d75effSDimitry Andric INTERCEPT_WRAP_W_W(malloc)
3568d75effSDimitry Andric INTERCEPT_WRAP_W_W(_malloc_base)
3668d75effSDimitry Andric INTERCEPT_WRAP_W_WWWW(_malloc_dbg)
3768d75effSDimitry Andric 
3868d75effSDimitry Andric INTERCEPT_WRAP_W_WW(calloc)
3968d75effSDimitry Andric INTERCEPT_WRAP_W_WW(_calloc_base)
4068d75effSDimitry Andric INTERCEPT_WRAP_W_WWWWW(_calloc_dbg)
4168d75effSDimitry Andric INTERCEPT_WRAP_W_WWW(_calloc_impl)
4268d75effSDimitry Andric 
4368d75effSDimitry Andric INTERCEPT_WRAP_W_WW(realloc)
4468d75effSDimitry Andric INTERCEPT_WRAP_W_WW(_realloc_base)
4568d75effSDimitry Andric INTERCEPT_WRAP_W_WWW(_realloc_dbg)
4668d75effSDimitry Andric INTERCEPT_WRAP_W_WWW(_recalloc)
4768d75effSDimitry Andric INTERCEPT_WRAP_W_WWW(_recalloc_base)
4868d75effSDimitry Andric 
4968d75effSDimitry Andric INTERCEPT_WRAP_W_W(_msize)
5068d75effSDimitry Andric INTERCEPT_WRAP_W_W(_msize_base)
5168d75effSDimitry Andric INTERCEPT_WRAP_W_W(_expand)
5268d75effSDimitry Andric INTERCEPT_WRAP_W_W(_expand_dbg)
5368d75effSDimitry Andric 
5468d75effSDimitry Andric // TODO(timurrrr): Might want to add support for _aligned_* allocation
5568d75effSDimitry Andric // functions to detect a bit more bugs.  Those functions seem to wrap malloc().
5668d75effSDimitry Andric 
5768d75effSDimitry Andric // TODO(timurrrr): Do we need to add _Crt* stuff here? (see asan_malloc_win.cpp)
5868d75effSDimitry Andric 
5904eeddc0SDimitry Andric #  if defined(_MSC_VER) && !defined(__clang__)
6004eeddc0SDimitry Andric // Disable warnings such as: 'void memchr(void)': incorrect number of arguments
6104eeddc0SDimitry Andric // for intrinsic function, expected '3' arguments.
6204eeddc0SDimitry Andric #    pragma warning(push)
6304eeddc0SDimitry Andric #    pragma warning(disable : 4392)
6404eeddc0SDimitry Andric #  endif
6504eeddc0SDimitry Andric 
6668d75effSDimitry Andric INTERCEPT_LIBRARY_FUNCTION(atoi);
6768d75effSDimitry Andric INTERCEPT_LIBRARY_FUNCTION(atol);
688a4dda33SDimitry Andric INTERCEPT_LIBRARY_FUNCTION(atoll);
6968d75effSDimitry Andric INTERCEPT_LIBRARY_FUNCTION(frexp);
7068d75effSDimitry Andric INTERCEPT_LIBRARY_FUNCTION(longjmp);
7168d75effSDimitry Andric #if SANITIZER_INTERCEPT_MEMCHR
7268d75effSDimitry Andric INTERCEPT_LIBRARY_FUNCTION(memchr);
7368d75effSDimitry Andric #endif
7468d75effSDimitry Andric INTERCEPT_LIBRARY_FUNCTION(memcmp);
7568d75effSDimitry Andric INTERCEPT_LIBRARY_FUNCTION(memcpy);
7668d75effSDimitry Andric INTERCEPT_LIBRARY_FUNCTION(memmove);
7768d75effSDimitry Andric INTERCEPT_LIBRARY_FUNCTION(memset);
7868d75effSDimitry Andric INTERCEPT_LIBRARY_FUNCTION(strcat);
7968d75effSDimitry Andric INTERCEPT_LIBRARY_FUNCTION(strchr);
8068d75effSDimitry Andric INTERCEPT_LIBRARY_FUNCTION(strcmp);
8168d75effSDimitry Andric INTERCEPT_LIBRARY_FUNCTION(strcpy);
8268d75effSDimitry Andric INTERCEPT_LIBRARY_FUNCTION(strcspn);
83*0fca6ea1SDimitry Andric INTERCEPT_LIBRARY_FUNCTION(_strdup);
8468d75effSDimitry Andric INTERCEPT_LIBRARY_FUNCTION(strlen);
8568d75effSDimitry Andric INTERCEPT_LIBRARY_FUNCTION(strncat);
8668d75effSDimitry Andric INTERCEPT_LIBRARY_FUNCTION(strncmp);
8768d75effSDimitry Andric INTERCEPT_LIBRARY_FUNCTION(strncpy);
8868d75effSDimitry Andric INTERCEPT_LIBRARY_FUNCTION(strnlen);
8968d75effSDimitry Andric INTERCEPT_LIBRARY_FUNCTION(strpbrk);
9068d75effSDimitry Andric INTERCEPT_LIBRARY_FUNCTION(strrchr);
9168d75effSDimitry Andric INTERCEPT_LIBRARY_FUNCTION(strspn);
9268d75effSDimitry Andric INTERCEPT_LIBRARY_FUNCTION(strstr);
9368d75effSDimitry Andric INTERCEPT_LIBRARY_FUNCTION(strtok);
9468d75effSDimitry Andric INTERCEPT_LIBRARY_FUNCTION(strtol);
958a4dda33SDimitry Andric INTERCEPT_LIBRARY_FUNCTION(strtoll);
9668d75effSDimitry Andric INTERCEPT_LIBRARY_FUNCTION(wcslen);
9768d75effSDimitry Andric INTERCEPT_LIBRARY_FUNCTION(wcsnlen);
9868d75effSDimitry Andric 
9904eeddc0SDimitry Andric #  if defined(_MSC_VER) && !defined(__clang__)
10004eeddc0SDimitry Andric #    pragma warning(pop)
10104eeddc0SDimitry Andric #  endif
10204eeddc0SDimitry Andric 
10368d75effSDimitry Andric #ifdef _WIN64
10468d75effSDimitry Andric INTERCEPT_LIBRARY_FUNCTION(__C_specific_handler);
10568d75effSDimitry Andric #else
10668d75effSDimitry Andric INTERCEPT_LIBRARY_FUNCTION(_except_handler3);
10768d75effSDimitry Andric // _except_handler4 checks -GS cookie which is different for each module, so we
10868d75effSDimitry Andric // can't use INTERCEPT_LIBRARY_FUNCTION(_except_handler4).
INTERCEPTOR(int,_except_handler4,void * a,void * b,void * c,void * d)10968d75effSDimitry Andric INTERCEPTOR(int, _except_handler4, void *a, void *b, void *c, void *d) {
11068d75effSDimitry Andric   __asan_handle_no_return();
11168d75effSDimitry Andric   return REAL(_except_handler4)(a, b, c, d);
11268d75effSDimitry Andric }
11368d75effSDimitry Andric #endif
11468d75effSDimitry Andric 
11568d75effSDimitry Andric // Windows specific functions not included in asan_interface.inc.
11668d75effSDimitry Andric INTERCEPT_WRAP_W_V(__asan_should_detect_stack_use_after_return)
11768d75effSDimitry Andric INTERCEPT_WRAP_W_V(__asan_get_shadow_memory_dynamic_address)
11868d75effSDimitry Andric INTERCEPT_WRAP_W_W(__asan_unhandled_exception_filter)
11968d75effSDimitry Andric 
12068d75effSDimitry Andric using namespace __sanitizer;
12168d75effSDimitry Andric 
12268d75effSDimitry Andric extern "C" {
12368d75effSDimitry Andric int __asan_option_detect_stack_use_after_return;
12468d75effSDimitry Andric uptr __asan_shadow_memory_dynamic_address;
12568d75effSDimitry Andric } // extern "C"
12668d75effSDimitry Andric 
asan_dll_thunk_init()12768d75effSDimitry Andric static int asan_dll_thunk_init() {
12868d75effSDimitry Andric   typedef void (*fntype)();
12968d75effSDimitry Andric   static fntype fn = 0;
13068d75effSDimitry Andric   // asan_dll_thunk_init is expected to be called by only one thread.
13168d75effSDimitry Andric   if (fn) return 0;
13268d75effSDimitry Andric 
13368d75effSDimitry Andric   // Ensure all interception was executed.
13468d75effSDimitry Andric   __dll_thunk_init();
13568d75effSDimitry Andric 
13668d75effSDimitry Andric   fn = (fntype) dllThunkGetRealAddrOrDie("__asan_init");
13768d75effSDimitry Andric   fn();
13868d75effSDimitry Andric   __asan_option_detect_stack_use_after_return =
13968d75effSDimitry Andric       (__asan_should_detect_stack_use_after_return() != 0);
14068d75effSDimitry Andric   __asan_shadow_memory_dynamic_address =
14168d75effSDimitry Andric       (uptr)__asan_get_shadow_memory_dynamic_address();
14268d75effSDimitry Andric 
14368d75effSDimitry Andric #ifndef _WIN64
14468d75effSDimitry Andric   INTERCEPT_FUNCTION(_except_handler4);
14568d75effSDimitry Andric #endif
14668d75effSDimitry Andric   // In DLLs, the callbacks are expected to return 0,
14768d75effSDimitry Andric   // otherwise CRT initialization fails.
14868d75effSDimitry Andric   return 0;
14968d75effSDimitry Andric }
15068d75effSDimitry Andric 
15168d75effSDimitry Andric #pragma section(".CRT$XIB", long, read)
15268d75effSDimitry Andric __declspec(allocate(".CRT$XIB")) int (*__asan_preinit)() = asan_dll_thunk_init;
15368d75effSDimitry Andric 
asan_thread_init(void * mod,unsigned long reason,void * reserved)15468d75effSDimitry Andric static void WINAPI asan_thread_init(void *mod, unsigned long reason,
15568d75effSDimitry Andric                                     void *reserved) {
15668d75effSDimitry Andric   if (reason == /*DLL_PROCESS_ATTACH=*/1) asan_dll_thunk_init();
15768d75effSDimitry Andric }
15868d75effSDimitry Andric 
15968d75effSDimitry Andric #pragma section(".CRT$XLAB", long, read)
16068d75effSDimitry Andric __declspec(allocate(".CRT$XLAB")) void (WINAPI *__asan_tls_init)(void *,
16168d75effSDimitry Andric     unsigned long, void *) = asan_thread_init;
16268d75effSDimitry Andric 
16368d75effSDimitry Andric WIN_FORCE_LINK(__asan_dso_reg_hook)
16468d75effSDimitry Andric 
16568d75effSDimitry Andric #endif // SANITIZER_DLL_THUNK
166