[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
This commit is contained in:
parent
bfdfaa11ca
commit
f5d265460d
|
|
@ -24,7 +24,7 @@
|
||||||
|
|
||||||
// ASan own interface functions.
|
// ASan own interface functions.
|
||||||
#define INTERFACE_FUNCTION(Name) INTERCEPT_SANITIZER_FUNCTION(Name)
|
#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"
|
#include "asan_interface.inc"
|
||||||
|
|
||||||
// Memory allocation functions.
|
// Memory allocation functions.
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,6 @@
|
||||||
#include "sanitizer_win_dll_thunk.h"
|
#include "sanitizer_win_dll_thunk.h"
|
||||||
// Sanitizer Coverage interface functions.
|
// Sanitizer Coverage interface functions.
|
||||||
#define INTERFACE_FUNCTION(Name) INTERCEPT_SANITIZER_FUNCTION(Name)
|
#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"
|
#include "sanitizer_coverage_interface.inc"
|
||||||
#endif // SANITIZER_DLL_THUNK
|
#endif // SANITIZER_DLL_THUNK
|
||||||
|
|
|
||||||
|
|
@ -37,11 +37,22 @@ int dllThunkIntercept(const char* main_function, uptr dll_function) {
|
||||||
abort();
|
abort();
|
||||||
return 0;
|
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
|
} // namespace __sanitizer
|
||||||
|
|
||||||
// Include Sanitizer Common interface.
|
// Include Sanitizer Common interface.
|
||||||
#define INTERFACE_FUNCTION(Name) INTERCEPT_SANITIZER_FUNCTION(Name)
|
#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"
|
#include "sanitizer_common_interface.inc"
|
||||||
|
|
||||||
#pragma section(".DLLTH$A", read) // NOLINT
|
#pragma section(".DLLTH$A", read) // NOLINT
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,9 @@ namespace __sanitizer {
|
||||||
uptr dllThunkGetRealAddrOrDie(const char *name);
|
uptr dllThunkGetRealAddrOrDie(const char *name);
|
||||||
|
|
||||||
int dllThunkIntercept(const char* main_function, uptr dll_function);
|
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();
|
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)() = \
|
__declspec(allocate(".DLLTH$M")) int (*__dll_thunk_##dll_function)() = \
|
||||||
intercept_##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 ------------------------ //
|
// -------------------- Function interception macros ------------------------ //
|
||||||
// Special case of hooks -- ASan own interface functions. Those are only called
|
// Special case of hooks -- ASan own interface functions. Those are only called
|
||||||
// after __asan_init, thus an empty implementation is sufficient.
|
// after __asan_init, thus an empty implementation is sufficient.
|
||||||
|
|
@ -44,6 +58,17 @@ extern "C" int __dll_thunk_init();
|
||||||
} \
|
} \
|
||||||
INTERCEPT_OR_DIE(#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 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
|
// 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
|
// 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
|
// just to be able to get its address. Me may miss the first few calls to the
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,6 @@
|
||||||
#include "sanitizer_common/sanitizer_win_dll_thunk.h"
|
#include "sanitizer_common/sanitizer_win_dll_thunk.h"
|
||||||
// Ubsan interface functions.
|
// Ubsan interface functions.
|
||||||
#define INTERFACE_FUNCTION(Name) INTERCEPT_SANITIZER_FUNCTION(Name)
|
#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"
|
#include "ubsan_interface.inc"
|
||||||
#endif // SANITIZER_DLL_THUNK
|
#endif // SANITIZER_DLL_THUNK
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue