[llvm-commits] [compiler-rt] r162091 - in /compiler-rt/trunk/lib: asan/CMakeLists.txt asan/asan_interceptors.cc asan/asan_malloc_mac.cc asan/dynamic/ asan/dynamic/asan_interceptors_dynamic.cc interception/interception.h

Alexander Potapenko glider at google.com
Fri Aug 17 02:00:08 PDT 2012


Author: glider
Date: Fri Aug 17 04:00:08 2012
New Revision: 162091

URL: http://llvm.org/viewvc/llvm-project?rev=162091&view=rev
Log:
Commit the source and CMake changes that will allow to build ASan runtime
as a shared library on Mac OS. This will provide an alternative to
mach_override.


Added:
    compiler-rt/trunk/lib/asan/dynamic/
    compiler-rt/trunk/lib/asan/dynamic/asan_interceptors_dynamic.cc
Modified:
    compiler-rt/trunk/lib/asan/CMakeLists.txt
    compiler-rt/trunk/lib/asan/asan_interceptors.cc
    compiler-rt/trunk/lib/asan/asan_malloc_mac.cc
    compiler-rt/trunk/lib/interception/interception.h

Modified: compiler-rt/trunk/lib/asan/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/CMakeLists.txt?rev=162091&r1=162090&r2=162091&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/asan/CMakeLists.txt Fri Aug 17 04:00:08 2012
@@ -22,6 +22,11 @@
   asan_win.cc
   )
 
+set(ASAN_DYLIB_SOURCES
+  ${ASAN_SOURCES}
+  dynamic/asan_interceptors_dynamic.cc
+  )
+
 include_directories(..)
 
 set(ASAN_CFLAGS
@@ -33,6 +38,12 @@
   -fomit-frame-pointer
   -O3
   )
+
+set(ASAN_DYLIB_DEFINITIONS
+  ${ASAN_COMMON_DEFINITIONS}
+  MAC_INTERPOSE_FUNCTIONS=1
+  )
+
 if (SUPPORTS_NO_VARIADIC_MACROS_FLAG)
   list(APPEND ASAN_CFLAGS -Wno-variadic-macros)
 endif ()
@@ -89,6 +100,24 @@
   COMPILE_DEFINITIONS ${ASAN_COMMON_DEFINITIONS})
 add_clang_runtime_static_library(${ASAN_RUNTIME_LIBRARIES})
 
+set(ASAN_DYNAMIC_RUNTIME_LIBRARIES)
+if(APPLE)
+  # Build universal binary on APPLE.
+  add_library(clang_rt.asan_osx_dynamic SHARED
+    ${ASAN_DYLIB_SOURCES}
+    $<TARGET_OBJECTS:RTInterception.osx>
+    $<TARGET_OBJECTS:RTSanitizerCommon.osx>
+    )
+  set_target_compile_flags(clang_rt.asan_osx_dynamic ${ASAN_CFLAGS})
+  filter_available_targets(ASAN_TARGETS x86_64 i386)
+  set_target_properties(clang_rt.asan_osx_dynamic PROPERTIES
+    COMPILE_DEFINITIONS ${ASAN_DYLIB_DEFINITIONS}
+    OSX_ARCHITECTURES "${ASAN_TARGETS}"
+    LINK_FLAGS "-framework Foundation")
+  list(APPEND ASAN_DYNAMIC_RUNTIME_LIBRARIES clang_rt.asan_osx_dynamic)
+endif()
+
+
 if(LLVM_INCLUDE_TESTS)
   add_subdirectory(tests)
 endif()

