1//===-- asan_win_dll_thunk.cpp --------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file is a part of AddressSanitizer, an address sanity checker.
10//
11// This file defines a family of thunks that should be statically linked into
12// the DLLs that have ASan instrumentation in order to delegate the calls to the
13// shared runtime that lives in the main binary.
14// See https://github.com/google/sanitizers/issues/209 for the details.
15//===----------------------------------------------------------------------===//
16
17#ifdef SANITIZER_DLL_THUNK
18#include "asan_init_version.h"
19#include "interception/interception.h"
20#include "sanitizer_common/sanitizer_win_defs.h"
21#include "sanitizer_common/sanitizer_win_dll_thunk.h"
22#include "sanitizer_common/sanitizer_platform_interceptors.h"
23
24// ASan own interface functions.
25#define INTERFACE_FUNCTION(Name) INTERCEPT_SANITIZER_FUNCTION(Name)
26#define INTERFACE_WEAK_FUNCTION(Name) INTERCEPT_SANITIZER_WEAK_FUNCTION(Name)
27#include "asan_interface.inc"
28
29// Memory allocation functions.
30INTERCEPT_WRAP_V_W(free)
31INTERCEPT_WRAP_V_W(_free_base)
32INTERCEPT_WRAP_V_WW(_free_dbg)
33
34INTERCEPT_WRAP_W_W(malloc)
35INTERCEPT_WRAP_W_W(_malloc_base)
36INTERCEPT_WRAP_W_WWWW(_malloc_dbg)
37
38INTERCEPT_WRAP_W_WW(calloc)
39INTERCEPT_WRAP_W_WW(_calloc_base)
40INTERCEPT_WRAP_W_WWWWW(_calloc_dbg)
41INTERCEPT_WRAP_W_WWW(_calloc_impl)
42
43INTERCEPT_WRAP_W_WW(realloc)
44INTERCEPT_WRAP_W_WW(_realloc_base)
45INTERCEPT_WRAP_W_WWW(_realloc_dbg)
46INTERCEPT_WRAP_W_WWW(_recalloc)
47INTERCEPT_WRAP_W_WWW(_recalloc_base)
48
49INTERCEPT_WRAP_W_W(_msize)
50INTERCEPT_WRAP_W_W(_msize_base)
51INTERCEPT_WRAP_W_W(_expand)
52INTERCEPT_WRAP_W_W(_expand_dbg)
53
54// TODO(timurrrr): Might want to add support for _aligned_* allocation
55// functions to detect a bit more bugs.  Those functions seem to wrap malloc().
56
57// TODO(timurrrr): Do we need to add _Crt* stuff here? (see asan_malloc_win.cpp)
58
59#  if defined(_MSC_VER) && !defined(__clang__)
60// Disable warnings such as: 'void memchr(void)': incorrect number of arguments
61// for intrinsic function, expected '3' arguments.
62#    pragma warning(push)
63#    pragma warning(disable : 4392)
64#  endif
65
66INTERCEPT_LIBRARY_FUNCTION(atoi);
67INTERCEPT_LIBRARY_FUNCTION(atol);
68INTERCEPT_LIBRARY_FUNCTION(frexp);
69INTERCEPT_LIBRARY_FUNCTION(longjmp);
70#if SANITIZER_INTERCEPT_MEMCHR
71INTERCEPT_LIBRARY_FUNCTION(memchr);
72#endif
73INTERCEPT_LIBRARY_FUNCTION(memcmp);
74INTERCEPT_LIBRARY_FUNCTION(memcpy);
75INTERCEPT_LIBRARY_FUNCTION(memmove);
76INTERCEPT_LIBRARY_FUNCTION(memset);
77INTERCEPT_LIBRARY_FUNCTION(strcat);
78INTERCEPT_LIBRARY_FUNCTION(strchr);
79INTERCEPT_LIBRARY_FUNCTION(strcmp);
80INTERCEPT_LIBRARY_FUNCTION(strcpy);
81INTERCEPT_LIBRARY_FUNCTION(strcspn);
82INTERCEPT_LIBRARY_FUNCTION(strdup);
83INTERCEPT_LIBRARY_FUNCTION(strlen);
84INTERCEPT_LIBRARY_FUNCTION(strncat);
85INTERCEPT_LIBRARY_FUNCTION(strncmp);
86INTERCEPT_LIBRARY_FUNCTION(strncpy);
87INTERCEPT_LIBRARY_FUNCTION(strnlen);
88INTERCEPT_LIBRARY_FUNCTION(strpbrk);
89INTERCEPT_LIBRARY_FUNCTION(strrchr);
90INTERCEPT_LIBRARY_FUNCTION(strspn);
91INTERCEPT_LIBRARY_FUNCTION(strstr);
92INTERCEPT_LIBRARY_FUNCTION(strtok);
93INTERCEPT_LIBRARY_FUNCTION(strtol);
94INTERCEPT_LIBRARY_FUNCTION(wcslen);
95INTERCEPT_LIBRARY_FUNCTION(wcsnlen);
96
97#  if defined(_MSC_VER) && !defined(__clang__)
98#    pragma warning(pop)
99#  endif
100
101#ifdef _WIN64
102INTERCEPT_LIBRARY_FUNCTION(__C_specific_handler);
103#else
104INTERCEPT_LIBRARY_FUNCTION(_except_handler3);
105// _except_handler4 checks -GS cookie which is different for each module, so we
106// can't use INTERCEPT_LIBRARY_FUNCTION(_except_handler4).
107INTERCEPTOR(int, _except_handler4, void *a, void *b, void *c, void *d) {
108  __asan_handle_no_return();
109  return REAL(_except_handler4)(a, b, c, d);
110}
111#endif
112
113// Windows specific functions not included in asan_interface.inc.
114INTERCEPT_WRAP_W_V(__asan_should_detect_stack_use_after_return)
115INTERCEPT_WRAP_W_V(__asan_get_shadow_memory_dynamic_address)
116INTERCEPT_WRAP_W_W(__asan_unhandled_exception_filter)
117
118using namespace __sanitizer;
119
120extern "C" {
121int __asan_option_detect_stack_use_after_return;
122uptr __asan_shadow_memory_dynamic_address;
123} // extern "C"
124
125static int asan_dll_thunk_init() {
126  typedef void (*fntype)();
127  static fntype fn = 0;
128  // asan_dll_thunk_init is expected to be called by only one thread.
129  if (fn) return 0;
130
131  // Ensure all interception was executed.
132  __dll_thunk_init();
133
134  fn = (fntype) dllThunkGetRealAddrOrDie("__asan_init");
135  fn();
136  __asan_option_detect_stack_use_after_return =
137      (__asan_should_detect_stack_use_after_return() != 0);
138  __asan_shadow_memory_dynamic_address =
139      (uptr)__asan_get_shadow_memory_dynamic_address();
140
141#ifndef _WIN64
142  INTERCEPT_FUNCTION(_except_handler4);
143#endif
144  // In DLLs, the callbacks are expected to return 0,
145  // otherwise CRT initialization fails.
146  return 0;
147}
148
149#pragma section(".CRT$XIB", long, read)
150__declspec(allocate(".CRT$XIB")) int (*__asan_preinit)() = asan_dll_thunk_init;
151
152static void WINAPI asan_thread_init(void *mod, unsigned long reason,
153                                    void *reserved) {
154  if (reason == /*DLL_PROCESS_ATTACH=*/1) asan_dll_thunk_init();
155}
156
157#pragma section(".CRT$XLAB", long, read)
158__declspec(allocate(".CRT$XLAB")) void (WINAPI *__asan_tls_init)(void *,
159    unsigned long, void *) = asan_thread_init;
160
161WIN_FORCE_LINK(__asan_dso_reg_hook)
162
163#endif // SANITIZER_DLL_THUNK
164