From e8ba1c851a8f3f3397422dd49e4554e017f0eb8f Mon Sep 17 00:00:00 2001 From: Alexander Potapenko Date: Thu, 21 Feb 2013 14:41:16 +0000 Subject: [PATCH] [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. llvm-svn: 175740 --- compiler-rt/lib/asan/asan_intercepted_functions.h | 237 ---------------------- compiler-rt/lib/asan/asan_interceptors.cc | 9 +- compiler-rt/lib/asan/asan_mac.cc | 18 -- compiler-rt/lib/interception/interception.h | 51 ++++- 4 files changed, 53 insertions(+), 262 deletions(-) diff --git a/compiler-rt/lib/asan/asan_intercepted_functions.h b/compiler-rt/lib/asan/asan_intercepted_functions.h index 35e948c..ea04c1f 100644 --- a/compiler-rt/lib/asan/asan_intercepted_functions.h +++ b/compiler-rt/lib/asan/asan_intercepted_functions.h @@ -79,248 +79,11 @@ using __sanitizer::uptr; # define ASAN_INTERCEPT___CXA_THROW 0 #endif -#define INTERPOSE_FUNCTION(function) \ - { reinterpret_cast(WRAP(function)), \ - reinterpret_cast(function) } - -#define INTERPOSE_FUNCTION_2(function, wrapper) \ - { reinterpret_cast(wrapper), \ - reinterpret_cast(function) } - -struct interpose_substitution { - const uptr replacement; - const uptr original; -}; - -#define INTERPOSER(func) __attribute__((used)) \ -const interpose_substitution substitution_##func[] \ - __attribute__((section("__DATA, __interpose"))) = { \ - INTERPOSE_FUNCTION(func), \ -} - -#define INTERPOSER_2(func, wrapper) __attribute__((used)) \ -const interpose_substitution substitution_##func[] \ - __attribute__((section("__DATA, __interpose"))) = { \ - INTERPOSE_FUNCTION_2(func, wrapper), \ -} - - -#define DECLARE_FUNCTION_AND_WRAPPER(ret_type, func, ...) \ - ret_type func(__VA_ARGS__); \ - ret_type WRAP(func)(__VA_ARGS__); \ - INTERPOSER(func) - -// Use extern declarations of intercepted functions on Mac and Windows -// to avoid including system headers. -#if defined(__APPLE__) || (defined(_WIN32) && !defined(_DLL)) -extern "C" { -// signal.h -# if ASAN_INTERCEPT_SIGNAL_AND_SIGACTION -struct sigaction; -DECLARE_FUNCTION_AND_WRAPPER(int, sigaction, int sig, - const struct sigaction *act, - struct sigaction *oldact); -DECLARE_FUNCTION_AND_WRAPPER(void*, signal, int signum, void *handler); -# endif - -// setjmp.h -DECLARE_FUNCTION_AND_WRAPPER(void, longjmp, void *env, int value); -# if ASAN_INTERCEPT__LONGJMP -DECLARE_FUNCTION_AND_WRAPPER(void, _longjmp, void *env, int value); -# endif -# if ASAN_INTERCEPT_SIGLONGJMP -DECLARE_FUNCTION_AND_WRAPPER(void, siglongjmp, void *env, int value); -# endif -# if ASAN_INTERCEPT___CXA_THROW -DECLARE_FUNCTION_AND_WRAPPER(void, __cxa_throw, void *a, void *b, void *c); -# endif - -// string.h / strings.h -DECLARE_FUNCTION_AND_WRAPPER(int, memcmp, - const void *a1, const void *a2, uptr size); -DECLARE_FUNCTION_AND_WRAPPER(void*, memmove, - void *to, const void *from, uptr size); -DECLARE_FUNCTION_AND_WRAPPER(void*, memcpy, - void *to, const void *from, uptr size); -DECLARE_FUNCTION_AND_WRAPPER(void*, memset, void *block, int c, uptr size); -DECLARE_FUNCTION_AND_WRAPPER(char*, strchr, const char *str, int c); -DECLARE_FUNCTION_AND_WRAPPER(char*, strcat, /* NOLINT */ - char *to, const char* from); -DECLARE_FUNCTION_AND_WRAPPER(char*, strncat, - char *to, const char* from, uptr size); -DECLARE_FUNCTION_AND_WRAPPER(char*, strcpy, /* NOLINT */ - char *to, const char* from); -DECLARE_FUNCTION_AND_WRAPPER(char*, strncpy, - char *to, const char* from, uptr size); -DECLARE_FUNCTION_AND_WRAPPER(int, strcmp, const char *s1, const char* s2); -DECLARE_FUNCTION_AND_WRAPPER(int, strncmp, - const char *s1, const char* s2, uptr size); -DECLARE_FUNCTION_AND_WRAPPER(uptr, strlen, const char *s); -# if ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP -DECLARE_FUNCTION_AND_WRAPPER(int, strcasecmp, const char *s1, const char *s2); -DECLARE_FUNCTION_AND_WRAPPER(int, strncasecmp, - const char *s1, const char *s2, uptr n); -# endif -# if ASAN_INTERCEPT_STRDUP -DECLARE_FUNCTION_AND_WRAPPER(char*, strdup, const char *s); -# endif -# if ASAN_INTERCEPT_STRNLEN -DECLARE_FUNCTION_AND_WRAPPER(uptr, strnlen, const char *s, uptr maxlen); -# endif -# if ASAN_INTERCEPT_INDEX -char* index(const char *string, int c); -INTERPOSER_2(index, WRAP(strchr)); -# endif - -// stdlib.h -DECLARE_FUNCTION_AND_WRAPPER(int, atoi, const char *nptr); -DECLARE_FUNCTION_AND_WRAPPER(long, atol, const char *nptr); // NOLINT -DECLARE_FUNCTION_AND_WRAPPER(long, strtol, const char *nptr, char **endptr, int base); // NOLINT -# if ASAN_INTERCEPT_ATOLL_AND_STRTOLL -DECLARE_FUNCTION_AND_WRAPPER(long long, atoll, const char *nptr); // NOLINT -DECLARE_FUNCTION_AND_WRAPPER(long long, strtoll, const char *nptr, char **endptr, int base); // NOLINT -# endif - -// unistd.h -# if SANITIZER_INTERCEPT_READ -DECLARE_FUNCTION_AND_WRAPPER(SSIZE_T, read, int fd, void *buf, SIZE_T count); -# endif -# if SANITIZER_INTERCEPT_PREAD -DECLARE_FUNCTION_AND_WRAPPER(SSIZE_T, pread, int fd, void *buf, - SIZE_T count, OFF_T offset); -# endif -# if SANITIZER_INTERCEPT_PREAD64 -DECLARE_FUNCTION_AND_WRAPPER(SSIZE_T, pread64, int fd, void *buf, - SIZE_T count, OFF64_T offset); -# endif - -# if SANITIZER_INTERCEPT_WRITE -DECLARE_FUNCTION_AND_WRAPPER(SSIZE_T, write, int fd, void *ptr, SIZE_T count); -# endif -# if SANITIZER_INTERCEPT_PWRITE -DECLARE_FUNCTION_AND_WRAPPER(SSIZE_T, pwrite, - int fd, void *ptr, SIZE_T count, OFF_T offset); -# endif - -# if ASAN_INTERCEPT_MLOCKX -// mlock/munlock -DECLARE_FUNCTION_AND_WRAPPER(int, mlock, const void *addr, SIZE_T len); -DECLARE_FUNCTION_AND_WRAPPER(int, munlock, const void *addr, SIZE_T len); -DECLARE_FUNCTION_AND_WRAPPER(int, mlockall, int flags); -DECLARE_FUNCTION_AND_WRAPPER(int, munlockall, void); -# endif - // Windows threads. # if defined(_WIN32) __declspec(dllimport) void* __stdcall CreateThread(void *sec, uptr st, void* start, void *arg, DWORD fl, DWORD *id); # endif -// Posix threads. -# if ASAN_INTERCEPT_PTHREAD_CREATE -DECLARE_FUNCTION_AND_WRAPPER(int, pthread_create, - void *thread, void *attr, - void *(*start_routine)(void*), void *arg); -# endif - -# if SANITIZER_INTERCEPT_LOCALTIME_AND_FRIENDS -DECLARE_FUNCTION_AND_WRAPPER(void *, localtime, unsigned long *timep); -DECLARE_FUNCTION_AND_WRAPPER(void *, localtime_r, unsigned long *timep, - void *result); -DECLARE_FUNCTION_AND_WRAPPER(void *, gmtime, unsigned long *timep); -DECLARE_FUNCTION_AND_WRAPPER(void *, gmtime_r, unsigned long *timep, - void *result); -DECLARE_FUNCTION_AND_WRAPPER(char *, ctime, unsigned long *timep); -DECLARE_FUNCTION_AND_WRAPPER(char *, ctime_r, unsigned long *timep, - char *result); -DECLARE_FUNCTION_AND_WRAPPER(char *, asctime, void *tm); -DECLARE_FUNCTION_AND_WRAPPER(char *, asctime_r, void *tm, char *result); -# endif - -// stdio.h -# if SANITIZER_INTERCEPT_SCANF -DECLARE_FUNCTION_AND_WRAPPER(int, vscanf, const char *format, va_list ap); -DECLARE_FUNCTION_AND_WRAPPER(int, vsscanf, const char *str, const char *format, - va_list ap); -DECLARE_FUNCTION_AND_WRAPPER(int, vfscanf, void *stream, const char *format, - va_list ap); -DECLARE_FUNCTION_AND_WRAPPER(int, scanf, const char *format, ...); -DECLARE_FUNCTION_AND_WRAPPER(int, fscanf, - void* stream, const char *format, ...); -DECLARE_FUNCTION_AND_WRAPPER(int, sscanf, // NOLINT - const char *str, const char *format, ...); -# endif - -# if defined(__APPLE__) -typedef void* pthread_workqueue_t; -typedef void* pthread_workitem_handle_t; - -typedef void* dispatch_group_t; -typedef void* dispatch_queue_t; -typedef void* dispatch_source_t; -typedef u64 dispatch_time_t; -typedef void (*dispatch_function_t)(void *block); -typedef void* (*worker_t)(void *block); - -DECLARE_FUNCTION_AND_WRAPPER(void, dispatch_async_f, - dispatch_queue_t dq, - void *ctxt, dispatch_function_t func); -DECLARE_FUNCTION_AND_WRAPPER(void, dispatch_sync_f, - dispatch_queue_t dq, - void *ctxt, dispatch_function_t func); -DECLARE_FUNCTION_AND_WRAPPER(void, dispatch_after_f, - dispatch_time_t when, dispatch_queue_t dq, - void *ctxt, dispatch_function_t func); -DECLARE_FUNCTION_AND_WRAPPER(void, dispatch_barrier_async_f, - dispatch_queue_t dq, - void *ctxt, dispatch_function_t func); -DECLARE_FUNCTION_AND_WRAPPER(void, dispatch_group_async_f, - dispatch_group_t group, dispatch_queue_t dq, - void *ctxt, dispatch_function_t func); - -# if !defined(MISSING_BLOCKS_SUPPORT) -DECLARE_FUNCTION_AND_WRAPPER(void, dispatch_group_async, - dispatch_group_t dg, - dispatch_queue_t dq, void (^work)(void)); -DECLARE_FUNCTION_AND_WRAPPER(void, dispatch_async, - dispatch_queue_t dq, void (^work)(void)); -DECLARE_FUNCTION_AND_WRAPPER(void, dispatch_after, - dispatch_queue_t dq, void (^work)(void)); -DECLARE_FUNCTION_AND_WRAPPER(void, dispatch_source_set_event_handler, - dispatch_source_t ds, void (^work)(void)); -DECLARE_FUNCTION_AND_WRAPPER(void, dispatch_source_set_cancel_handler, - dispatch_source_t ds, void (^work)(void)); -# endif // MISSING_BLOCKS_SUPPORT - -typedef void malloc_zone_t; -typedef size_t vm_size_t; -DECLARE_FUNCTION_AND_WRAPPER(malloc_zone_t *, malloc_create_zone, - vm_size_t start_size, unsigned flags); -DECLARE_FUNCTION_AND_WRAPPER(malloc_zone_t *, malloc_default_zone, void); -DECLARE_FUNCTION_AND_WRAPPER( - malloc_zone_t *, malloc_default_purgeable_zone, void); -DECLARE_FUNCTION_AND_WRAPPER(void, malloc_make_purgeable, void *ptr); -DECLARE_FUNCTION_AND_WRAPPER(int, malloc_make_nonpurgeable, void *ptr); -DECLARE_FUNCTION_AND_WRAPPER(void, malloc_set_zone_name, - malloc_zone_t *zone, const char *name); -DECLARE_FUNCTION_AND_WRAPPER(void *, malloc, size_t size); -DECLARE_FUNCTION_AND_WRAPPER(void, free, void *ptr); -DECLARE_FUNCTION_AND_WRAPPER(void *, realloc, void *ptr, size_t size); -DECLARE_FUNCTION_AND_WRAPPER(void *, calloc, size_t nmemb, size_t size); -DECLARE_FUNCTION_AND_WRAPPER(void *, valloc, size_t size); -DECLARE_FUNCTION_AND_WRAPPER(size_t, malloc_good_size, size_t size); -DECLARE_FUNCTION_AND_WRAPPER(int, posix_memalign, - void **memptr, size_t alignment, size_t size); -#if 0 -DECLARE_FUNCTION_AND_WRAPPER(void, _malloc_fork_prepare, void); -DECLARE_FUNCTION_AND_WRAPPER(void, _malloc_fork_parent, void); -DECLARE_FUNCTION_AND_WRAPPER(void, _malloc_fork_child, void); -#endif - - - -# endif // __APPLE__ -} // extern "C" -#endif // defined(__APPLE__) || (defined(_WIN32) && !defined(_DLL)) #endif // ASAN_INTERCEPTED_FUNCTIONS_H diff --git a/compiler-rt/lib/asan/asan_interceptors.cc b/compiler-rt/lib/asan/asan_interceptors.cc index af4d5a3..5f3975b 100644 --- a/compiler-rt/lib/asan/asan_interceptors.cc +++ b/compiler-rt/lib/asan/asan_interceptors.cc @@ -341,9 +341,14 @@ INTERCEPTOR(char*, strchr, const char *str, int c) { #if ASAN_INTERCEPT_INDEX # if ASAN_USE_ALIAS_ATTRIBUTE_FOR_INDEX INTERCEPTOR(char*, index, const char *string, int c) - ALIAS(WRAPPER_NAME(strchr)); + WEAK_ALIAS(WRAPPER_NAME(strchr)); # else -DEFINE_REAL(char*, index, const char *string, int c) +# if defined(__APPLE__) +DECLARE_REAL(char*, index, const char *string, int c) +OVERRIDE_FUNCTION(index, strchr); +# else +DEFINE_REAL(char*, index, const char *string, int c); +# endif # endif #endif // ASAN_INTERCEPT_INDEX diff --git a/compiler-rt/lib/asan/asan_mac.cc b/compiler-rt/lib/asan/asan_mac.cc index 3aeb1a5d..0f51a06 100644 --- a/compiler-rt/lib/asan/asan_mac.cc +++ b/compiler-rt/lib/asan/asan_mac.cc @@ -288,24 +288,6 @@ typedef struct { u32 parent_tid; } asan_block_context_t; -// We use extern declarations of libdispatch functions here instead -// of including . This header is not present on -// Mac OS X Leopard and eariler, and although we don't expect ASan to -// work on legacy systems, it's bad to break the build of -// LLVM compiler-rt there. -extern "C" { -void dispatch_async_f(dispatch_queue_t dq, void *ctxt, - dispatch_function_t func); -void dispatch_sync_f(dispatch_queue_t dq, void *ctxt, - dispatch_function_t func); -void dispatch_after_f(dispatch_time_t when, dispatch_queue_t dq, void *ctxt, - dispatch_function_t func); -void dispatch_barrier_async_f(dispatch_queue_t dq, void *ctxt, - dispatch_function_t func); -void dispatch_group_async_f(dispatch_group_t group, dispatch_queue_t dq, - void *ctxt, dispatch_function_t func); -} // extern "C" - static ALWAYS_INLINE void asan_register_worker_thread(int parent_tid, StackTrace *stack) { AsanThread *t = asanThreadRegistry().GetCurrent(); diff --git a/compiler-rt/lib/interception/interception.h b/compiler-rt/lib/interception/interception.h index eb5ff8f..b6be72c 100644 --- a/compiler-rt/lib/interception/interception.h +++ b/compiler-rt/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(WRAP(func_name)), \ + reinterpret_cast(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(wrapper_name), \ + reinterpret_cast(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" -- 2.7.4