summaryrefslogtreecommitdiff
path: root/lib/interception
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2012-05-24 13:54:31 +0000
committerDmitry Vyukov <dvyukov@google.com>2012-05-24 13:54:31 +0000
commit580469d7e40e39319cb2d3750edac4bccca18105 (patch)
treefca0e8f57a0c68e1aedf80f7f10c6cadf4f54117 /lib/interception
parent24567d409cca096b950574fa4b19aa4c2c67a1f0 (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.h25
-rw-r--r--lib/interception/interception_linux.cc5
-rw-r--r--lib/interception/interception_linux.h6
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__