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