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. |
30 | INTERCEPT_WRAP_V_W(free) |
31 | INTERCEPT_WRAP_V_W(_free_base) |
32 | INTERCEPT_WRAP_V_WW(_free_dbg) |
33 | |
34 | INTERCEPT_WRAP_W_W(malloc) |
35 | INTERCEPT_WRAP_W_W(_malloc_base) |
36 | INTERCEPT_WRAP_W_WWWW(_malloc_dbg) |
37 | |
38 | INTERCEPT_WRAP_W_WW(calloc) |
39 | INTERCEPT_WRAP_W_WW(_calloc_base) |
40 | INTERCEPT_WRAP_W_WWWWW(_calloc_dbg) |
41 | INTERCEPT_WRAP_W_WWW(_calloc_impl) |
42 | |
43 | INTERCEPT_WRAP_W_WW(realloc) |
44 | INTERCEPT_WRAP_W_WW(_realloc_base) |
45 | INTERCEPT_WRAP_W_WWW(_realloc_dbg) |
46 | INTERCEPT_WRAP_W_WWW(_recalloc) |
47 | INTERCEPT_WRAP_W_WWW(_recalloc_base) |
48 | |
49 | INTERCEPT_WRAP_W_W(_msize) |
50 | INTERCEPT_WRAP_W_W(_msize_base) |
51 | INTERCEPT_WRAP_W_W(_expand) |
52 | INTERCEPT_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 | |
66 | INTERCEPT_LIBRARY_FUNCTION(atoi); |
67 | INTERCEPT_LIBRARY_FUNCTION(atol); |
68 | INTERCEPT_LIBRARY_FUNCTION(atoll); |
69 | INTERCEPT_LIBRARY_FUNCTION(frexp); |
70 | INTERCEPT_LIBRARY_FUNCTION(longjmp); |
71 | #if SANITIZER_INTERCEPT_MEMCHR |
72 | INTERCEPT_LIBRARY_FUNCTION(memchr); |
73 | #endif |
74 | INTERCEPT_LIBRARY_FUNCTION(memcmp); |
75 | INTERCEPT_LIBRARY_FUNCTION(memcpy); |
76 | INTERCEPT_LIBRARY_FUNCTION(memmove); |
77 | INTERCEPT_LIBRARY_FUNCTION(memset); |
78 | INTERCEPT_LIBRARY_FUNCTION(strcat); |
79 | INTERCEPT_LIBRARY_FUNCTION(strchr); |
80 | INTERCEPT_LIBRARY_FUNCTION(strcmp); |
81 | INTERCEPT_LIBRARY_FUNCTION(strcpy); |
82 | INTERCEPT_LIBRARY_FUNCTION(strcspn); |
83 | INTERCEPT_LIBRARY_FUNCTION(_strdup); |
84 | INTERCEPT_LIBRARY_FUNCTION(strlen); |
85 | INTERCEPT_LIBRARY_FUNCTION(strncat); |
86 | INTERCEPT_LIBRARY_FUNCTION(strncmp); |
87 | INTERCEPT_LIBRARY_FUNCTION(strncpy); |
88 | INTERCEPT_LIBRARY_FUNCTION(strnlen); |
89 | INTERCEPT_LIBRARY_FUNCTION(strpbrk); |
90 | INTERCEPT_LIBRARY_FUNCTION(strrchr); |
91 | INTERCEPT_LIBRARY_FUNCTION(strspn); |
92 | INTERCEPT_LIBRARY_FUNCTION(strstr); |
93 | INTERCEPT_LIBRARY_FUNCTION(strtok); |
94 | INTERCEPT_LIBRARY_FUNCTION(strtol); |
95 | INTERCEPT_LIBRARY_FUNCTION(strtoll); |
96 | INTERCEPT_LIBRARY_FUNCTION(wcslen); |
97 | INTERCEPT_LIBRARY_FUNCTION(wcsnlen); |
98 | |
99 | # if defined(_MSC_VER) && !defined(__clang__) |
100 | # pragma warning(pop) |
101 | # endif |
102 | |
103 | #ifdef _WIN64 |
104 | INTERCEPT_LIBRARY_FUNCTION(__C_specific_handler); |
105 | #else |
106 | INTERCEPT_LIBRARY_FUNCTION(_except_handler3); |
107 | // _except_handler4 checks -GS cookie which is different for each module, so we |
108 | // can't use INTERCEPT_LIBRARY_FUNCTION(_except_handler4). |
109 | INTERCEPTOR(int, _except_handler4, void *a, void *b, void *c, void *d) { |
110 | __asan_handle_no_return(); |
111 | return REAL(_except_handler4)(a, b, c, d); |
112 | } |
113 | #endif |
114 | |
115 | // Windows specific functions not included in asan_interface.inc. |
116 | INTERCEPT_WRAP_W_V(__asan_should_detect_stack_use_after_return) |
117 | INTERCEPT_WRAP_W_V(__asan_get_shadow_memory_dynamic_address) |
118 | INTERCEPT_WRAP_W_W(__asan_unhandled_exception_filter) |
119 | |
120 | using namespace __sanitizer; |
121 | |
122 | extern "C" { |
123 | int __asan_option_detect_stack_use_after_return; |
124 | uptr __asan_shadow_memory_dynamic_address; |
125 | } // extern "C" |
126 | |
127 | static int asan_dll_thunk_init() { |
128 | typedef void (*fntype)(); |
129 | static fntype fn = 0; |
130 | // asan_dll_thunk_init is expected to be called by only one thread. |
131 | if (fn) return 0; |
132 | |
133 | // Ensure all interception was executed. |
134 | __dll_thunk_init(); |
135 | |
136 | fn = (fntype) dllThunkGetRealAddrOrDie("__asan_init" ); |
137 | fn(); |
138 | __asan_option_detect_stack_use_after_return = |
139 | (__asan_should_detect_stack_use_after_return() != 0); |
140 | __asan_shadow_memory_dynamic_address = |
141 | (uptr)__asan_get_shadow_memory_dynamic_address(); |
142 | |
143 | #ifndef _WIN64 |
144 | INTERCEPT_FUNCTION(_except_handler4); |
145 | #endif |
146 | // In DLLs, the callbacks are expected to return 0, |
147 | // otherwise CRT initialization fails. |
148 | return 0; |
149 | } |
150 | |
151 | #pragma section(".CRT$XIB", long, read) |
152 | __declspec(allocate(".CRT$XIB" )) int (*__asan_preinit)() = asan_dll_thunk_init; |
153 | |
154 | static void WINAPI asan_thread_init(void *mod, unsigned long reason, |
155 | void *reserved) { |
156 | if (reason == /*DLL_PROCESS_ATTACH=*/1) asan_dll_thunk_init(); |
157 | } |
158 | |
159 | #pragma section(".CRT$XLAB", long, read) |
160 | __declspec(allocate(".CRT$XLAB" )) void (WINAPI *__asan_tls_init)(void *, |
161 | unsigned long, void *) = asan_thread_init; |
162 | |
163 | WIN_FORCE_LINK(__asan_dso_reg_hook) |
164 | |
165 | #endif // SANITIZER_DLL_THUNK |
166 | |