diff --git a/compiler-rt/lib/asan/asan_interceptors.cc b/compiler-rt/lib/asan/asan_interceptors.cc index 27e4ee8ef8e4..5cbf3f3e6dc5 100644 --- a/compiler-rt/lib/asan/asan_interceptors.cc +++ b/compiler-rt/lib/asan/asan_interceptors.cc @@ -9,7 +9,7 @@ // // This file is a part of AddressSanitizer, an address sanity checker. // -// Intercept various libc functions to catch buggy memory accesses there. +// Intercept various libc functions. //===----------------------------------------------------------------------===// #include "asan_interceptors.h" @@ -30,6 +30,54 @@ #include #include +// To replace weak 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 +// 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 +// the "wrap_" prefix on Mac. +// +// After interception, the calls to system functions will be substituted by +// calls to our interceptors. We store pointers to system function f() +// in __asan::real_f(). +// +// TODO(glider): mach_override_ptr() tends to spend too much time +// in allocateBranchIsland(). This should be ok for real-word +// application, but slows down our tests which fork too many children. +#ifdef __APPLE__ +#include "mach_override/mach_override.h" +#define WRAPPER_NAME(x) "wrap_"#x + +#define OVERRIDE_FUNCTION(oldfunc, newfunc) \ + CHECK(0 == __asan_mach_override_ptr((void*)(oldfunc), \ + (void*)(newfunc), \ + (void**)&real_##oldfunc)); \ + CHECK(real_##oldfunc != NULL); + +#define OVERRIDE_FUNCTION_IF_EXISTS(oldfunc, newfunc) \ + do { __asan_mach_override_ptr((void*)(oldfunc), \ + (void*)(newfunc), \ + (void**)&real_##oldfunc); } while (0) + +#define INTERCEPT_FUNCTION(func) \ + OVERRIDE_FUNCTION(func, WRAP(func)) + +#define INTERCEPT_FUNCTION_IF_EXISTS(func) \ + OVERRIDE_FUNCTION_IF_EXISTS(func, WRAP(func)) + +#else // __linux__ +#define WRAPPER_NAME(x) #x + +#define INTERCEPT_FUNCTION(func) \ + CHECK((real_##func = (func##_f)dlsym(RTLD_NEXT, #func))); + +#define INTERCEPT_FUNCTION_IF_EXISTS(func) \ + do { real_##func = (func##_f)dlsym(RTLD_NEXT, #func); } while (0) +#endif + namespace __asan { typedef void (*longjmp_f)(void *env, int val); diff --git a/compiler-rt/lib/asan/asan_interceptors.h b/compiler-rt/lib/asan/asan_interceptors.h index 47d43fab398c..fb8a55759f3b 100644 --- a/compiler-rt/lib/asan/asan_interceptors.h +++ b/compiler-rt/lib/asan/asan_interceptors.h @@ -16,57 +16,12 @@ #include "asan_internal.h" -// To replace weak 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 -// 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 -// the "wrap_" prefix on Mac. -// -// After interception, the calls to system functions will be substituted by -// calls to our interceptors. We store pointers to system function f() -// in __asan::real_f(). -// -// TODO(glider): mach_override_ptr() tends to spend too much time -// in allocateBranchIsland(). This should be ok for real-word -// application, but slows down our tests which fork too many children. #ifdef __APPLE__ -#include "mach_override/mach_override.h" -#define WRAP(x) wrap_##x -#define WRAPPER_NAME(x) "wrap_"#x - -#define OVERRIDE_FUNCTION(oldfunc, newfunc) \ - CHECK(0 == __asan_mach_override_ptr((void*)(oldfunc), \ - (void*)(newfunc), \ - (void**)&real_##oldfunc)); \ - CHECK(real_##oldfunc != NULL); - -#define OVERRIDE_FUNCTION_IF_EXISTS(oldfunc, newfunc) \ - do { __asan_mach_override_ptr((void*)(oldfunc), \ - (void*)(newfunc), \ - (void**)&real_##oldfunc); } while (0) - -#define INTERCEPT_FUNCTION(func) \ - OVERRIDE_FUNCTION(func, WRAP(func)) - -#define INTERCEPT_FUNCTION_IF_EXISTS(func) \ - OVERRIDE_FUNCTION_IF_EXISTS(func, WRAP(func)) - -#else // __linux__ -#define WRAP(x) x -#define WRAPPER_NAME(x) #x - -#define INTERCEPT_FUNCTION(func) \ - CHECK((real_##func = (func##_f)dlsym(RTLD_NEXT, #func))); - -#define INTERCEPT_FUNCTION_IF_EXISTS(func) \ - do { real_##func = (func##_f)dlsym(RTLD_NEXT, #func); } while (0) +# define WRAP(x) wrap_##x +#else +# define WRAP(x) x #endif - namespace __asan { typedef void* (*index_f)(const char *string, int c); @@ -116,8 +71,6 @@ int internal_memcmp(const void* s1, const void* s2, size_t n); char *internal_strstr(const char *haystack, const char *needle); char *internal_strncat(char *dst, const char *src, size_t n); - -// Initializes pointers to str*/mem* functions. void InitializeAsanInterceptors(); } // namespace __asan diff --git a/compiler-rt/lib/asan/asan_rtl.cc b/compiler-rt/lib/asan/asan_rtl.cc index 96e34045f3bb..57dfa2e3fff6 100644 --- a/compiler-rt/lib/asan/asan_rtl.cc +++ b/compiler-rt/lib/asan/asan_rtl.cc @@ -95,7 +95,7 @@ size_t ReadFileToBuffer(const char *file_name, char **buff, // This function should be called first inside __asan_init. static const char* GetEnvFromProcSelfEnviron(const char* name) { static char *environ; - static ssize_t len; + static size_t len; static bool inited; if (!inited) { inited = true; @@ -103,7 +103,7 @@ static const char* GetEnvFromProcSelfEnviron(const char* name) { len = ReadFileToBuffer("/proc/self/environ", &environ, &environ_size, 1 << 20); } - if (!environ || len <= 0) return NULL; + if (!environ || len == 0) return NULL; size_t namelen = internal_strlen(name); const char *p = environ; while (*p != '\0') { // will happen at the \0\0 that terminates the buffer