From f5d265460d9969661ad30e4222a928ecdf3b9868 Mon Sep 17 00:00:00 2001 From: Marcos Pividori Date: Thu, 2 Feb 2017 23:01:34 +0000 Subject: [PATCH] [sanitizer] Intercept weak functions in dll_thunks. In this diff, I update current implementation of the interception in dll_thunks to consider the special case of weak functions. First we check if the client has redefined the function in the main executable (for example: __sanitizer_cov_trace_pc_guard). It we can't find it, then we look for the default implementation (__sanitizer_cov_trace_pc_guard__dll). The default implementation is always available because the static runtime is linked to the main executable. Differential Revision: https://reviews.llvm.org/D29155 llvm-svn: 293952 --- compiler-rt/lib/asan/asan_win_dll_thunk.cc | 2 +- .../sanitizer_coverage_win_dll_thunk.cc | 2 +- .../sanitizer_win_dll_thunk.cc | 13 +++++++++- .../sanitizer_win_dll_thunk.h | 25 +++++++++++++++++++ compiler-rt/lib/ubsan/ubsan_win_dll_thunk.cc | 2 +- 5 files changed, 40 insertions(+), 4 deletions(-) diff --git a/compiler-rt/lib/asan/asan_win_dll_thunk.cc b/compiler-rt/lib/asan/asan_win_dll_thunk.cc index b53c717eabd8..a64fd9d213c7 100644 --- a/compiler-rt/lib/asan/asan_win_dll_thunk.cc +++ b/compiler-rt/lib/asan/asan_win_dll_thunk.cc @@ -24,7 +24,7 @@ // ASan own interface functions. #define INTERFACE_FUNCTION(Name) INTERCEPT_SANITIZER_FUNCTION(Name) -#define INTERFACE_WEAK_FUNCTION(Name) +#define INTERFACE_WEAK_FUNCTION(Name) INTERCEPT_SANITIZER_WEAK_FUNCTION(Name) #include "asan_interface.inc" // Memory allocation functions. diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_coverage_win_dll_thunk.cc b/compiler-rt/lib/sanitizer_common/sanitizer_coverage_win_dll_thunk.cc index 0ab62c074362..d5e459f2c020 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_coverage_win_dll_thunk.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_coverage_win_dll_thunk.cc @@ -16,6 +16,6 @@ #include "sanitizer_win_dll_thunk.h" // Sanitizer Coverage interface functions. #define INTERFACE_FUNCTION(Name) INTERCEPT_SANITIZER_FUNCTION(Name) -#define INTERFACE_WEAK_FUNCTION(Name) +#define INTERFACE_WEAK_FUNCTION(Name) INTERCEPT_SANITIZER_WEAK_FUNCTION(Name) #include "sanitizer_coverage_interface.inc" #endif // SANITIZER_DLL_THUNK diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_win_dll_thunk.cc b/compiler-rt/lib/sanitizer_common/sanitizer_win_dll_thunk.cc index 955a2aa3e9bd..4fb4650be478 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_win_dll_thunk.cc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_win_dll_thunk.cc @@ -37,11 +37,22 @@ int dllThunkIntercept(const char* main_function, uptr dll_function) { abort(); return 0; } + +int dllThunkInterceptWhenPossible(const char* main_function, + const char* default_function, uptr dll_function) { + uptr wrapper = __interception::InternalGetProcAddress( + (void *)GetModuleHandleA(0), main_function); + if (!wrapper) + wrapper = dllThunkGetRealAddrOrDie(default_function); + if (!__interception::OverrideFunction(dll_function, wrapper, 0)) + abort(); + return 0; +} } // namespace __sanitizer // Include Sanitizer Common interface. #define INTERFACE_FUNCTION(Name) INTERCEPT_SANITIZER_FUNCTION(Name) -#define INTERFACE_WEAK_FUNCTION(Name) +#define INTERFACE_WEAK_FUNCTION(Name) INTERCEPT_SANITIZER_WEAK_FUNCTION(Name) #include "sanitizer_common_interface.inc" #pragma section(".DLLTH$A", read) // NOLINT diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_win_dll_thunk.h b/compiler-rt/lib/sanitizer_common/sanitizer_win_dll_thunk.h index b19d01a29ce9..00a3b023dd84 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_win_dll_thunk.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_win_dll_thunk.h @@ -19,6 +19,9 @@ namespace __sanitizer { uptr dllThunkGetRealAddrOrDie(const char *name); int dllThunkIntercept(const char* main_function, uptr dll_function); + +int dllThunkInterceptWhenPossible(const char* main_function, + const char* default_function, uptr dll_function); } extern "C" int __dll_thunk_init(); @@ -34,6 +37,17 @@ extern "C" int __dll_thunk_init(); __declspec(allocate(".DLLTH$M")) int (*__dll_thunk_##dll_function)() = \ intercept_##dll_function; +// 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) \ + static int intercept_##dll_function() { \ + return __sanitizer::dllThunkInterceptWhenPossible(main_function, \ + default_function, (__sanitizer::uptr)dll_function); \ + } \ + __pragma(section(".DLLTH$M", long, read)) \ + __declspec(allocate(".DLLTH$M")) int (*__dll_thunk_##dll_function)() = \ + intercept_##dll_function; + // -------------------- Function interception macros ------------------------ // // Special case of hooks -- ASan own interface functions. Those are only called // after __asan_init, thus an empty implementation is sufficient. @@ -44,6 +58,17 @@ extern "C" int __dll_thunk_init(); } \ 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 INTERCEPT_SANITIZER_WEAK_FUNCTION(name) \ + extern "C" __declspec(noinline) void name() { \ + volatile int prevent_icf = (__LINE__ << 8); (void)prevent_icf; \ + __debugbreak(); \ + } \ + INTERCEPT_WHEN_POSSIBLE(#name, STRINGIFY(WEAK_EXPORT_NAME(name)), name) + // 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 diff --git a/compiler-rt/lib/ubsan/ubsan_win_dll_thunk.cc b/compiler-rt/lib/ubsan/ubsan_win_dll_thunk.cc index 858042e297f0..a1d0dbd66056 100644 --- a/compiler-rt/lib/ubsan/ubsan_win_dll_thunk.cc +++ b/compiler-rt/lib/ubsan/ubsan_win_dll_thunk.cc @@ -16,6 +16,6 @@ #include "sanitizer_common/sanitizer_win_dll_thunk.h" // Ubsan interface functions. #define INTERFACE_FUNCTION(Name) INTERCEPT_SANITIZER_FUNCTION(Name) -#define INTERFACE_WEAK_FUNCTION(Name) +#define INTERFACE_WEAK_FUNCTION(Name) INTERCEPT_SANITIZER_WEAK_FUNCTION(Name) #include "ubsan_interface.inc" #endif // SANITIZER_DLL_THUNK