Modified: compiler-rt/trunk/lib/asan/asan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_interceptors.cc?rev=162091&r1=162090&r2=162091&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_interceptors.cc Fri Aug 17 04:00:08 2012
@@ -206,6 +206,9 @@
 }
 
 INTERCEPTOR(int, memcmp, const void *a1, const void *a2, uptr size) {
+#if MAC_INTERPOSE_FUNCTIONS
+  if (!asan_inited) return REAL(memcmp)(a1, a2, size);
+#endif
   ENSURE_ASAN_INITED();
   unsigned char c1 = 0, c2 = 0;
   const unsigned char *s1 = (const unsigned char*)a1;
@@ -265,6 +268,9 @@
 }
 
 INTERCEPTOR(char*, strchr, const char *str, int c) {
+#if MAC_INTERPOSE_FUNCTIONS
+  if (!asan_inited) return REAL(strchr)(str, c);
+#endif
   ENSURE_ASAN_INITED();
   char *result = REAL(strchr)(str, c);
   if (flags()->replace_str) {
@@ -322,6 +328,9 @@
 }
 
 INTERCEPTOR(int, strcmp, const char *s1, const char *s2) {
+#if MAC_INTERPOSE_FUNCTIONS
+  if (!asan_inited) return REAL(strcmp)(s1, s2);
+#endif
   if (asan_init_is_running) {
     return REAL(strcmp)(s1, s2);
   }
@@ -339,6 +348,9 @@
 }
 
 INTERCEPTOR(char*, strcpy, char *to, const char *from) {  // NOLINT
+#if MAC_INTERPOSE_FUNCTIONS
+  if (!asan_inited) return REAL(strcpy)(to, from);
+#endif
   // strcpy is called from malloc_default_purgeable_zone()
   // in __asan::ReplaceSystemAlloc() on Mac.
   if (asan_init_is_running) {
@@ -356,6 +368,9 @@
 
 #if ASAN_INTERCEPT_STRDUP
 INTERCEPTOR(char*, strdup, const char *s) {
+#if MAC_INTERPOSE_FUNCTIONS
+  if (!asan_inited) return REAL(strdup)(s);
+#endif
   ENSURE_ASAN_INITED();
   if (flags()->replace_str) {
     uptr length = REAL(strlen)(s);
@@ -366,6 +381,9 @@
 #endif
 
 INTERCEPTOR(uptr, strlen, const char *s) {
+#if MAC_INTERPOSE_FUNCTIONS
+  if (!asan_inited) return REAL(strlen)(s);
+#endif
   // strlen is called from malloc_default_purgeable_zone()
   // in __asan::ReplaceSystemAlloc() on Mac.
   if (asan_init_is_running) {
@@ -410,6 +428,9 @@
 #endif  // ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP
 
 INTERCEPTOR(int, strncmp, const char *s1, const char *s2, uptr size) {
+#if MAC_INTERPOSE_FUNCTIONS
+  if (!asan_inited) return REAL(strncmp)(s1, s2, size);
+#endif
   // strncmp is called from malloc_default_purgeable_zone()
   // in __asan::ReplaceSystemAlloc() on Mac.
   if (asan_init_is_running) {
@@ -486,6 +507,9 @@
 }
 
 INTERCEPTOR(int, atoi, const char *nptr) {
+#if MAC_INTERPOSE_FUNCTIONS
+  if (!asan_inited) return REAL(atoi)(nptr);
+#endif
   ENSURE_ASAN_INITED();
   if (!flags()->replace_str) {
     return REAL(atoi)(nptr);
@@ -502,6 +526,9 @@
 }
 
 INTERCEPTOR(long, atol, const char *nptr) {  // NOLINT
+#if MAC_INTERPOSE_FUNCTIONS
+  if (!asan_inited) return REAL(atol)(nptr);
+#endif
   ENSURE_ASAN_INITED();
   if (!flags()->replace_str) {
     return REAL(atol)(nptr);
@@ -580,6 +607,9 @@
   static bool was_called_once;
   CHECK(was_called_once == false);
   was_called_once = true;
+#if MAC_INTERPOSE_FUNCTIONS
+  return;
+#endif
   // Intercept mem* functions.
   ASAN_INTERCEPT_FUNC(memcmp);
   ASAN_INTERCEPT_FUNC(memmove);
@@ -587,7 +617,11 @@
   if (PLATFORM_HAS_DIFFERENT_MEMCPY_AND_MEMMOVE) {
     ASAN_INTERCEPT_FUNC(memcpy);
   } else {
-    REAL(memcpy) = REAL(memmove);
+#if !MAC_INTERPOSE_FUNCTIONS
+    // If we're using dynamic interceptors on Mac, these two are just plain 
+    // functions.
+    *(uptr*)&REAL(memcpy) = (uptr)REAL(memmove);
+#endif
   }
 
   // Intercept str* functions.

Modified: compiler-rt/trunk/lib/asan/asan_malloc_mac.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_malloc_mac.cc?rev=162091&r1=162090&r2=162091&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_malloc_mac.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_malloc_mac.cc Fri Aug 17 04:00:08 2012
@@ -95,10 +95,14 @@
 // See http://code.google.com/p/address-sanitizer/issues/detail?id=87
 // and http://opensource.apple.com/source/CF/CF-550.43/CFRuntime.c
 INTERCEPTOR(void, __CFInitialize) {
+  // If the runtime is built as dynamic library, __CFInitialize wrapper may be
+  // called before __asan_init.
+#if !MAC_INTERPOSE_FUNCTIONS
   CHECK(flags()->replace_cfallocator);
   CHECK(asan_inited);
+#endif
   REAL(__CFInitialize)();
-  if (!cf_asan) ReplaceCFAllocator();
+  if (!cf_asan && asan_inited) ReplaceCFAllocator();
 }
 
 namespace {

Added: compiler-rt/trunk/lib/asan/dynamic/asan_interceptors_dynamic.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/dynamic/asan_interceptors_dynamic.cc?rev=162091&view=auto
==============================================================================
--- compiler-rt/trunk/lib/asan/dynamic/asan_interceptors_dynamic.cc (added)
+++ compiler-rt/trunk/lib/asan/dynamic/asan_interceptors_dynamic.cc Fri Aug 17 04:00:08 2012
@@ -0,0 +1,93 @@
+//===-- asan_interceptors_dynamic.cc --------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// __DATA,__interpose section of the dynamic runtime library for Mac OS.
+//===----------------------------------------------------------------------===//
+
+#if defined(__APPLE__)
+
+#include "asan_interceptors.h"
+#include "asan_intercepted_functions.h"
+
+namespace __asan {
+
+#define INTERPOSE_FUNCTION(function) \
+    { reinterpret_cast<const uptr>(WRAP(function)), \
+      reinterpret_cast<const uptr>(function) }
+
+#define INTERPOSE_FUNCTION_2(function, wrapper) \
+    { reinterpret_cast<const uptr>(wrapper), \
+      reinterpret_cast<const uptr>(function) }
+
+struct interpose_substitution {
+  const uptr replacement;
+  const uptr original;
+};
+
+__attribute__((used))
+const interpose_substitution substitutions[]
+    __attribute__((section("__DATA, __interpose"))) = {
+  INTERPOSE_FUNCTION(strlen),
+  INTERPOSE_FUNCTION(memcmp),
+  INTERPOSE_FUNCTION(memcpy),
+  INTERPOSE_FUNCTION(memmove),
+  INTERPOSE_FUNCTION(memset),
+  INTERPOSE_FUNCTION(strchr),
+  INTERPOSE_FUNCTION(strcat),
+  INTERPOSE_FUNCTION(strncat),
+  INTERPOSE_FUNCTION(strcpy),
+  INTERPOSE_FUNCTION(strncpy),
+  INTERPOSE_FUNCTION(pthread_create),
+  INTERPOSE_FUNCTION(longjmp),
+  INTERPOSE_FUNCTION(_longjmp),
+  INTERPOSE_FUNCTION(siglongjmp),
+#if ASAN_INTERCEPT_STRDUP
+  INTERPOSE_FUNCTION(strdup),
+#endif
+#if ASAN_INTERCEPT_STRNLEN
+  INTERPOSE_FUNCTION(strnlen),
+#endif
+#if ASAN_INTERCEPT_INDEX
+  INTERPOSE_FUNCTION_2(index, WRAP(strchr)),
+#endif
+  INTERPOSE_FUNCTION(strcmp),
+  INTERPOSE_FUNCTION(strncmp),
+#if ASAN_INTERCEPT_STRCASECMP_AND_STRNCASECMP
+  INTERPOSE_FUNCTION(strcasecmp),
+  INTERPOSE_FUNCTION(strncasecmp),
+#endif
+  INTERPOSE_FUNCTION(atoi),
+  INTERPOSE_FUNCTION(atol),
+  INTERPOSE_FUNCTION(strtol),
+#if ASAN_INTERCEPT_ATOLL_AND_STRTOLL
+  INTERPOSE_FUNCTION(atoll),
+  INTERPOSE_FUNCTION(strtoll),
+#endif
+#if ASAN_INTERCEPT_MLOCKX
+  INTERPOSE_FUNCTION(mlock),
+  INTERPOSE_FUNCTION(munlock),
+  INTERPOSE_FUNCTION(mlockall),
+  INTERPOSE_FUNCTION(munlockall),
+#endif
+  INTERPOSE_FUNCTION(dispatch_async_f),
+  INTERPOSE_FUNCTION(dispatch_sync_f),
+  INTERPOSE_FUNCTION(dispatch_after_f),
+  INTERPOSE_FUNCTION(dispatch_barrier_async_f),
+  INTERPOSE_FUNCTION(dispatch_group_async_f),
+
+  INTERPOSE_FUNCTION(__CFInitialize),
+  INTERPOSE_FUNCTION(CFStringCreateCopy),
+  INTERPOSE_FUNCTION(free),
+};
+
+}  // namespace __asan
+
+#endif  // __APPLE__

Modified: compiler-rt/trunk/lib/interception/interception.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/interception/interception.h?rev=162091&r1=162090&r2=162091&view=diff
==============================================================================
--- compiler-rt/trunk/lib/interception/interception.h (original)
+++ compiler-rt/trunk/lib/interception/interception.h Fri Aug 17 04:00:08 2012
@@ -75,6 +75,16 @@
 // mach_override, a handy framework for patching functions at runtime.
 // To avoid possible name clashes, our replacement functions have
 // the "wrap_" prefix on Mac.
+// An alternative to function patching is to create a dylib containing a
+// __DATA,__interpose section that associates library functions with their
+// wrappers. When this dylib is preloaded before an executable using
+// DYLD_INSERT_LIBRARIES, it routes all the calls to interposed functions done
+// through stubs to the wrapper functions. Such a library is built with
+// -DMAC_INTERPOSE_FUNCTIONS=1.
+
+#if !defined(MAC_INTERPOSE_FUNCTIONS) || !defined(__APPLE__)
+# define MAC_INTERPOSE_FUNCTIONS 0
+#endif
 
 #if defined(__APPLE__)
 # define WRAP(x) wrap_##x
@@ -101,15 +111,21 @@
     __attribute__((weak, alias("__interceptor_" #func), visibility("default")));
 #endif
 
-#define PTR_TO_REAL(x) real_##x
-#define REAL(x) __interception::PTR_TO_REAL(x)
-#define FUNC_TYPE(x) x##_f
-
-#define DECLARE_REAL(ret_type, func, ...) \
-  typedef ret_type (*FUNC_TYPE(func))(__VA_ARGS__); \
-  namespace __interception { \
-    extern FUNC_TYPE(func) PTR_TO_REAL(func); \
-  }
+#if !MAC_INTERPOSE_FUNCTIONS
+# define PTR_TO_REAL(x) real_##x
+# define REAL(x) __interception::PTR_TO_REAL(x)
+# define FUNC_TYPE(x) x##_f
+
+# define DECLARE_REAL(ret_type, func, ...) \
+    typedef ret_type (*FUNC_TYPE(func))(__VA_ARGS__); \
+    namespace __interception { \
+      extern FUNC_TYPE(func) PTR_TO_REAL(func); \
+    }
+#else  // MAC_INTERPOSE_FUNCTIONS
+# define REAL(x) x
+# define DECLARE_REAL(ret_type, func, ...) \
+    extern "C" ret_type func(__VA_ARGS__);
+#endif  // MAC_INTERPOSE_FUNCTIONS
 
 #define DECLARE_REAL_AND_INTERCEPTOR(ret_type, func, ...) \
   DECLARE_REAL(ret_type, func, ##__VA_ARGS__) \
@@ -118,11 +134,15 @@
 // FIXME(timurrrr): We might need to add DECLARE_REAL_EX etc to support
 // different calling conventions later.
 
-#define DEFINE_REAL_EX(ret_type, convention, func, ...) \
-  typedef ret_type (convention *FUNC_TYPE(func))(__VA_ARGS__); \
-  namespace __interception { \
-    FUNC_TYPE(func) PTR_TO_REAL(func); \
-  }
+#if !MAC_INTERPOSE_FUNCTIONS
+# define DEFINE_REAL_EX(ret_type, convention, func, ...) \
+    typedef ret_type (convention *FUNC_TYPE(func))(__VA_ARGS__); \
+    namespace __interception { \
+      FUNC_TYPE(func) PTR_TO_REAL(func); \
+    }
+#else
+# define DEFINE_REAL_EX(ret_type, convention, func, ...)
+#endif
 
 // Generally, you don't need to use DEFINE_REAL by itself, as INTERCEPTOR
 // macros does its job. In exceptional cases you may need to call REAL(foo)





More information about the llvm-commits mailing list