]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/compiler-rt/lib/asan/asan_win_dll_thunk.cc
Update compiler-rt to release_39 branch r288513. Since this contains a
[FreeBSD/FreeBSD.git] / contrib / compiler-rt / lib / asan / asan_win_dll_thunk.cc
1 //===-- asan_win_dll_thunk.cc ---------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file is a part of AddressSanitizer, an address sanity checker.
11 //
12 // This file defines a family of thunks that should be statically linked into
13 // the DLLs that have ASan instrumentation in order to delegate the calls to the
14 // shared runtime that lives in the main binary.
15 // See https://github.com/google/sanitizers/issues/209 for the details.
16 //===----------------------------------------------------------------------===//
17
18 // Only compile this code when buidling asan_dll_thunk.lib
19 // Using #ifdef rather than relying on Makefiles etc.
20 // simplifies the build procedure.
21 #ifdef ASAN_DLL_THUNK
22 #include "asan_init_version.h"
23 #include "interception/interception.h"
24 #include "sanitizer_common/sanitizer_platform_interceptors.h"
25
26 // ---------- Function interception helper functions and macros ----------- {{{1
27 extern "C" {
28 void *__stdcall GetModuleHandleA(const char *module_name);
29 void *__stdcall GetProcAddress(void *module, const char *proc_name);
30 void abort();
31 }
32
33 static uptr getRealProcAddressOrDie(const char *name) {
34   uptr ret =
35       __interception::InternalGetProcAddress((void *)GetModuleHandleA(0), name);
36   if (!ret)
37     abort();
38   return ret;
39 }
40
41 // We need to intercept some functions (e.g. ASan interface, memory allocator --
42 // let's call them "hooks") exported by the DLL thunk and forward the hooks to
43 // the runtime in the main module.
44 // However, we don't want to keep two lists of these hooks.
45 // To avoid that, the list of hooks should be defined using the
46 // INTERCEPT_WHEN_POSSIBLE macro. Then, all these hooks can be intercepted
47 // at once by calling INTERCEPT_HOOKS().
48
49 // Use macro+template magic to automatically generate the list of hooks.
50 // Each hook at line LINE defines a template class with a static
51 // FunctionInterceptor<LINE>::Execute() method intercepting the hook.
52 // The default implementation of FunctionInterceptor<LINE> is to call
53 // the Execute() method corresponding to the previous line.
54 template<int LINE>
55 struct FunctionInterceptor {
56   static void Execute() { FunctionInterceptor<LINE-1>::Execute(); }
57 };
58
59 // There shouldn't be any hooks with negative definition line number.
60 template<>
61 struct FunctionInterceptor<0> {
62   static void Execute() {}
63 };
64
65 #define INTERCEPT_WHEN_POSSIBLE(main_function, dll_function)                   \
66   template <> struct FunctionInterceptor<__LINE__> {                           \
67     static void Execute() {                                                    \
68       uptr wrapper = getRealProcAddressOrDie(main_function);                   \
69       if (!__interception::OverrideFunction((uptr)dll_function, wrapper, 0))   \
70         abort();                                                               \
71       FunctionInterceptor<__LINE__ - 1>::Execute();                            \
72     }                                                                          \
73   };
74
75 // Special case of hooks -- ASan own interface functions.  Those are only called
76 // after __asan_init, thus an empty implementation is sufficient.
77 #define INTERFACE_FUNCTION(name)                                               \
78   extern "C" __declspec(noinline) void name() {                                \
79     volatile int prevent_icf = (__LINE__ << 8); (void)prevent_icf;             \
80     __debugbreak();                                                            \
81   }                                                                            \
82   INTERCEPT_WHEN_POSSIBLE(#name, name)
83
84 // INTERCEPT_HOOKS must be used after the last INTERCEPT_WHEN_POSSIBLE.
85 #define INTERCEPT_HOOKS FunctionInterceptor<__LINE__>::Execute
86
87 // We can't define our own version of strlen etc. because that would lead to
88 // link-time or even type mismatch errors.  Instead, we can declare a function
89 // just to be able to get its address.  Me may miss the first few calls to the
90 // functions since it can be called before __asan_init, but that would lead to
91 // false negatives in the startup code before user's global initializers, which
92 // isn't a big deal.
93 #define INTERCEPT_LIBRARY_FUNCTION(name)                                       \
94   extern "C" void name();                                                      \
95   INTERCEPT_WHEN_POSSIBLE(WRAPPER_NAME(name), name)
96
97 // Disable compiler warnings that show up if we declare our own version
98 // of a compiler intrinsic (e.g. strlen).
99 #pragma warning(disable: 4391)
100 #pragma warning(disable: 4392)
101
102 static void InterceptHooks();
103 // }}}
104
105 // ---------- Function wrapping helpers ----------------------------------- {{{1
106 #define WRAP_V_V(name)                                                         \
107   extern "C" void name() {                                                     \
108     typedef void (*fntype)();                                                  \
109     static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
110     fn();                                                                      \
111   }                                                                            \
112   INTERCEPT_WHEN_POSSIBLE(#name, name);
113
114 #define WRAP_V_W(name)                                                         \
115   extern "C" void name(void *arg) {                                            \
116     typedef void (*fntype)(void *arg);                                         \
117     static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
118     fn(arg);                                                                   \
119   }                                                                            \
120   INTERCEPT_WHEN_POSSIBLE(#name, name);
121
122 #define WRAP_V_WW(name)                                                        \
123   extern "C" void name(void *arg1, void *arg2) {                               \
124     typedef void (*fntype)(void *, void *);                                    \
125     static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
126     fn(arg1, arg2);                                                            \
127   }                                                                            \
128   INTERCEPT_WHEN_POSSIBLE(#name, name);
129
130 #define WRAP_V_WWW(name)                                                       \
131   extern "C" void name(void *arg1, void *arg2, void *arg3) {                   \
132     typedef void *(*fntype)(void *, void *, void *);                           \
133     static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
134     fn(arg1, arg2, arg3);                                                      \
135   }                                                                            \
136   INTERCEPT_WHEN_POSSIBLE(#name, name);
137
138 #define WRAP_W_V(name)                                                         \
139   extern "C" void *name() {                                                    \
140     typedef void *(*fntype)();                                                 \
141     static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
142     return fn();                                                               \
143   }                                                                            \
144   INTERCEPT_WHEN_POSSIBLE(#name, name);
145
146 #define WRAP_W_W(name)                                                         \
147   extern "C" void *name(void *arg) {                                           \
148     typedef void *(*fntype)(void *arg);                                        \
149     static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
150     return fn(arg);                                                            \
151   }                                                                            \
152   INTERCEPT_WHEN_POSSIBLE(#name, name);
153
154 #define WRAP_W_WW(name)                                                        \
155   extern "C" void *name(void *arg1, void *arg2) {                              \
156     typedef void *(*fntype)(void *, void *);                                   \
157     static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
158     return fn(arg1, arg2);                                                     \
159   }                                                                            \
160   INTERCEPT_WHEN_POSSIBLE(#name, name);
161
162 #define WRAP_W_WWW(name)                                                       \
163   extern "C" void *name(void *arg1, void *arg2, void *arg3) {                  \
164     typedef void *(*fntype)(void *, void *, void *);                           \
165     static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
166     return fn(arg1, arg2, arg3);                                               \
167   }                                                                            \
168   INTERCEPT_WHEN_POSSIBLE(#name, name);
169
170 #define WRAP_W_WWWW(name)                                                      \
171   extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4) {      \
172     typedef void *(*fntype)(void *, void *, void *, void *);                   \
173     static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
174     return fn(arg1, arg2, arg3, arg4);                                         \
175   }                                                                            \
176   INTERCEPT_WHEN_POSSIBLE(#name, name);
177
178 #define WRAP_W_WWWWW(name)                                                     \
179   extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4,        \
180                         void *arg5) {                                          \
181     typedef void *(*fntype)(void *, void *, void *, void *, void *);           \
182     static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
183     return fn(arg1, arg2, arg3, arg4, arg5);                                   \
184   }                                                                            \
185   INTERCEPT_WHEN_POSSIBLE(#name, name);
186
187 #define WRAP_W_WWWWWW(name)                                                    \
188   extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4,        \
189                         void *arg5, void *arg6) {                              \
190     typedef void *(*fntype)(void *, void *, void *, void *, void *, void *);   \
191     static fntype fn = (fntype)getRealProcAddressOrDie(#name);                 \
192     return fn(arg1, arg2, arg3, arg4, arg5, arg6);                             \
193   }                                                                            \
194   INTERCEPT_WHEN_POSSIBLE(#name, name);
195 // }}}
196
197 // ----------------- ASan own interface functions --------------------
198 // Don't use the INTERFACE_FUNCTION machinery for this function as we actually
199 // want to call it in the __asan_init interceptor.
200 WRAP_W_V(__asan_should_detect_stack_use_after_return)
201
202 extern "C" {
203   int __asan_option_detect_stack_use_after_return;
204
205   // Manually wrap __asan_init as we need to initialize
206   // __asan_option_detect_stack_use_after_return afterwards.
207   void __asan_init() {
208     typedef void (*fntype)();
209     static fntype fn = 0;
210     // __asan_init is expected to be called by only one thread.
211     if (fn) return;
212
213     fn = (fntype)getRealProcAddressOrDie("__asan_init");
214     fn();
215     __asan_option_detect_stack_use_after_return =
216         (__asan_should_detect_stack_use_after_return() != 0);
217
218     InterceptHooks();
219   }
220 }
221
222 extern "C" void __asan_version_mismatch_check() {
223   // Do nothing.
224 }
225
226 INTERFACE_FUNCTION(__asan_handle_no_return)
227
228 INTERFACE_FUNCTION(__asan_report_store1)
229 INTERFACE_FUNCTION(__asan_report_store2)
230 INTERFACE_FUNCTION(__asan_report_store4)
231 INTERFACE_FUNCTION(__asan_report_store8)
232 INTERFACE_FUNCTION(__asan_report_store16)
233 INTERFACE_FUNCTION(__asan_report_store_n)
234
235 INTERFACE_FUNCTION(__asan_report_load1)
236 INTERFACE_FUNCTION(__asan_report_load2)
237 INTERFACE_FUNCTION(__asan_report_load4)
238 INTERFACE_FUNCTION(__asan_report_load8)
239 INTERFACE_FUNCTION(__asan_report_load16)
240 INTERFACE_FUNCTION(__asan_report_load_n)
241
242 INTERFACE_FUNCTION(__asan_store1)
243 INTERFACE_FUNCTION(__asan_store2)
244 INTERFACE_FUNCTION(__asan_store4)
245 INTERFACE_FUNCTION(__asan_store8)
246 INTERFACE_FUNCTION(__asan_store16)
247 INTERFACE_FUNCTION(__asan_storeN)
248
249 INTERFACE_FUNCTION(__asan_load1)
250 INTERFACE_FUNCTION(__asan_load2)
251 INTERFACE_FUNCTION(__asan_load4)
252 INTERFACE_FUNCTION(__asan_load8)
253 INTERFACE_FUNCTION(__asan_load16)
254 INTERFACE_FUNCTION(__asan_loadN)
255
256 INTERFACE_FUNCTION(__asan_memcpy);
257 INTERFACE_FUNCTION(__asan_memset);
258 INTERFACE_FUNCTION(__asan_memmove);
259
260 INTERFACE_FUNCTION(__asan_alloca_poison);
261 INTERFACE_FUNCTION(__asan_allocas_unpoison);
262
263 INTERFACE_FUNCTION(__asan_register_globals)
264 INTERFACE_FUNCTION(__asan_unregister_globals)
265
266 INTERFACE_FUNCTION(__asan_before_dynamic_init)
267 INTERFACE_FUNCTION(__asan_after_dynamic_init)
268
269 INTERFACE_FUNCTION(__asan_poison_stack_memory)
270 INTERFACE_FUNCTION(__asan_unpoison_stack_memory)
271
272 INTERFACE_FUNCTION(__asan_poison_memory_region)
273 INTERFACE_FUNCTION(__asan_unpoison_memory_region)
274
275 INTERFACE_FUNCTION(__asan_address_is_poisoned)
276 INTERFACE_FUNCTION(__asan_region_is_poisoned)
277
278 INTERFACE_FUNCTION(__asan_get_current_fake_stack)
279 INTERFACE_FUNCTION(__asan_addr_is_in_fake_stack)
280
281 INTERFACE_FUNCTION(__asan_stack_malloc_0)
282 INTERFACE_FUNCTION(__asan_stack_malloc_1)
283 INTERFACE_FUNCTION(__asan_stack_malloc_2)
284 INTERFACE_FUNCTION(__asan_stack_malloc_3)
285 INTERFACE_FUNCTION(__asan_stack_malloc_4)
286 INTERFACE_FUNCTION(__asan_stack_malloc_5)
287 INTERFACE_FUNCTION(__asan_stack_malloc_6)
288 INTERFACE_FUNCTION(__asan_stack_malloc_7)
289 INTERFACE_FUNCTION(__asan_stack_malloc_8)
290 INTERFACE_FUNCTION(__asan_stack_malloc_9)
291 INTERFACE_FUNCTION(__asan_stack_malloc_10)
292
293 INTERFACE_FUNCTION(__asan_stack_free_0)
294 INTERFACE_FUNCTION(__asan_stack_free_1)
295 INTERFACE_FUNCTION(__asan_stack_free_2)
296 INTERFACE_FUNCTION(__asan_stack_free_4)
297 INTERFACE_FUNCTION(__asan_stack_free_5)
298 INTERFACE_FUNCTION(__asan_stack_free_6)
299 INTERFACE_FUNCTION(__asan_stack_free_7)
300 INTERFACE_FUNCTION(__asan_stack_free_8)
301 INTERFACE_FUNCTION(__asan_stack_free_9)
302 INTERFACE_FUNCTION(__asan_stack_free_10)
303
304 // FIXME: we might want to have a sanitizer_win_dll_thunk?
305 INTERFACE_FUNCTION(__sanitizer_annotate_contiguous_container)
306 INTERFACE_FUNCTION(__sanitizer_contiguous_container_find_bad_address)
307 INTERFACE_FUNCTION(__sanitizer_cov)
308 INTERFACE_FUNCTION(__sanitizer_cov_dump)
309 INTERFACE_FUNCTION(__sanitizer_cov_indir_call16)
310 INTERFACE_FUNCTION(__sanitizer_cov_init)
311 INTERFACE_FUNCTION(__sanitizer_cov_module_init)
312 INTERFACE_FUNCTION(__sanitizer_cov_trace_basic_block)
313 INTERFACE_FUNCTION(__sanitizer_cov_trace_func_enter)
314 INTERFACE_FUNCTION(__sanitizer_cov_trace_cmp)
315 INTERFACE_FUNCTION(__sanitizer_cov_trace_switch)
316 INTERFACE_FUNCTION(__sanitizer_cov_with_check)
317 INTERFACE_FUNCTION(__sanitizer_get_allocated_size)
318 INTERFACE_FUNCTION(__sanitizer_get_coverage_guards)
319 INTERFACE_FUNCTION(__sanitizer_get_coverage_pc_buffer)
320 INTERFACE_FUNCTION(__sanitizer_get_current_allocated_bytes)
321 INTERFACE_FUNCTION(__sanitizer_get_estimated_allocated_size)
322 INTERFACE_FUNCTION(__sanitizer_get_free_bytes)
323 INTERFACE_FUNCTION(__sanitizer_get_heap_size)
324 INTERFACE_FUNCTION(__sanitizer_get_ownership)
325 INTERFACE_FUNCTION(__sanitizer_get_total_unique_caller_callee_pairs)
326 INTERFACE_FUNCTION(__sanitizer_get_total_unique_coverage)
327 INTERFACE_FUNCTION(__sanitizer_get_unmapped_bytes)
328 INTERFACE_FUNCTION(__sanitizer_maybe_open_cov_file)
329 INTERFACE_FUNCTION(__sanitizer_print_stack_trace)
330 INTERFACE_FUNCTION(__sanitizer_ptr_cmp)
331 INTERFACE_FUNCTION(__sanitizer_ptr_sub)
332 INTERFACE_FUNCTION(__sanitizer_report_error_summary)
333 INTERFACE_FUNCTION(__sanitizer_reset_coverage)
334 INTERFACE_FUNCTION(__sanitizer_get_number_of_counters)
335 INTERFACE_FUNCTION(__sanitizer_update_counter_bitset_and_clear_counters)
336 INTERFACE_FUNCTION(__sanitizer_sandbox_on_notify)
337 INTERFACE_FUNCTION(__sanitizer_set_death_callback)
338 INTERFACE_FUNCTION(__sanitizer_set_report_path)
339 INTERFACE_FUNCTION(__sanitizer_set_report_fd)
340 INTERFACE_FUNCTION(__sanitizer_unaligned_load16)
341 INTERFACE_FUNCTION(__sanitizer_unaligned_load32)
342 INTERFACE_FUNCTION(__sanitizer_unaligned_load64)
343 INTERFACE_FUNCTION(__sanitizer_unaligned_store16)
344 INTERFACE_FUNCTION(__sanitizer_unaligned_store32)
345 INTERFACE_FUNCTION(__sanitizer_unaligned_store64)
346 INTERFACE_FUNCTION(__sanitizer_verify_contiguous_container)
347 INTERFACE_FUNCTION(__sanitizer_install_malloc_and_free_hooks)
348 INTERFACE_FUNCTION(__sanitizer_start_switch_fiber)
349 INTERFACE_FUNCTION(__sanitizer_finish_switch_fiber)
350
351 // TODO(timurrrr): Add more interface functions on the as-needed basis.
352
353 // ----------------- Memory allocation functions ---------------------
354 WRAP_V_W(free)
355 WRAP_V_W(_free_base)
356 WRAP_V_WW(_free_dbg)
357
358 WRAP_W_W(malloc)
359 WRAP_W_W(_malloc_base)
360 WRAP_W_WWWW(_malloc_dbg)
361
362 WRAP_W_WW(calloc)
363 WRAP_W_WW(_calloc_base)
364 WRAP_W_WWWWW(_calloc_dbg)
365 WRAP_W_WWW(_calloc_impl)
366
367 WRAP_W_WW(realloc)
368 WRAP_W_WW(_realloc_base)
369 WRAP_W_WWW(_realloc_dbg)
370 WRAP_W_WWW(_recalloc)
371
372 WRAP_W_W(_msize)
373 WRAP_W_W(_expand)
374 WRAP_W_W(_expand_dbg)
375
376 // TODO(timurrrr): Might want to add support for _aligned_* allocation
377 // functions to detect a bit more bugs.  Those functions seem to wrap malloc().
378
379 // TODO(timurrrr): Do we need to add _Crt* stuff here? (see asan_malloc_win.cc).
380
381 INTERCEPT_LIBRARY_FUNCTION(atoi);
382 INTERCEPT_LIBRARY_FUNCTION(atol);
383
384 #ifdef _WIN64
385 INTERCEPT_LIBRARY_FUNCTION(__C_specific_handler);
386 #else
387 INTERCEPT_LIBRARY_FUNCTION(_except_handler3);
388
389 // _except_handler4 checks -GS cookie which is different for each module, so we
390 // can't use INTERCEPT_LIBRARY_FUNCTION(_except_handler4).
391 INTERCEPTOR(int, _except_handler4, void *a, void *b, void *c, void *d) {
392   __asan_handle_no_return();
393   return REAL(_except_handler4)(a, b, c, d);
394 }
395 #endif
396
397 INTERCEPT_LIBRARY_FUNCTION(frexp);
398 INTERCEPT_LIBRARY_FUNCTION(longjmp);
399 #if SANITIZER_INTERCEPT_MEMCHR
400 INTERCEPT_LIBRARY_FUNCTION(memchr);
401 #endif
402 INTERCEPT_LIBRARY_FUNCTION(memcmp);
403 INTERCEPT_LIBRARY_FUNCTION(memcpy);
404 INTERCEPT_LIBRARY_FUNCTION(memmove);
405 INTERCEPT_LIBRARY_FUNCTION(memset);
406 INTERCEPT_LIBRARY_FUNCTION(strcat);  // NOLINT
407 INTERCEPT_LIBRARY_FUNCTION(strchr);
408 INTERCEPT_LIBRARY_FUNCTION(strcmp);
409 INTERCEPT_LIBRARY_FUNCTION(strcpy);  // NOLINT
410 INTERCEPT_LIBRARY_FUNCTION(strcspn);
411 INTERCEPT_LIBRARY_FUNCTION(strdup);
412 INTERCEPT_LIBRARY_FUNCTION(strlen);
413 INTERCEPT_LIBRARY_FUNCTION(strncat);
414 INTERCEPT_LIBRARY_FUNCTION(strncmp);
415 INTERCEPT_LIBRARY_FUNCTION(strncpy);
416 INTERCEPT_LIBRARY_FUNCTION(strnlen);
417 INTERCEPT_LIBRARY_FUNCTION(strpbrk);
418 INTERCEPT_LIBRARY_FUNCTION(strrchr);
419 INTERCEPT_LIBRARY_FUNCTION(strspn);
420 INTERCEPT_LIBRARY_FUNCTION(strstr);
421 INTERCEPT_LIBRARY_FUNCTION(strtol);
422 INTERCEPT_LIBRARY_FUNCTION(wcslen);
423
424 // Must be after all the interceptor declarations due to the way INTERCEPT_HOOKS
425 // is defined.
426 void InterceptHooks() {
427   INTERCEPT_HOOKS();
428 #ifndef _WIN64
429   INTERCEPT_FUNCTION(_except_handler4);
430 #endif
431 }
432
433 // We want to call __asan_init before C/C++ initializers/constructors are
434 // executed, otherwise functions like memset might be invoked.
435 // For some strange reason, merely linking in asan_preinit.cc doesn't work
436 // as the callback is never called...  Is link.exe doing something too smart?
437
438 // In DLLs, the callbacks are expected to return 0,
439 // otherwise CRT initialization fails.
440 static int call_asan_init() {
441   __asan_init();
442   return 0;
443 }
444 #pragma section(".CRT$XIB", long, read)  // NOLINT
445 __declspec(allocate(".CRT$XIB")) int (*__asan_preinit)() = call_asan_init;
446
447 #endif // ASAN_DLL_THUNK