summaryrefslogtreecommitdiff
path: root/lib/interception/interception.h
diff options
context:
space:
mode:
authorAlexander Potapenko <glider@google.com>2013-02-21 14:41:16 +0000
committerAlexander Potapenko <glider@google.com>2013-02-21 14:41:16 +0000
commit50a002ecad3f0a10c136496e5b6289bd3c71590e (patch)
treed9e0a899067d99a83a116704039313166b1ee12b /lib/interception/interception.h
parent372b267fadcaf73b9d9cee5c8050d3c10e94f74d (diff)
[ASan] Refactoring: nuke the redundant function declarations in asan_intercepted_functions.h
that had been used on OS X only. The INTERCEPTOR() macro on OS X is now responsible for declaring the wrapped function, the wrapper and the pair of pointers to them in __DATA,__interposition section. Thus adding an interceptor requires editing a single file now. git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@175740 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/interception/interception.h')
-rw-r--r--lib/interception/interception.h51
1 files changed, 46 insertions, 5 deletions
diff --git a/lib/interception/interception.h b/lib/interception/interception.h
index eb5ff8f48..b6be72c69 100644
--- a/lib/interception/interception.h
+++ b/lib/interception/interception.h
@@ -57,14 +57,14 @@ typedef __sanitizer::u64 OFF64_T;
// 3b) add DECLARE_REAL_AND_INTERCEPTOR(int, foo, const char*, double)
// to a header file.
-// Notes: 1. Things may not work properly if macro INTERCEPT(...) {...} or
+// Notes: 1. Things may not work properly if macro INTERCEPTOR(...) {...} or
// DECLARE_REAL(...) are located inside namespaces.
-// 2. On Mac you can also use: "OVERRIDE_FUNCTION(foo, zoo);" to
+// 2. On Mac you can also use: "OVERRIDE_FUNCTION(foo, zoo)" to
// effectively redirect calls from "foo" to "zoo". In this case
// you aren't required to implement
// INTERCEPTOR(int, foo, const char *bar, double baz) {...}
// but instead you'll have to add
-// DEFINE_REAL(int, foo, const char *bar, double baz) in your
+// DECLARE_REAL(int, foo, const char *bar, double baz) in your
// source file (to define a pointer to overriden function).
// How it works:
@@ -75,6 +75,7 @@ typedef __sanitizer::u64 OFF64_T;
// we intercept. To resolve this we declare our interceptors with __interceptor_
// prefix, and then make actual interceptors weak aliases to __interceptor_
// 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
@@ -84,12 +85,42 @@ typedef __sanitizer::u64 OFF64_T;
// preloaded before an executable using DYLD_INSERT_LIBRARIES, it routes all
// the calls to interposed functions done through stubs to the wrapper
// functions.
+// As it's decided at compile time which functions are to be intercepted on Mac,
+// INTERCEPT_FUNCTION() is effectively a no-op on this system.
#if defined(__APPLE__)
+
+// Just a pair of pointers.
+struct interpose_substitution {
+ const uptr replacement;
+ const uptr original;
+};
+
+// For a function foo() create a global pair of pointers { wrap_foo, foo } in
+// the __DATA,__interpose section.
+// As a result all the calls to foo() will be routed to wrap_foo() at runtime.
+#define INTERPOSER(func_name) __attribute__((used)) \
+const interpose_substitution substitution_##func_name[] \
+ __attribute__((section("__DATA, __interpose"))) = { \
+ { reinterpret_cast<const uptr>(WRAP(func_name)), \
+ reinterpret_cast<const uptr>(func_name) } \
+}
+
+// For a function foo() and a wrapper function bar() create a global pair
+// of pointers { bar, foo } in the __DATA,__interpose section.
+// As a result all the calls to foo() will be routed to bar() at runtime.
+#define INTERPOSER_2(func_name, wrapper_name) __attribute__((used)) \
+const interpose_substitution substitution_##func_name[] \
+ __attribute__((section("__DATA, __interpose"))) = { \
+ { reinterpret_cast<const uptr>(wrapper_name), \
+ reinterpret_cast<const uptr>(func_name) } \
+}
+
# define WRAP(x) wrap_##x
# define WRAPPER_NAME(x) "wrap_"#x
# define INTERCEPTOR_ATTRIBUTE
# define DECLARE_WRAPPER(ret_type, func, ...)
+
#elif defined(_WIN32)
# if defined(_DLL) // DLL CRT
# define WRAP(x) x
@@ -144,12 +175,24 @@ typedef __sanitizer::u64 OFF64_T;
# define DEFINE_REAL(ret_type, func, ...)
#endif
+#if !defined(__APPLE__)
#define INTERCEPTOR(ret_type, func, ...) \
DEFINE_REAL(ret_type, func, __VA_ARGS__) \
DECLARE_WRAPPER(ret_type, func, __VA_ARGS__) \
extern "C" \
INTERCEPTOR_ATTRIBUTE \
ret_type WRAP(func)(__VA_ARGS__)
+#else // __APPLE__
+#define INTERCEPTOR(ret_type, func, ...) \
+ extern "C" ret_type func(__VA_ARGS__); \
+ extern "C" ret_type WRAP(func)(__VA_ARGS__); \
+ INTERPOSER(func); \
+ extern "C" INTERCEPTOR_ATTRIBUTE ret_type WRAP(func)(__VA_ARGS__)
+
+// Override |overridee| with |overrider|.
+#define OVERRIDE_FUNCTION(overridee, overrider) \
+ INTERPOSER_2(overridee, WRAP(overrider))
+#endif
#if defined(_WIN32)
# define INTERCEPTOR_WINAPI(ret_type, func, ...) \
@@ -183,8 +226,6 @@ typedef unsigned long uptr; // NOLINT
# define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_LINUX(func)
#elif defined(__APPLE__)
# include "interception_mac.h"
-# define OVERRIDE_FUNCTION(old_func, new_func) \
- OVERRIDE_FUNCTION_MAC(old_func, new_func)
# define INTERCEPT_FUNCTION(func) INTERCEPT_FUNCTION_MAC(func)
#else // defined(_WIN32)
# include "interception_win.h"