12f1c5ccdim//===-- asan_win_dll_thunk.cc ---------------------------------------------===//
22f1c5ccdim//
38312957dim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
48312957dim// See https://llvm.org/LICENSE.txt for license information.
58312957dim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
62f1c5ccdim//
72f1c5ccdim//===----------------------------------------------------------------------===//
82f1c5ccdim//
92f1c5ccdim// This file is a part of AddressSanitizer, an address sanity checker.
102f1c5ccdim//
112f1c5ccdim// This file defines a family of thunks that should be statically linked into
122f1c5ccdim// the DLLs that have ASan instrumentation in order to delegate the calls to the
132f1c5ccdim// shared runtime that lives in the main binary.
140d16d37dim// See https://github.com/google/sanitizers/issues/209 for the details.
152f1c5ccdim//===----------------------------------------------------------------------===//
162f1c5ccdim
176070792dim#ifdef SANITIZER_DLL_THUNK
182f1c5ccdim#include "asan_init_version.h"
192f1c5ccdim#include "interception/interception.h"
206070792dim#include "sanitizer_common/sanitizer_win_defs.h"
216070792dim#include "sanitizer_common/sanitizer_win_dll_thunk.h"
22906f157dim#include "sanitizer_common/sanitizer_platform_interceptors.h"
232f1c5ccdim
246070792dim// ASan own interface functions.
256070792dim#define INTERFACE_FUNCTION(Name) INTERCEPT_SANITIZER_FUNCTION(Name)
266070792dim#define INTERFACE_WEAK_FUNCTION(Name) INTERCEPT_SANITIZER_WEAK_FUNCTION(Name)
276070792dim#include "asan_interface.inc"
280d16d37dim
296070792dim// Memory allocation functions.
306070792dimINTERCEPT_WRAP_V_W(free)
316070792dimINTERCEPT_WRAP_V_W(_free_base)
326070792dimINTERCEPT_WRAP_V_WW(_free_dbg)
332f1c5ccdim
346070792dimINTERCEPT_WRAP_W_W(malloc)
356070792dimINTERCEPT_WRAP_W_W(_malloc_base)
366070792dimINTERCEPT_WRAP_W_WWWW(_malloc_dbg)
372f1c5ccdim
386070792dimINTERCEPT_WRAP_W_WW(calloc)
396070792dimINTERCEPT_WRAP_W_WW(_calloc_base)
406070792dimINTERCEPT_WRAP_W_WWWWW(_calloc_dbg)
416070792dimINTERCEPT_WRAP_W_WWW(_calloc_impl)
422f1c5ccdim
436070792dimINTERCEPT_WRAP_W_WW(realloc)
446070792dimINTERCEPT_WRAP_W_WW(_realloc_base)
456070792dimINTERCEPT_WRAP_W_WWW(_realloc_dbg)
466070792dimINTERCEPT_WRAP_W_WWW(_recalloc)
476070792dimINTERCEPT_WRAP_W_WWW(_recalloc_base)
482f1c5ccdim
496070792dimINTERCEPT_WRAP_W_W(_msize)
505c86f01dimINTERCEPT_WRAP_W_W(_msize_base)
516070792dimINTERCEPT_WRAP_W_W(_expand)
526070792dimINTERCEPT_WRAP_W_W(_expand_dbg)
532f1c5ccdim
542f1c5ccdim// TODO(timurrrr): Might want to add support for _aligned_* allocation
552f1c5ccdim// functions to detect a bit more bugs.  Those functions seem to wrap malloc().
562f1c5ccdim
572f1c5ccdim// TODO(timurrrr): Do we need to add _Crt* stuff here? (see asan_malloc_win.cc).
582f1c5ccdim
592f1c5ccdimINTERCEPT_LIBRARY_FUNCTION(atoi);
602f1c5ccdimINTERCEPT_LIBRARY_FUNCTION(atol);
612f1c5ccdimINTERCEPT_LIBRARY_FUNCTION(frexp);
622f1c5ccdimINTERCEPT_LIBRARY_FUNCTION(longjmp);
63906f157dim#if SANITIZER_INTERCEPT_MEMCHR
642f1c5ccdimINTERCEPT_LIBRARY_FUNCTION(memchr);
65906f157dim#endif
662f1c5ccdimINTERCEPT_LIBRARY_FUNCTION(memcmp);
672f1c5ccdimINTERCEPT_LIBRARY_FUNCTION(memcpy);
682f1c5ccdimINTERCEPT_LIBRARY_FUNCTION(memmove);
692f1c5ccdimINTERCEPT_LIBRARY_FUNCTION(memset);
702f1c5ccdimINTERCEPT_LIBRARY_FUNCTION(strcat);  // NOLINT
712f1c5ccdimINTERCEPT_LIBRARY_FUNCTION(strchr);
722f1c5ccdimINTERCEPT_LIBRARY_FUNCTION(strcmp);
732f1c5ccdimINTERCEPT_LIBRARY_FUNCTION(strcpy);  // NOLINT
743da1400dimINTERCEPT_LIBRARY_FUNCTION(strcspn);
75906f157dimINTERCEPT_LIBRARY_FUNCTION(strdup);
762f1c5ccdimINTERCEPT_LIBRARY_FUNCTION(strlen);
772f1c5ccdimINTERCEPT_LIBRARY_FUNCTION(strncat);
782f1c5ccdimINTERCEPT_LIBRARY_FUNCTION(strncmp);
792f1c5ccdimINTERCEPT_LIBRARY_FUNCTION(strncpy);
802f1c5ccdimINTERCEPT_LIBRARY_FUNCTION(strnlen);
813da1400dimINTERCEPT_LIBRARY_FUNCTION(strpbrk);
82906f157dimINTERCEPT_LIBRARY_FUNCTION(strrchr);
833da1400dimINTERCEPT_LIBRARY_FUNCTION(strspn);
843da1400dimINTERCEPT_LIBRARY_FUNCTION(strstr);
856070792dimINTERCEPT_LIBRARY_FUNCTION(strtok);
862f1c5ccdimINTERCEPT_LIBRARY_FUNCTION(strtol);
872f1c5ccdimINTERCEPT_LIBRARY_FUNCTION(wcslen);
88c932718dimINTERCEPT_LIBRARY_FUNCTION(wcsnlen);
892f1c5ccdim
906070792dim#ifdef _WIN64
916070792dimINTERCEPT_LIBRARY_FUNCTION(__C_specific_handler);
926070792dim#else
936070792dimINTERCEPT_LIBRARY_FUNCTION(_except_handler3);
946070792dim// _except_handler4 checks -GS cookie which is different for each module, so we
956070792dim// can't use INTERCEPT_LIBRARY_FUNCTION(_except_handler4).
966070792dimINTERCEPTOR(int, _except_handler4, void *a, void *b, void *c, void *d) {
976070792dim  __asan_handle_no_return();
986070792dim  return REAL(_except_handler4)(a, b, c, d);
992f1c5ccdim}
1006070792dim#endif
1012f1c5ccdim
1029419380dim// Windows specific functions not included in asan_interface.inc.
1036070792dimINTERCEPT_WRAP_W_V(__asan_should_detect_stack_use_after_return)
1046070792dimINTERCEPT_WRAP_W_V(__asan_get_shadow_memory_dynamic_address)
1056070792dimINTERCEPT_WRAP_W_W(__asan_unhandled_exception_filter)
1062f1c5ccdim
1076070792dimusing namespace __sanitizer;
1086070792dim
1096070792dimextern "C" {
1106070792dimint __asan_option_detect_stack_use_after_return;
1116070792dimuptr __asan_shadow_memory_dynamic_address;
1126070792dim} // extern "C"
1136070792dim
1146070792dimstatic int asan_dll_thunk_init() {
1156070792dim  typedef void (*fntype)();
1166070792dim  static fntype fn = 0;
1176070792dim  // asan_dll_thunk_init is expected to be called by only one thread.
1186070792dim  if (fn) return 0;
1196070792dim
1206070792dim  // Ensure all interception was executed.
1216070792dim  __dll_thunk_init();
1226070792dim
1236070792dim  fn = (fntype) dllThunkGetRealAddrOrDie("__asan_init");
1246070792dim  fn();
1256070792dim  __asan_option_detect_stack_use_after_return =
1266070792dim      (__asan_should_detect_stack_use_after_return() != 0);
1276070792dim  __asan_shadow_memory_dynamic_address =
1286070792dim      (uptr)__asan_get_shadow_memory_dynamic_address();
1296070792dim
1306070792dim#ifndef _WIN64
1316070792dim  INTERCEPT_FUNCTION(_except_handler4);
1326070792dim#endif
1336070792dim  // In DLLs, the callbacks are expected to return 0,
1346070792dim  // otherwise CRT initialization fails.
1352f1c5ccdim  return 0;
1362f1c5ccdim}
1376070792dim
1382f1c5ccdim#pragma section(".CRT$XIB", long, read)  // NOLINT
1396070792dim__declspec(allocate(".CRT$XIB")) int (*__asan_preinit)() = asan_dll_thunk_init;
1402f1c5ccdim
14124528c5dimstatic void WINAPI asan_thread_init(void *mod, unsigned long reason,
1426070792dim                                    void *reserved) {
1436070792dim  if (reason == /*DLL_PROCESS_ATTACH=*/1) asan_dll_thunk_init();
14424528c5dim}
14524528c5dim
14624528c5dim#pragma section(".CRT$XLAB", long, read)  // NOLINT
14724528c5dim__declspec(allocate(".CRT$XLAB")) void (WINAPI *__asan_tls_init)(void *,
14824528c5dim    unsigned long, void *) = asan_thread_init;
14924528c5dim
1506070792dimWIN_FORCE_LINK(__asan_dso_reg_hook)
15124528c5dim
1526070792dim#endif // SANITIZER_DLL_THUNK
153