diff options
author | Dmitry Vyukov <dvyukov@google.com> | 2012-05-24 13:54:31 +0000 |
---|---|---|
committer | Dmitry Vyukov <dvyukov@google.com> | 2012-05-24 13:54:31 +0000 |
commit | 580469d7e40e39319cb2d3750edac4bccca18105 (patch) | |
tree | fca0e8f57a0c68e1aedf80f7f10c6cadf4f54117 /lib/interception | |
parent | 24567d409cca096b950574fa4b19aa4c2c67a1f0 (diff) |
asan/tsan: weak interceptors
The idea isthat asan/tsan can survive if user intercepts the same functions. At the same time user has an ability to call back into asan/tsan runtime. See the following tests for examples:
asan/output_tests/interception_failure_test-linux.cc
asan/output_tests/interception_test-linux.cc
asan/output_tests/interception_malloc_test-linux.cc
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@157388 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/interception')
-rw-r--r-- | lib/interception/interception.h | 25 | ||||
-rw-r--r-- | lib/interception/interception_linux.cc | 5 | ||||
-rw-r--r-- | lib/interception/interception_linux.h | 6 |
3 files changed, 25 insertions, 11 deletions
diff --git a/lib/interception/interception.h b/lib/interception/interception.h index fb3eef08a..0a7eedc92 100644 --- a/lib/interception/interception.h +++ b/lib/interception/interception.h @@ -61,20 +61,26 @@ // source file (to define a pointer to overriden function). // How it works: -// To replace weak system functions on Linux we just need to declare functions +// To replace system functions on Linux we just need to declare functions // with same names in our library and then obtain the real function pointers -// using dlsym(). This is not so on Mac OS, where the two-level namespace makes +// using dlsym(). +// There is one complication. A user may also intercept some of the functions +// we intercept. To resolve this we declare our interceptors with __xsan_ +// prefix, and then make actual interceptors weak aliases to __xsan_ +// functions. +// This is not so on Mac OS, where the two-level namespace makes // our replacement functions invisible to other libraries. This may be overcomed // using the DYLD_FORCE_FLAT_NAMESPACE, but some errors loading the shared -// libraries in Chromium were noticed when doing so. -// Instead we use mach_override, a handy framework for patching functions at -// runtime. To avoid possible name clashes, our replacement functions have +// libraries in Chromium were noticed when doing so. Instead we use +// mach_override, a handy framework for patching functions at runtime. +// To avoid possible name clashes, our replacement functions have // the "wrap_" prefix on Mac. #if defined(__APPLE__) # define WRAP(x) wrap_##x # define WRAPPER_NAME(x) "wrap_"#x # define INTERCEPTOR_ATTRIBUTE +# define DECLARE_WRAPPER(ret_type, convention, func, ...) #elif defined(_WIN32) # if defined(_DLL) // DLL CRT # define WRAP(x) x @@ -85,10 +91,14 @@ # define WRAPPER_NAME(x) "wrap_"#x # define INTERCEPTOR_ATTRIBUTE # endif +# define DECLARE_WRAPPER(ret_type, convention, func, ...) #else -# define WRAP(x) x -# define WRAPPER_NAME(x) #x +# define WRAP(x) __xsan_ ## x +# define WRAPPER_NAME(x) "__xsan_" #x # define INTERCEPTOR_ATTRIBUTE __attribute__((visibility("default"))) +# define DECLARE_WRAPPER(ret_type, convention, func, ...) \ + extern "C" ret_type convention func(__VA_ARGS__) \ + __attribute__((weak, alias("__xsan_" #func), visibility("default"))) #endif #define PTR_TO_REAL(x) real_##x @@ -125,6 +135,7 @@ #define INTERCEPTOR_EX(ret_type, convention, func, ...) \ DEFINE_REAL_EX(ret_type, convention, func, __VA_ARGS__); \ + DECLARE_WRAPPER(ret_type, convention, func, __VA_ARGS__); \ extern "C" \ INTERCEPTOR_ATTRIBUTE \ ret_type convention WRAP(func)(__VA_ARGS__) diff --git a/lib/interception/interception_linux.cc b/lib/interception/interception_linux.cc index 74fcf563f..37e593323 100644 --- a/lib/interception/interception_linux.cc +++ b/lib/interception/interception_linux.cc @@ -18,9 +18,10 @@ #include <dlfcn.h> // for dlsym namespace __interception { -bool GetRealFunctionAddress(const char *func_name, void **func_addr) { +bool GetRealFunctionAddress(const char *func_name, void **func_addr, + void *real, void *wrapper) { *func_addr = dlsym(RTLD_NEXT, func_name); - return (*func_addr != NULL); + return real == wrapper; } } // namespace __interception diff --git a/lib/interception/interception_linux.h b/lib/interception/interception_linux.h index 102b3c190..76a29c6a9 100644 --- a/lib/interception/interception_linux.h +++ b/lib/interception/interception_linux.h @@ -23,11 +23,13 @@ namespace __interception { // returns true if a function with the given name was found. -bool GetRealFunctionAddress(const char *func_name, void **func_addr); +bool GetRealFunctionAddress(const char *func_name, void **func_addr, + void *real, void *wrapper); } // namespace __interception #define INTERCEPT_FUNCTION_LINUX(func) \ - ::__interception::GetRealFunctionAddress(#func, (void**)&REAL(func)) + ::__interception::GetRealFunctionAddress(#func, (void**)&REAL(func), \ + (void*)&(func), (void*)&WRAP(func)) #endif // INTERCEPTION_LINUX_H #endif // __linux__ |