diff options
author | Jakub Jelinek <jakub@redhat.com> | 2017-10-19 13:23:59 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@gcc.gnu.org> | 2017-10-19 13:23:59 +0200 |
commit | 5d3805fca3e9a199fbaa18aee3c05ecb30ebca61 (patch) | |
tree | 22f091462fe7932142888d43abb6ff39f610e7f7 /libsanitizer/asan/asan_win_dll_thunk.cc | |
parent | 93659712d9807d7ef01d472dc58119f4ac15cbad (diff) | |
download | gcc-5d3805fca3e9a199fbaa18aee3c05ecb30ebca61.zip gcc-5d3805fca3e9a199fbaa18aee3c05ecb30ebca61.tar.gz gcc-5d3805fca3e9a199fbaa18aee3c05ecb30ebca61.tar.bz2 |
ubsan.c (ubsan_expand_null_ifn): Use _v1 suffixed type mismatch builtins...
* ubsan.c (ubsan_expand_null_ifn): Use _v1 suffixed type mismatch
builtins, store max (log2 (align), 0) into uchar field instead of
align into uptr field.
(ubsan_expand_objsize_ifn): Use _v1 suffixed type mismatch builtins,
store uchar 0 field instead of uptr 0 field.
(instrument_nonnull_return): Use _v1 suffixed nonnull return builtin,
instead of passing one address of struct with 2 locations pass
two addresses of structs with 1 location each.
* sanitizer.def (BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH,
BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_ABORT,
BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN,
BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_ABORT): Removed.
(BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_V1,
BUILT_IN_UBSAN_HANDLE_TYPE_MISMATCH_V1_ABORT,
BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_V1,
BUILT_IN_UBSAN_HANDLE_NONNULL_RETURN_V1_ABORT): New builtins.
* c-c++-common/ubsan/float-cast-overflow-1.c: Drop value keyword
from expected output regexps.
* c-c++-common/ubsan/float-cast-overflow-2.c: Likewise.
* c-c++-common/ubsan/float-cast-overflow-3.c: Likewise.
* c-c++-common/ubsan/float-cast-overflow-4.c: Likewise.
* c-c++-common/ubsan/float-cast-overflow-5.c: Likewise.
* c-c++-common/ubsan/float-cast-overflow-6.c: Likewise.
* c-c++-common/ubsan/float-cast-overflow-8.c: Likewise.
* c-c++-common/ubsan/float-cast-overflow-9.c: Likewise.
* c-c++-common/ubsan/float-cast-overflow-10.c: Likewise.
* g++.dg/ubsan/float-cast-overflow-bf.C: Likewise.
* gcc.dg/ubsan/float-cast-overflow-bf.c: Likewise.
* g++.dg/asan/default-options-1.C (__asan_default_options): Add
used attribute.
* g++.dg/asan/asan_test.C: Run with ASAN_OPTIONS=handle_segv=2
in the environment.
* All source files: Merge from upstream 315899.
* asan/Makefile.am (nodist_saninclude_HEADERS): Add
include/sanitizer/tsan_interface.h.
* asan/libtool-version: Bump the libasan SONAME.
* lsan/Makefile.am (sanitizer_lsan_files): Add lsan_common_mac.cc.
(lsan_files): Add lsan_linux.cc, lsan_mac.cc and lsan_malloc_mac.cc.
* sanitizer_common/Makefile.am (sanitizer_common_files): Add
sancov_flags.cc, sanitizer_allocator_checks.cc,
sanitizer_coverage_libcdep_new.cc, sanitizer_errno.cc,
sanitizer_file.cc, sanitizer_mac_libcdep.cc and
sanitizer_stoptheworld_mac.cc. Remove sanitizer_coverage_libcdep.cc
and sanitizer_coverage_mapping_libcdep.cc.
* tsan/Makefile.am (tsan_files): Add tsan_external.cc.
* ubsan/Makefile.am (DEFS): Add -DUBSAN_CAN_USE_CXXABI=1.
(ubsan_files): Add ubsan_init_standalone.cc and
ubsan_signals_standalone.cc.
* ubsan/libtool-version: Bump the libubsan SONAME.
* asan/Makefile.in: Regenerate.
* lsan/Makefile.in: Regenerate.
* sanitizer_common/Makefile.in: Regenerate.
* tsan/Makefile.in: Regenerate.
* ubsan/Makefile.in: Regenerate.
From-SVN: r253887
Diffstat (limited to 'libsanitizer/asan/asan_win_dll_thunk.cc')
-rw-r--r-- | libsanitizer/asan/asan_win_dll_thunk.cc | 473 |
1 files changed, 83 insertions, 390 deletions
diff --git a/libsanitizer/asan/asan_win_dll_thunk.cc b/libsanitizer/asan/asan_win_dll_thunk.cc index f7c9a37..31847efe 100644 --- a/libsanitizer/asan/asan_win_dll_thunk.cc +++ b/libsanitizer/asan/asan_win_dll_thunk.cc @@ -13,375 +13,41 @@ // See https://github.com/google/sanitizers/issues/209 for the details. //===----------------------------------------------------------------------===// -// Only compile this code when building asan_dll_thunk.lib -// Using #ifdef rather than relying on Makefiles etc. -// simplifies the build procedure. -#ifdef ASAN_DLL_THUNK +#ifdef SANITIZER_DLL_THUNK #include "asan_init_version.h" #include "interception/interception.h" +#include "sanitizer_common/sanitizer_win_defs.h" +#include "sanitizer_common/sanitizer_win_dll_thunk.h" #include "sanitizer_common/sanitizer_platform_interceptors.h" -// ---------- Function interception helper functions and macros ----------- {{{1 -extern "C" { -void *__stdcall GetModuleHandleA(const char *module_name); -void *__stdcall GetProcAddress(void *module, const char *proc_name); -void abort(); -} - -using namespace __sanitizer; - -static uptr getRealProcAddressOrDie(const char *name) { - uptr ret = - __interception::InternalGetProcAddress((void *)GetModuleHandleA(0), name); - if (!ret) - abort(); - return ret; -} - -// We need to intercept some functions (e.g. ASan interface, memory allocator -- -// let's call them "hooks") exported by the DLL thunk and forward the hooks to -// the runtime in the main module. -// However, we don't want to keep two lists of these hooks. -// To avoid that, the list of hooks should be defined using the -// INTERCEPT_WHEN_POSSIBLE macro. Then, all these hooks can be intercepted -// at once by calling INTERCEPT_HOOKS(). - -// Use macro+template magic to automatically generate the list of hooks. -// Each hook at line LINE defines a template class with a static -// FunctionInterceptor<LINE>::Execute() method intercepting the hook. -// The default implementation of FunctionInterceptor<LINE> is to call -// the Execute() method corresponding to the previous line. -template<int LINE> -struct FunctionInterceptor { - static void Execute() { FunctionInterceptor<LINE-1>::Execute(); } -}; - -// There shouldn't be any hooks with negative definition line number. -template<> -struct FunctionInterceptor<0> { - static void Execute() {} -}; - -#define INTERCEPT_WHEN_POSSIBLE(main_function, dll_function) \ - template <> struct FunctionInterceptor<__LINE__> { \ - static void Execute() { \ - uptr wrapper = getRealProcAddressOrDie(main_function); \ - if (!__interception::OverrideFunction((uptr)dll_function, wrapper, 0)) \ - abort(); \ - FunctionInterceptor<__LINE__ - 1>::Execute(); \ - } \ - }; - -// Special case of hooks -- ASan own interface functions. Those are only called -// after __asan_init, thus an empty implementation is sufficient. -#define INTERFACE_FUNCTION(name) \ - extern "C" __declspec(noinline) void name() { \ - volatile int prevent_icf = (__LINE__ << 8); (void)prevent_icf; \ - __debugbreak(); \ - } \ - INTERCEPT_WHEN_POSSIBLE(#name, name) - -// INTERCEPT_HOOKS must be used after the last INTERCEPT_WHEN_POSSIBLE. -#define INTERCEPT_HOOKS FunctionInterceptor<__LINE__>::Execute - -// We can't define our own version of strlen etc. because that would lead to -// link-time or even type mismatch errors. Instead, we can declare a function -// just to be able to get its address. Me may miss the first few calls to the -// functions since it can be called before __asan_init, but that would lead to -// false negatives in the startup code before user's global initializers, which -// isn't a big deal. -#define INTERCEPT_LIBRARY_FUNCTION(name) \ - extern "C" void name(); \ - INTERCEPT_WHEN_POSSIBLE(WRAPPER_NAME(name), name) - -// Disable compiler warnings that show up if we declare our own version -// of a compiler intrinsic (e.g. strlen). -#pragma warning(disable: 4391) -#pragma warning(disable: 4392) - -static void InterceptHooks(); -// }}} - -// ---------- Function wrapping helpers ----------------------------------- {{{1 -#define WRAP_V_V(name) \ - extern "C" void name() { \ - typedef void (*fntype)(); \ - static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ - fn(); \ - } \ - INTERCEPT_WHEN_POSSIBLE(#name, name); - -#define WRAP_V_W(name) \ - extern "C" void name(void *arg) { \ - typedef void (*fntype)(void *arg); \ - static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ - fn(arg); \ - } \ - INTERCEPT_WHEN_POSSIBLE(#name, name); - -#define WRAP_V_WW(name) \ - extern "C" void name(void *arg1, void *arg2) { \ - typedef void (*fntype)(void *, void *); \ - static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ - fn(arg1, arg2); \ - } \ - INTERCEPT_WHEN_POSSIBLE(#name, name); - -#define WRAP_V_WWW(name) \ - extern "C" void name(void *arg1, void *arg2, void *arg3) { \ - typedef void *(*fntype)(void *, void *, void *); \ - static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ - fn(arg1, arg2, arg3); \ - } \ - INTERCEPT_WHEN_POSSIBLE(#name, name); - -#define WRAP_W_V(name) \ - extern "C" void *name() { \ - typedef void *(*fntype)(); \ - static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ - return fn(); \ - } \ - INTERCEPT_WHEN_POSSIBLE(#name, name); - -#define WRAP_W_W(name) \ - extern "C" void *name(void *arg) { \ - typedef void *(*fntype)(void *arg); \ - static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ - return fn(arg); \ - } \ - INTERCEPT_WHEN_POSSIBLE(#name, name); - -#define WRAP_W_WW(name) \ - extern "C" void *name(void *arg1, void *arg2) { \ - typedef void *(*fntype)(void *, void *); \ - static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ - return fn(arg1, arg2); \ - } \ - INTERCEPT_WHEN_POSSIBLE(#name, name); - -#define WRAP_W_WWW(name) \ - extern "C" void *name(void *arg1, void *arg2, void *arg3) { \ - typedef void *(*fntype)(void *, void *, void *); \ - static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ - return fn(arg1, arg2, arg3); \ - } \ - INTERCEPT_WHEN_POSSIBLE(#name, name); - -#define WRAP_W_WWWW(name) \ - extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4) { \ - typedef void *(*fntype)(void *, void *, void *, void *); \ - static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ - return fn(arg1, arg2, arg3, arg4); \ - } \ - INTERCEPT_WHEN_POSSIBLE(#name, name); - -#define WRAP_W_WWWWW(name) \ - extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4, \ - void *arg5) { \ - typedef void *(*fntype)(void *, void *, void *, void *, void *); \ - static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ - return fn(arg1, arg2, arg3, arg4, arg5); \ - } \ - INTERCEPT_WHEN_POSSIBLE(#name, name); - -#define WRAP_W_WWWWWW(name) \ - extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4, \ - void *arg5, void *arg6) { \ - typedef void *(*fntype)(void *, void *, void *, void *, void *, void *); \ - static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ - return fn(arg1, arg2, arg3, arg4, arg5, arg6); \ - } \ - INTERCEPT_WHEN_POSSIBLE(#name, name); -// }}} - -// ----------------- ASan own interface functions -------------------- -// Don't use the INTERFACE_FUNCTION machinery for this function as we actually -// want to call it in the __asan_init interceptor. -WRAP_W_V(__asan_should_detect_stack_use_after_return) -WRAP_W_V(__asan_get_shadow_memory_dynamic_address) - -extern "C" { - int __asan_option_detect_stack_use_after_return; - uptr __asan_shadow_memory_dynamic_address; - - // Manually wrap __asan_init as we need to initialize - // __asan_option_detect_stack_use_after_return afterwards. - void __asan_init() { - typedef void (*fntype)(); - static fntype fn = 0; - // __asan_init is expected to be called by only one thread. - if (fn) return; - - fn = (fntype)getRealProcAddressOrDie("__asan_init"); - fn(); - __asan_option_detect_stack_use_after_return = - (__asan_should_detect_stack_use_after_return() != 0); - __asan_shadow_memory_dynamic_address = - (uptr)__asan_get_shadow_memory_dynamic_address(); - InterceptHooks(); - } -} - -extern "C" void __asan_version_mismatch_check() { - // Do nothing. -} - -INTERFACE_FUNCTION(__asan_handle_no_return) - -INTERFACE_FUNCTION(__asan_report_store1) -INTERFACE_FUNCTION(__asan_report_store2) -INTERFACE_FUNCTION(__asan_report_store4) -INTERFACE_FUNCTION(__asan_report_store8) -INTERFACE_FUNCTION(__asan_report_store16) -INTERFACE_FUNCTION(__asan_report_store_n) - -INTERFACE_FUNCTION(__asan_report_load1) -INTERFACE_FUNCTION(__asan_report_load2) -INTERFACE_FUNCTION(__asan_report_load4) -INTERFACE_FUNCTION(__asan_report_load8) -INTERFACE_FUNCTION(__asan_report_load16) -INTERFACE_FUNCTION(__asan_report_load_n) - -INTERFACE_FUNCTION(__asan_store1) -INTERFACE_FUNCTION(__asan_store2) -INTERFACE_FUNCTION(__asan_store4) -INTERFACE_FUNCTION(__asan_store8) -INTERFACE_FUNCTION(__asan_store16) -INTERFACE_FUNCTION(__asan_storeN) - -INTERFACE_FUNCTION(__asan_load1) -INTERFACE_FUNCTION(__asan_load2) -INTERFACE_FUNCTION(__asan_load4) -INTERFACE_FUNCTION(__asan_load8) -INTERFACE_FUNCTION(__asan_load16) -INTERFACE_FUNCTION(__asan_loadN) - -INTERFACE_FUNCTION(__asan_memcpy); -INTERFACE_FUNCTION(__asan_memset); -INTERFACE_FUNCTION(__asan_memmove); - -INTERFACE_FUNCTION(__asan_set_shadow_00); -INTERFACE_FUNCTION(__asan_set_shadow_f1); -INTERFACE_FUNCTION(__asan_set_shadow_f2); -INTERFACE_FUNCTION(__asan_set_shadow_f3); -INTERFACE_FUNCTION(__asan_set_shadow_f5); -INTERFACE_FUNCTION(__asan_set_shadow_f8); - -INTERFACE_FUNCTION(__asan_alloca_poison); -INTERFACE_FUNCTION(__asan_allocas_unpoison); - -INTERFACE_FUNCTION(__asan_register_globals) -INTERFACE_FUNCTION(__asan_unregister_globals) - -INTERFACE_FUNCTION(__asan_before_dynamic_init) -INTERFACE_FUNCTION(__asan_after_dynamic_init) - -INTERFACE_FUNCTION(__asan_poison_stack_memory) -INTERFACE_FUNCTION(__asan_unpoison_stack_memory) +// ASan own interface functions. +#define INTERFACE_FUNCTION(Name) INTERCEPT_SANITIZER_FUNCTION(Name) +#define INTERFACE_WEAK_FUNCTION(Name) INTERCEPT_SANITIZER_WEAK_FUNCTION(Name) +#include "asan_interface.inc" -INTERFACE_FUNCTION(__asan_poison_memory_region) -INTERFACE_FUNCTION(__asan_unpoison_memory_region) +// Memory allocation functions. +INTERCEPT_WRAP_V_W(free) +INTERCEPT_WRAP_V_W(_free_base) +INTERCEPT_WRAP_V_WW(_free_dbg) -INTERFACE_FUNCTION(__asan_address_is_poisoned) -INTERFACE_FUNCTION(__asan_region_is_poisoned) +INTERCEPT_WRAP_W_W(malloc) +INTERCEPT_WRAP_W_W(_malloc_base) +INTERCEPT_WRAP_W_WWWW(_malloc_dbg) -INTERFACE_FUNCTION(__asan_get_current_fake_stack) -INTERFACE_FUNCTION(__asan_addr_is_in_fake_stack) +INTERCEPT_WRAP_W_WW(calloc) +INTERCEPT_WRAP_W_WW(_calloc_base) +INTERCEPT_WRAP_W_WWWWW(_calloc_dbg) +INTERCEPT_WRAP_W_WWW(_calloc_impl) -INTERFACE_FUNCTION(__asan_stack_malloc_0) -INTERFACE_FUNCTION(__asan_stack_malloc_1) -INTERFACE_FUNCTION(__asan_stack_malloc_2) -INTERFACE_FUNCTION(__asan_stack_malloc_3) -INTERFACE_FUNCTION(__asan_stack_malloc_4) -INTERFACE_FUNCTION(__asan_stack_malloc_5) -INTERFACE_FUNCTION(__asan_stack_malloc_6) -INTERFACE_FUNCTION(__asan_stack_malloc_7) -INTERFACE_FUNCTION(__asan_stack_malloc_8) -INTERFACE_FUNCTION(__asan_stack_malloc_9) -INTERFACE_FUNCTION(__asan_stack_malloc_10) +INTERCEPT_WRAP_W_WW(realloc) +INTERCEPT_WRAP_W_WW(_realloc_base) +INTERCEPT_WRAP_W_WWW(_realloc_dbg) +INTERCEPT_WRAP_W_WWW(_recalloc) +INTERCEPT_WRAP_W_WWW(_recalloc_base) -INTERFACE_FUNCTION(__asan_stack_free_0) -INTERFACE_FUNCTION(__asan_stack_free_1) -INTERFACE_FUNCTION(__asan_stack_free_2) -INTERFACE_FUNCTION(__asan_stack_free_4) -INTERFACE_FUNCTION(__asan_stack_free_5) -INTERFACE_FUNCTION(__asan_stack_free_6) -INTERFACE_FUNCTION(__asan_stack_free_7) -INTERFACE_FUNCTION(__asan_stack_free_8) -INTERFACE_FUNCTION(__asan_stack_free_9) -INTERFACE_FUNCTION(__asan_stack_free_10) - -// FIXME: we might want to have a sanitizer_win_dll_thunk? -INTERFACE_FUNCTION(__sanitizer_annotate_contiguous_container) -INTERFACE_FUNCTION(__sanitizer_contiguous_container_find_bad_address) -INTERFACE_FUNCTION(__sanitizer_cov) -INTERFACE_FUNCTION(__sanitizer_cov_dump) -INTERFACE_FUNCTION(__sanitizer_cov_indir_call16) -INTERFACE_FUNCTION(__sanitizer_cov_init) -INTERFACE_FUNCTION(__sanitizer_cov_module_init) -INTERFACE_FUNCTION(__sanitizer_cov_trace_basic_block) -INTERFACE_FUNCTION(__sanitizer_cov_trace_func_enter) -INTERFACE_FUNCTION(__sanitizer_cov_with_check) -INTERFACE_FUNCTION(__sanitizer_get_allocated_size) -INTERFACE_FUNCTION(__sanitizer_get_coverage_guards) -INTERFACE_FUNCTION(__sanitizer_get_current_allocated_bytes) -INTERFACE_FUNCTION(__sanitizer_get_estimated_allocated_size) -INTERFACE_FUNCTION(__sanitizer_get_free_bytes) -INTERFACE_FUNCTION(__sanitizer_get_heap_size) -INTERFACE_FUNCTION(__sanitizer_get_ownership) -INTERFACE_FUNCTION(__sanitizer_get_total_unique_caller_callee_pairs) -INTERFACE_FUNCTION(__sanitizer_get_total_unique_coverage) -INTERFACE_FUNCTION(__sanitizer_get_unmapped_bytes) -INTERFACE_FUNCTION(__sanitizer_maybe_open_cov_file) -INTERFACE_FUNCTION(__sanitizer_print_stack_trace) -INTERFACE_FUNCTION(__sanitizer_symbolize_pc) -INTERFACE_FUNCTION(__sanitizer_symbolize_global) -INTERFACE_FUNCTION(__sanitizer_ptr_cmp) -INTERFACE_FUNCTION(__sanitizer_ptr_sub) -INTERFACE_FUNCTION(__sanitizer_report_error_summary) -INTERFACE_FUNCTION(__sanitizer_reset_coverage) -INTERFACE_FUNCTION(__sanitizer_get_number_of_counters) -INTERFACE_FUNCTION(__sanitizer_update_counter_bitset_and_clear_counters) -INTERFACE_FUNCTION(__sanitizer_sandbox_on_notify) -INTERFACE_FUNCTION(__sanitizer_set_death_callback) -INTERFACE_FUNCTION(__sanitizer_set_report_path) -INTERFACE_FUNCTION(__sanitizer_set_report_fd) -INTERFACE_FUNCTION(__sanitizer_unaligned_load16) -INTERFACE_FUNCTION(__sanitizer_unaligned_load32) -INTERFACE_FUNCTION(__sanitizer_unaligned_load64) -INTERFACE_FUNCTION(__sanitizer_unaligned_store16) -INTERFACE_FUNCTION(__sanitizer_unaligned_store32) -INTERFACE_FUNCTION(__sanitizer_unaligned_store64) -INTERFACE_FUNCTION(__sanitizer_verify_contiguous_container) -INTERFACE_FUNCTION(__sanitizer_install_malloc_and_free_hooks) -INTERFACE_FUNCTION(__sanitizer_start_switch_fiber) -INTERFACE_FUNCTION(__sanitizer_finish_switch_fiber) - -// TODO(timurrrr): Add more interface functions on the as-needed basis. - -// ----------------- Memory allocation functions --------------------- -WRAP_V_W(free) -WRAP_V_W(_free_base) -WRAP_V_WW(_free_dbg) - -WRAP_W_W(malloc) -WRAP_W_W(_malloc_base) -WRAP_W_WWWW(_malloc_dbg) - -WRAP_W_WW(calloc) -WRAP_W_WW(_calloc_base) -WRAP_W_WWWWW(_calloc_dbg) -WRAP_W_WWW(_calloc_impl) - -WRAP_W_WW(realloc) -WRAP_W_WW(_realloc_base) -WRAP_W_WWW(_realloc_dbg) -WRAP_W_WWW(_recalloc) -WRAP_W_WWW(_recalloc_base) - -WRAP_W_W(_msize) -WRAP_W_W(_expand) -WRAP_W_W(_expand_dbg) +INTERCEPT_WRAP_W_W(_msize) +INTERCEPT_WRAP_W_W(_expand) +INTERCEPT_WRAP_W_W(_expand_dbg) // TODO(timurrrr): Might want to add support for _aligned_* allocation // functions to detect a bit more bugs. Those functions seem to wrap malloc(). @@ -390,20 +56,6 @@ WRAP_W_W(_expand_dbg) INTERCEPT_LIBRARY_FUNCTION(atoi); INTERCEPT_LIBRARY_FUNCTION(atol); - -#ifdef _WIN64 -INTERCEPT_LIBRARY_FUNCTION(__C_specific_handler); -#else -INTERCEPT_LIBRARY_FUNCTION(_except_handler3); - -// _except_handler4 checks -GS cookie which is different for each module, so we -// can't use INTERCEPT_LIBRARY_FUNCTION(_except_handler4). -INTERCEPTOR(int, _except_handler4, void *a, void *b, void *c, void *d) { - __asan_handle_no_return(); - return REAL(_except_handler4)(a, b, c, d); -} -#endif - INTERCEPT_LIBRARY_FUNCTION(frexp); INTERCEPT_LIBRARY_FUNCTION(longjmp); #if SANITIZER_INTERCEPT_MEMCHR @@ -428,30 +80,71 @@ INTERCEPT_LIBRARY_FUNCTION(strpbrk); INTERCEPT_LIBRARY_FUNCTION(strrchr); INTERCEPT_LIBRARY_FUNCTION(strspn); INTERCEPT_LIBRARY_FUNCTION(strstr); +INTERCEPT_LIBRARY_FUNCTION(strtok); INTERCEPT_LIBRARY_FUNCTION(strtol); INTERCEPT_LIBRARY_FUNCTION(wcslen); +INTERCEPT_LIBRARY_FUNCTION(wcsnlen); + +#ifdef _WIN64 +INTERCEPT_LIBRARY_FUNCTION(__C_specific_handler); +#else +INTERCEPT_LIBRARY_FUNCTION(_except_handler3); +// _except_handler4 checks -GS cookie which is different for each module, so we +// can't use INTERCEPT_LIBRARY_FUNCTION(_except_handler4). +INTERCEPTOR(int, _except_handler4, void *a, void *b, void *c, void *d) { + __asan_handle_no_return(); + return REAL(_except_handler4)(a, b, c, d); +} +#endif + +// Window specific functions not included in asan_interface.inc. +INTERCEPT_WRAP_W_V(__asan_should_detect_stack_use_after_return) +INTERCEPT_WRAP_W_V(__asan_get_shadow_memory_dynamic_address) +INTERCEPT_WRAP_W_W(__asan_unhandled_exception_filter) + +using namespace __sanitizer; + +extern "C" { +int __asan_option_detect_stack_use_after_return; +uptr __asan_shadow_memory_dynamic_address; +} // extern "C" + +static int asan_dll_thunk_init() { + typedef void (*fntype)(); + static fntype fn = 0; + // asan_dll_thunk_init is expected to be called by only one thread. + if (fn) return 0; + + // Ensure all interception was executed. + __dll_thunk_init(); + + fn = (fntype) dllThunkGetRealAddrOrDie("__asan_init"); + fn(); + __asan_option_detect_stack_use_after_return = + (__asan_should_detect_stack_use_after_return() != 0); + __asan_shadow_memory_dynamic_address = + (uptr)__asan_get_shadow_memory_dynamic_address(); -// Must be after all the interceptor declarations due to the way INTERCEPT_HOOKS -// is defined. -void InterceptHooks() { - INTERCEPT_HOOKS(); #ifndef _WIN64 INTERCEPT_FUNCTION(_except_handler4); #endif + // In DLLs, the callbacks are expected to return 0, + // otherwise CRT initialization fails. + return 0; } -// We want to call __asan_init before C/C++ initializers/constructors are -// executed, otherwise functions like memset might be invoked. -// For some strange reason, merely linking in asan_preinit.cc doesn't work -// as the callback is never called... Is link.exe doing something too smart? +#pragma section(".CRT$XIB", long, read) // NOLINT +__declspec(allocate(".CRT$XIB")) int (*__asan_preinit)() = asan_dll_thunk_init; -// In DLLs, the callbacks are expected to return 0, -// otherwise CRT initialization fails. -static int call_asan_init() { - __asan_init(); - return 0; +static void WINAPI asan_thread_init(void *mod, unsigned long reason, + void *reserved) { + if (reason == /*DLL_PROCESS_ATTACH=*/1) asan_dll_thunk_init(); } -#pragma section(".CRT$XIB", long, read) // NOLINT -__declspec(allocate(".CRT$XIB")) int (*__asan_preinit)() = call_asan_init; -#endif // ASAN_DLL_THUNK +#pragma section(".CRT$XLAB", long, read) // NOLINT +__declspec(allocate(".CRT$XLAB")) void (WINAPI *__asan_tls_init)(void *, + unsigned long, void *) = asan_thread_init; + +WIN_FORCE_LINK(__asan_dso_reg_hook) + +#endif // SANITIZER_DLL_THUNK |