Index: lib/asan/asan_win_dll_thunk.cc =================================================================== --- lib/asan/asan_win_dll_thunk.cc +++ lib/asan/asan_win_dll_thunk.cc @@ -47,13 +47,18 @@ return ret; } +static uptr getRealProcAddress(const char *name) { + return + __interception::InternalGetProcAddress((void *)GetModuleHandleA(0), name); +} + // 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(). +// INTERCEPT_[OR_DIE|WHEN_POSSIBLE] macros. 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 @@ -71,7 +76,8 @@ static void Execute() {} }; -#define INTERCEPT_WHEN_POSSIBLE(main_function, dll_function) \ +// Override dll_function with main_function from main executable. +#define INTERCEPT_OR_DIE(main_function, dll_function) \ template <> struct FunctionInterceptor<__LINE__> { \ static void Execute() { \ uptr wrapper = getRealProcAddressOrDie(main_function); \ @@ -81,6 +87,20 @@ } \ }; +// Try to override dll_function with main_function from main executable. +// If main_function is not present, override dll_function with default_function. +#define INTERCEPT_WHEN_POSSIBLE(main_function, default_function, dll_function) \ + template <> struct FunctionInterceptor<__LINE__> { \ + static void Execute() { \ + uptr wrapper = getRealProcAddress(#main_function); \ + if (! wrapper) \ + wrapper = getRealProcAddressOrDie(#default_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) \ @@ -88,9 +108,20 @@ volatile int prevent_icf = (__LINE__ << 8); (void)prevent_icf; \ __debugbreak(); \ } \ - INTERCEPT_WHEN_POSSIBLE(#name, name) + INTERCEPT_OR_DIE(#name, name) + +// Special case of hooks -- Weak functions, could be redefined in the main +// executable, but that is not necessary, so we shouldn't die if we can not find +// a reference. Instead, when the function is not present in the main executable +// we consider the default impl provided by asan library. +#define INTERFACE_WEAK_FUNCTION(name) \ + extern "C" __declspec(noinline) void name() { \ + volatile int prevent_icf = (__LINE__ << 8); (void)prevent_icf; \ + __debugbreak(); \ + } \ + INTERCEPT_WHEN_POSSIBLE(name, WEAK_DEF_NAME(name), name) -// INTERCEPT_HOOKS must be used after the last INTERCEPT_WHEN_POSSIBLE. +// INTERCEPT_HOOKS must be used after the last INTERCEPT_OR_DIE. #define INTERCEPT_HOOKS FunctionInterceptor<__LINE__>::Execute // We can't define our own version of strlen etc. because that would lead to @@ -101,7 +132,7 @@ // isn't a big deal. #define INTERCEPT_LIBRARY_FUNCTION(name) \ extern "C" void name(); \ - INTERCEPT_WHEN_POSSIBLE(WRAPPER_NAME(name), name) + INTERCEPT_OR_DIE(WRAPPER_NAME(name), name) // Disable compiler warnings that show up if we declare our own version // of a compiler intrinsic (e.g. strlen). @@ -118,7 +149,7 @@ static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ fn(); \ } \ - INTERCEPT_WHEN_POSSIBLE(#name, name); + INTERCEPT_OR_DIE(#name, name); #define WRAP_V_W(name) \ extern "C" void name(void *arg) { \ @@ -126,7 +157,7 @@ static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ fn(arg); \ } \ - INTERCEPT_WHEN_POSSIBLE(#name, name); + INTERCEPT_OR_DIE(#name, name); #define WRAP_V_WW(name) \ extern "C" void name(void *arg1, void *arg2) { \ @@ -134,7 +165,7 @@ static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ fn(arg1, arg2); \ } \ - INTERCEPT_WHEN_POSSIBLE(#name, name); + INTERCEPT_OR_DIE(#name, name); #define WRAP_V_WWW(name) \ extern "C" void name(void *arg1, void *arg2, void *arg3) { \ @@ -142,7 +173,7 @@ static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ fn(arg1, arg2, arg3); \ } \ - INTERCEPT_WHEN_POSSIBLE(#name, name); + INTERCEPT_OR_DIE(#name, name); #define WRAP_W_V(name) \ extern "C" void *name() { \ @@ -150,7 +181,7 @@ static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ return fn(); \ } \ - INTERCEPT_WHEN_POSSIBLE(#name, name); + INTERCEPT_OR_DIE(#name, name); #define WRAP_W_W(name) \ extern "C" void *name(void *arg) { \ @@ -158,7 +189,7 @@ static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ return fn(arg); \ } \ - INTERCEPT_WHEN_POSSIBLE(#name, name); + INTERCEPT_OR_DIE(#name, name); #define WRAP_W_WW(name) \ extern "C" void *name(void *arg1, void *arg2) { \ @@ -166,7 +197,7 @@ static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ return fn(arg1, arg2); \ } \ - INTERCEPT_WHEN_POSSIBLE(#name, name); + INTERCEPT_OR_DIE(#name, name); #define WRAP_W_WWW(name) \ extern "C" void *name(void *arg1, void *arg2, void *arg3) { \ @@ -174,7 +205,7 @@ static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ return fn(arg1, arg2, arg3); \ } \ - INTERCEPT_WHEN_POSSIBLE(#name, name); + INTERCEPT_OR_DIE(#name, name); #define WRAP_W_WWWW(name) \ extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4) { \ @@ -182,7 +213,7 @@ static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ return fn(arg1, arg2, arg3, arg4); \ } \ - INTERCEPT_WHEN_POSSIBLE(#name, name); + INTERCEPT_OR_DIE(#name, name); #define WRAP_W_WWWWW(name) \ extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4, \ @@ -191,7 +222,7 @@ static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ return fn(arg1, arg2, arg3, arg4, arg5); \ } \ - INTERCEPT_WHEN_POSSIBLE(#name, name); + INTERCEPT_OR_DIE(#name, name); #define WRAP_W_WWWWWW(name) \ extern "C" void *name(void *arg1, void *arg2, void *arg3, void *arg4, \ @@ -200,7 +231,7 @@ static fntype fn = (fntype)getRealProcAddressOrDie(#name); \ return fn(arg1, arg2, arg3, arg4, arg5, arg6); \ } \ - INTERCEPT_WHEN_POSSIBLE(#name, name); + INTERCEPT_OR_DIE(#name, name); // }}} // ----------------- ASan own interface functions -------------------- @@ -333,18 +364,18 @@ INTERFACE_FUNCTION(__sanitizer_cov_module_init) INTERFACE_FUNCTION(__sanitizer_cov_trace_basic_block) INTERFACE_FUNCTION(__sanitizer_cov_trace_func_enter) -INTERFACE_FUNCTION(__sanitizer_cov_trace_cmp) -INTERFACE_FUNCTION(__sanitizer_cov_trace_cmp1) -INTERFACE_FUNCTION(__sanitizer_cov_trace_cmp2) -INTERFACE_FUNCTION(__sanitizer_cov_trace_cmp4) -INTERFACE_FUNCTION(__sanitizer_cov_trace_cmp8) -INTERFACE_FUNCTION(__sanitizer_cov_trace_switch) -INTERFACE_FUNCTION(__sanitizer_cov_trace_div4) -INTERFACE_FUNCTION(__sanitizer_cov_trace_div8) -INTERFACE_FUNCTION(__sanitizer_cov_trace_gep) -INTERFACE_FUNCTION(__sanitizer_cov_trace_pc_indir) -INTERFACE_FUNCTION(__sanitizer_cov_trace_pc_guard) -INTERFACE_FUNCTION(__sanitizer_cov_trace_pc_guard_init) +INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp) +INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp1) +INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp2) +INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp4) +INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_cmp8) +INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_switch) +INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_div4) +INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_div8) +INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_gep) +INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_pc_indir) +INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_pc_guard) +INTERFACE_WEAK_FUNCTION(__sanitizer_cov_trace_pc_guard_init) INTERFACE_FUNCTION(__sanitizer_cov_with_check) INTERFACE_FUNCTION(__sanitizer_get_allocated_size) INTERFACE_FUNCTION(__sanitizer_get_coverage_guards)