[llvm-commits] [compiler-rt] r150083 - in /compiler-rt/trunk/lib/asan: Makefile.mk Makefile.old asan_interceptors.cc asan_interceptors.h asan_mac.cc asan_mac.h asan_malloc_mac.cc interception/ interception/Makefile.mk interception/interception.h interception/interception_linux.cc interception/interception_linux.h interception/interception_mac.cc interception/interception_mac.h

Alexey Samsonov samsonov at google.com
Wed Feb 8 11:52:01 PST 2012


Author: samsonov
Date: Wed Feb  8 13:52:01 2012
New Revision: 150083

URL: http://llvm.org/viewvc/llvm-project?rev=150083&view=rev
Log:
AddressSanitizer: start factoring out interception machinery

Added:
    compiler-rt/trunk/lib/asan/interception/
    compiler-rt/trunk/lib/asan/interception/Makefile.mk
    compiler-rt/trunk/lib/asan/interception/interception.h
    compiler-rt/trunk/lib/asan/interception/interception_linux.cc
    compiler-rt/trunk/lib/asan/interception/interception_linux.h
    compiler-rt/trunk/lib/asan/interception/interception_mac.cc
    compiler-rt/trunk/lib/asan/interception/interception_mac.h
Modified:
    compiler-rt/trunk/lib/asan/Makefile.mk
    compiler-rt/trunk/lib/asan/Makefile.old
    compiler-rt/trunk/lib/asan/asan_interceptors.cc
    compiler-rt/trunk/lib/asan/asan_interceptors.h
    compiler-rt/trunk/lib/asan/asan_mac.cc
    compiler-rt/trunk/lib/asan/asan_mac.h
    compiler-rt/trunk/lib/asan/asan_malloc_mac.cc

Modified: compiler-rt/trunk/lib/asan/Makefile.mk
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/Makefile.mk?rev=150083&r1=150082&r2=150083&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/Makefile.mk (original)
+++ compiler-rt/trunk/lib/asan/Makefile.mk Wed Feb  8 13:52:01 2012
@@ -8,7 +8,7 @@
 #===------------------------------------------------------------------------===#
 
 ModuleName := asan
-SubDirs := mach_override
+SubDirs := interception mach_override
 
 Sources := $(foreach file,$(wildcard $(Dir)/*.cc),$(notdir $(file)))
 ObjNames := $(Sources:%.cc=%.o)
@@ -17,6 +17,8 @@
 
 # FIXME: use automatic dependencies?
 Dependencies := $(wildcard $(Dir)/*.h)
+Dependencies += $(wildcard $(Dir)/interception/*.h)
+Dependencies += $(wildcard $(Dir)/mach_override/*.h)
 
 # Define a convenience variable for all the asan functions.
 AsanFunctions := $(Sources:%.cc=%)

Modified: compiler-rt/trunk/lib/asan/Makefile.old
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/Makefile.old?rev=150083&r1=150082&r2=150083&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/Makefile.old (original)
+++ compiler-rt/trunk/lib/asan/Makefile.old Wed Feb  8 13:52:01 2012
@@ -178,6 +178,9 @@
 	asan_stats.h \
 	asan_thread.h \
 	asan_thread_registry.h \
+	interception/interception.h \
+	interception/interception_linux.h \
+	interception/interception_mac.h \
 	mach_override/mach_override.h
 
 LIBASAN_OBJ=$(BIN)/asan_rtl$(SUFF).o \
@@ -195,6 +198,8 @@
 	    $(BIN)/asan_stats$(SUFF).o  \
 	    $(BIN)/asan_thread$(SUFF).o  \
 	    $(BIN)/asan_thread_registry$(SUFF).o  \
+	    $(BIN)/interception/interception_linux$(SUFF).o  \
+	    $(BIN)/interception/interception_mac$(SUFF).o  \
 	    $(BIN)/mach_override/mach_override$(SUFF).o
 
 GTEST_ROOT=third_party/googletest
@@ -215,9 +220,9 @@
 t32: b32
 	$(BIN)/asan_test32
 
-b64: | $(BIN)
+b64: | mk_bin_dir
 	$(MAKE) -f $(MAKEFILE) ARCH=x86_64 asan_test asan_benchmarks
-b32: | $(BIN)
+b32: | mk_bin_dir
 	$(MAKE) -f $(MAKEFILE) ARCH=i386 asan_test asan_benchmarks
 
 lib64:
@@ -225,8 +230,9 @@
 lib32:
 	$(MAKE) $(MAKEFILE) ARCH=i386 lib
 
-$(BIN):
+mk_bin_dir:
 	mkdir -p $(BIN)
+	mkdir -p $(BIN)/interception
 	mkdir -p $(BIN)/mach_override
 
 clang:
@@ -330,6 +336,7 @@
 lint:
 	third_party/cpplint/cpplint.py --filter=$(LLVM_LINT_FILTER) $(ADDRESS_SANITIZER_CPP)
 	third_party/cpplint/cpplint.py --filter=$(RTL_LINT_FITLER) asan_*.cc asan_*.h
+	third_party/cpplint/cpplint.py --filter=$(RTL_LINT_FITLER) interception/interception*.h interception/interception*.cc
 	third_party/cpplint/cpplint.py --filter=$(TEST_LINT_FITLER) tests/*.cc
 
 get_third_party:

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=150083&r1=150082&r2=150083&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_interceptors.cc Wed Feb  8 13:52:01 2012
@@ -21,74 +21,22 @@
 #include "asan_stack.h"
 #include "asan_stats.h"
 #include "asan_thread_registry.h"
+#include "interception/interception.h"
 
 #include <new>
 #include <ctype.h>
 
 #ifndef _WIN32
-#include <dlfcn.h>
 #include <pthread.h>
-#endif
+#endif  // _WIN32
 
-// 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().
 #if defined(__APPLE__)
-// Include the declarations of the original functions.
+// FIXME(samsonov): Gradually replace system headers with declarations of
+// intercepted functions.
 #include <signal.h>
 #include <string.h>
 #include <strings.h>
-
-#include "mach_override/mach_override.h"
-
-#define OVERRIDE_FUNCTION(oldfunc, newfunc)                                   \
-  do {CHECK(0 == __asan_mach_override_ptr_custom((void*)(oldfunc),            \
-                                                 (void*)(newfunc),            \
-                                                 (void**)&real_##oldfunc,     \
-                                                 __asan_allocate_island,      \
-                                                 __asan_deallocate_island));  \
-  CHECK(real_##oldfunc != NULL);   } while (0)
-
-#define OVERRIDE_FUNCTION_IF_EXISTS(oldfunc, newfunc)               \
-  do { __asan_mach_override_ptr_custom((void*)(oldfunc),            \
-                                       (void*)(newfunc),            \
-                                       (void**)&real_##oldfunc,     \
-                                       __asan_allocate_island,      \
-                                       __asan_deallocate_island);   \
-  } while (0)
-
-#define INTERCEPT_FUNCTION(func)                                        \
-  OVERRIDE_FUNCTION(func, WRAP(func))
-
-#define INTERCEPT_FUNCTION_IF_EXISTS(func)                              \
-  OVERRIDE_FUNCTION_IF_EXISTS(func, WRAP(func))
-
-#elif defined(_WIN32)
-// TODO(timurrrr): change these macros once we decide how to intercept
-// functions on Windows.
-#define INTERCEPT_FUNCTION(func)                                        \
-  do { } while (0)
-
-#define INTERCEPT_FUNCTION_IF_EXISTS(func)                              \
-  do { } while (0)
-
-#else  // __linux__
-#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
+#endif  // __APPLE__
 
 namespace __asan {
 
@@ -581,12 +529,12 @@
 namespace __asan {
 void InitializeAsanInterceptors() {
 #ifndef __APPLE__
-  INTERCEPT_FUNCTION(index);
+  CHECK(INTERCEPT_FUNCTION(index));
 #else
-  OVERRIDE_FUNCTION(index, WRAP(strchr));
+  CHECK(OVERRIDE_FUNCTION(index, WRAP(strchr)));
 #endif
-  INTERCEPT_FUNCTION(memcmp);
-  INTERCEPT_FUNCTION(memmove);
+  CHECK(INTERCEPT_FUNCTION(memcmp));
+  CHECK(INTERCEPT_FUNCTION(memmove));
 #ifdef __APPLE__
   // Wrap memcpy() on OS X 10.6 only, because on 10.7 memcpy() and memmove()
   // are resolved into memmove$VARIANT$sse42.
@@ -594,44 +542,44 @@
   // TODO(glider): need to check dynamically that memcpy() and memmove() are
   // actually the same function.
   if (GetMacosVersion() == MACOS_VERSION_SNOW_LEOPARD) {
-    INTERCEPT_FUNCTION(memcpy);
+    CHECK(INTERCEPT_FUNCTION(memcpy));
   } else {
     REAL(memcpy) = REAL(memmove);
   }
 #else
   // Always wrap memcpy() on non-Darwin platforms.
-  INTERCEPT_FUNCTION(memcpy);
+  CHECK(INTERCEPT_FUNCTION(memcpy));
 #endif
-  INTERCEPT_FUNCTION(memset);
-  INTERCEPT_FUNCTION(strcasecmp);
-  INTERCEPT_FUNCTION(strcat);  // NOLINT
-  INTERCEPT_FUNCTION(strchr);
-  INTERCEPT_FUNCTION(strcmp);
-  INTERCEPT_FUNCTION(strcpy);  // NOLINT
-  INTERCEPT_FUNCTION(strdup);
-  INTERCEPT_FUNCTION(strlen);
-  INTERCEPT_FUNCTION(strncasecmp);
-  INTERCEPT_FUNCTION(strncmp);
-  INTERCEPT_FUNCTION(strncpy);
-
-  INTERCEPT_FUNCTION(sigaction);
-  INTERCEPT_FUNCTION(signal);
-  INTERCEPT_FUNCTION(longjmp);
-  INTERCEPT_FUNCTION(_longjmp);
-  INTERCEPT_FUNCTION_IF_EXISTS(__cxa_throw);
-  INTERCEPT_FUNCTION(pthread_create);
+  CHECK(INTERCEPT_FUNCTION(memset));
+  CHECK(INTERCEPT_FUNCTION(strcasecmp));
+  CHECK(INTERCEPT_FUNCTION(strcat));  // NOLINT
+  CHECK(INTERCEPT_FUNCTION(strchr));
+  CHECK(INTERCEPT_FUNCTION(strcmp));
+  CHECK(INTERCEPT_FUNCTION(strcpy));  // NOLINT
+  CHECK(INTERCEPT_FUNCTION(strdup));
+  CHECK(INTERCEPT_FUNCTION(strlen));
+  CHECK(INTERCEPT_FUNCTION(strncasecmp));
+  CHECK(INTERCEPT_FUNCTION(strncmp));
+  CHECK(INTERCEPT_FUNCTION(strncpy));
+
+  CHECK(INTERCEPT_FUNCTION(sigaction));
+  CHECK(INTERCEPT_FUNCTION(signal));
+  CHECK(INTERCEPT_FUNCTION(longjmp));
+  CHECK(INTERCEPT_FUNCTION(_longjmp));
+  INTERCEPT_FUNCTION(__cxa_throw);
+  CHECK(INTERCEPT_FUNCTION(pthread_create));
 
 #ifdef __APPLE__
-  INTERCEPT_FUNCTION(dispatch_async_f);
-  INTERCEPT_FUNCTION(dispatch_sync_f);
-  INTERCEPT_FUNCTION(dispatch_after_f);
-  INTERCEPT_FUNCTION(dispatch_barrier_async_f);
-  INTERCEPT_FUNCTION(dispatch_group_async_f);
+  CHECK(INTERCEPT_FUNCTION(dispatch_async_f));
+  CHECK(INTERCEPT_FUNCTION(dispatch_sync_f));
+  CHECK(INTERCEPT_FUNCTION(dispatch_after_f));
+  CHECK(INTERCEPT_FUNCTION(dispatch_barrier_async_f));
+  CHECK(INTERCEPT_FUNCTION(dispatch_group_async_f));
   // We don't need to intercept pthread_workqueue_additem_np() to support the
   // libdispatch API, but it helps us to debug the unsupported functions. Let's
   // intercept it only during verbose runs.
   if (FLAG_v >= 2) {
-    INTERCEPT_FUNCTION(pthread_workqueue_additem_np);
+    CHECK(INTERCEPT_FUNCTION(pthread_workqueue_additem_np));
   }
   // Normally CFStringCreateCopy should not copy constant CF strings.
   // Replacing the default CFAllocator causes constant strings to be copied
@@ -640,15 +588,15 @@
   // http://code.google.com/p/address-sanitizer/issues/detail?id=10
   // Until this problem is fixed we need to check that the string is
   // non-constant before calling CFStringCreateCopy.
-  INTERCEPT_FUNCTION(CFStringCreateCopy);
+  CHECK(INTERCEPT_FUNCTION(CFStringCreateCopy));
 #else
   // On Darwin siglongjmp tailcalls longjmp, so we don't want to intercept it
   // there.
-  INTERCEPT_FUNCTION(siglongjmp);
+  CHECK(INTERCEPT_FUNCTION(siglongjmp));
 #endif
 
 #ifndef __APPLE__
-  INTERCEPT_FUNCTION(strnlen);
+  CHECK(INTERCEPT_FUNCTION(strnlen));
 #endif
   if (FLAG_v > 0) {
     Printf("AddressSanitizer: libc interceptors initialized\n");

Modified: compiler-rt/trunk/lib/asan/asan_interceptors.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_interceptors.h?rev=150083&r1=150082&r2=150083&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_interceptors.h (original)
+++ compiler-rt/trunk/lib/asan/asan_interceptors.h Wed Feb  8 13:52:01 2012
@@ -15,66 +15,7 @@
 #define ASAN_INTERCEPTORS_H
 
 #include "asan_internal.h"
-
-// Suppose you need to wrap/replace system function (generally, from libc):
-//      int foo(const char *bar, double baz);
-// You'll need to:
-//      1) define INTERCEPT(int, foo, const char *bar, double baz) { ... }
-//      2) add a line "INTERCEPT_FUNCTION(foo)" to InitializeAsanInterceptors()
-// You can access original function by calling __asan::real_foo(bar, baz).
-// By defualt, real_foo will be visible only inside your interceptor, and if
-// you want to use it in other parts of RTL, you'll need to:
-//      3a) add DECLARE_REAL(int, foo, const char*, double); to a
-//          header file.
-// However, if you want to implement your interceptor somewhere outside
-// asan_interceptors.cc, you'll instead need to:
-//      3b) add DECLARE_REAL_AND_INTERCEPTOR(int, foo, const char*, double);
-//          to a header.
-
-#if defined(__APPLE__)
-# define WRAP(x) wrap_##x
-# define WRAPPER_NAME(x) "wrap_"#x
-# define INTERCEPTOR_ATTRIBUTE
-#elif defined(_WIN32)
-// TODO(timurrrr): we're likely to use something else later on Windows.
-# define WRAP(x) wrap_##x
-# define WRAPPER_NAME(x) #x
-# define INTERCEPTOR_ATTRIBUTE
-#else
-# define WRAP(x) x
-# define WRAPPER_NAME(x) #x
-# define INTERCEPTOR_ATTRIBUTE __attribute__((visibility("default")))
-#endif
-
-#define REAL(x) real_##x
-#define FUNC_TYPE(x) x##_f
-
-#define DECLARE_REAL(ret_type, func, ...); \
-  typedef ret_type (*FUNC_TYPE(func))(__VA_ARGS__); \
-  namespace __asan { \
-    extern FUNC_TYPE(func) REAL(func); \
-  }
-
-#define DECLARE_REAL_AND_INTERCEPTOR(ret_type, func, ...); \
-    DECLARE_REAL(ret_type, func, ##__VA_ARGS__); \
-    extern "C" \
-    ret_type WRAP(func)(__VA_ARGS__);
-
-// 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)
-// without defining INTERCEPTOR(..., foo, ...). For example, if you override
-// foo with interceptor for other function.
-#define DEFINE_REAL(ret_type, func, ...); \
-  typedef ret_type (*FUNC_TYPE(func))(__VA_ARGS__); \
-  namespace __asan { \
-    FUNC_TYPE(func) REAL(func); \
-  }
-
-#define INTERCEPTOR(ret_type, func, ...); \
-  DEFINE_REAL(ret_type, func, __VA_ARGS__); \
-  extern "C" \
-  INTERCEPTOR_ATTRIBUTE \
-  ret_type WRAP(func)(__VA_ARGS__)
+#include "interception/interception.h"
 
 DECLARE_REAL(int, memcmp, const void *a1, const void *a2, size_t size);
 DECLARE_REAL(void*, memcpy, void *to, const void *from, size_t size);

Modified: compiler-rt/trunk/lib/asan/asan_mac.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_mac.cc?rev=150083&r1=150082&r2=150083&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_mac.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_mac.cc Wed Feb  8 13:52:01 2012
@@ -36,8 +36,6 @@
 
 namespace __asan {
 
-void *island_allocator_pos = NULL;
-
 void GetPcSpBp(void *context, uintptr_t *pc, uintptr_t *sp, uintptr_t *bp) {
   ucontext_t *ucontext = (ucontext_t*)context;
 # if __WORDSIZE == 64
@@ -314,25 +312,26 @@
   }
 }
 
-// The range of pages to be used by __asan_mach_override_ptr for escape
-// islands.
+// The range of pages to be used for escape islands.
 // TODO(glider): instead of mapping a fixed range we must find a range of
 // unmapped pages in vmmap and take them.
 // These constants were chosen empirically and may not work if the shadow
 // memory layout changes. Unfortunately they do necessarily depend on
 // kHighMemBeg or kHighMemEnd.
+static void *island_allocator_pos = NULL;
+
 #if __WORDSIZE == 32
-#define kIslandEnd (0xffdf0000 - kPageSize)
-#define kIslandBeg (kIslandEnd - 256 * kPageSize)
+# define kIslandEnd (0xffdf0000 - kPageSize)
+# define kIslandBeg (kIslandEnd - 256 * kPageSize)
 #else
-#define kIslandEnd (0x7fffffdf0000 - kPageSize)
-#define kIslandBeg (kIslandEnd - 256 * kPageSize)
+# define kIslandEnd (0x7fffffdf0000 - kPageSize)
+# define kIslandBeg (kIslandEnd - 256 * kPageSize)
 #endif
 
 extern "C"
-mach_error_t __asan_allocate_island(void **ptr,
-                                    size_t unused_size,
-                                    void *unused_hint) {
+mach_error_t __interception_allocate_island(void **ptr,
+                                            size_t unused_size,
+                                            void *unused_hint) {
   if (!island_allocator_pos) {
     island_allocator_pos =
         asan_mmap((void*)kIslandBeg, kIslandEnd - kIslandBeg,
@@ -349,7 +348,7 @@
 }
 
 extern "C"
-mach_error_t __asan_deallocate_island(void *ptr) {
+mach_error_t __interception_deallocate_island(void *ptr) {
   // Do nothing.
   // TODO(glider): allow to free and reuse the island memory.
   return err_none;

Modified: compiler-rt/trunk/lib/asan/asan_mac.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_mac.h?rev=150083&r1=150082&r2=150083&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_mac.h (original)
+++ compiler-rt/trunk/lib/asan/asan_mac.h Wed Feb  8 13:52:01 2012
@@ -20,7 +20,6 @@
 
 // TODO(glider): need to check if the OS X version is 10.6 or greater.
 #include <dispatch/dispatch.h>
-#include <mach/mach_error.h>
 #include <setjmp.h>
 #include <CoreFoundation/CFString.h>
 
@@ -79,15 +78,6 @@
 
 
 extern "C" {
-// Allocate memory for the escape island. This cannot be moved to
-// mach_override, because the allocator needs to know about the ASan shadow
-// mappings.
-// TODO(glider): in order to place a relative jump the allocated memory should
-// be within 2 Gb from the hint address.
-mach_error_t __asan_allocate_island(void **ptr, size_t unused_size,
-                                    void *unused_hint);
-mach_error_t __asan_deallocate_island(void *ptr);
-
 // dispatch_barrier_async_f() is not declared in <dispatch/dispatch.h>.
 void dispatch_barrier_async_f(dispatch_queue_t dq,
                               void *ctxt, dispatch_function_t func);

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=150083&r1=150082&r2=150083&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_malloc_mac.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_malloc_mac.cc Wed Feb  8 13:52:01 2012
@@ -310,7 +310,7 @@
 namespace __asan {
 void ReplaceSystemMalloc() {
   static malloc_introspection_t asan_introspection;
-  __asan::REAL(memset)(&asan_introspection, 0, sizeof(asan_introspection));
+  REAL(memset)(&asan_introspection, 0, sizeof(asan_introspection));
 
   asan_introspection.enumerator = &mi_enumerator;
   asan_introspection.good_size = &mi_good_size;
@@ -321,7 +321,7 @@
   asan_introspection.force_unlock = &mi_force_unlock;
 
   static malloc_zone_t asan_zone;
-  __asan::REAL(memset)(&asan_zone, 0, sizeof(malloc_zone_t));
+  REAL(memset)(&asan_zone, 0, sizeof(malloc_zone_t));
 
   // Start with a version 4 zone which is used for OS X 10.4 and 10.5.
   asan_zone.version = 4;

Added: compiler-rt/trunk/lib/asan/interception/Makefile.mk
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/interception/Makefile.mk?rev=150083&view=auto
==============================================================================
--- compiler-rt/trunk/lib/asan/interception/Makefile.mk (added)
+++ compiler-rt/trunk/lib/asan/interception/Makefile.mk Wed Feb  8 13:52:01 2012
@@ -0,0 +1,22 @@
+#===- lib/asan/interception/Makefile.mk --------------------*- Makefile -*--===#
+#
+#                     The LLVM Compiler Infrastructure
+#
+# This file is distributed under the University of Illinois Open Source
+# License. See LICENSE.TXT for details.
+#
+#===------------------------------------------------------------------------===#
+
+ModuleName := asan
+SubDirs :=
+
+Sources := $(foreach file,$(wildcard $(Dir)/*.cc),$(notdir $(file)))
+ObjNames := $(Sources:%.cc=%.o)
+
+Implementation := Generic
+
+# FIXME: use automatic dependencies?
+Dependencies := $(wildcard $(Dir)/*.h)
+
+# Define a convenience variable for all the asan functions.
+AsanFunctions += $(Sources:%.cc=%)

Added: compiler-rt/trunk/lib/asan/interception/interception.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/interception/interception.h?rev=150083&view=auto
==============================================================================
--- compiler-rt/trunk/lib/asan/interception/interception.h (added)
+++ compiler-rt/trunk/lib/asan/interception/interception.h Wed Feb  8 13:52:01 2012
@@ -0,0 +1,136 @@
+//===-- interception.h ------------------------------------------*- C++ -*-===//
+//
+//                     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.
+//
+// Machinery for providing replacements/wrappers for system functions.
+//===----------------------------------------------------------------------===//
+
+#ifndef INTERCEPTION_H
+#define INTERCEPTION_H
+
+#if !defined(__linux__) && !defined(__APPLE__) && !defined(_WIN32)
+# error "Interception doesn't work on this operating system."
+#endif
+
+// How to use this library:
+//      1) Include this header to define your own interceptors
+//         (see details below).
+//      2) Build all *.cc files and link against them.
+// On Mac you will also need to:
+//      3) Provide your own implementation for the following functions:
+//           mach_error_t __interception::allocate_island(void **ptr,
+//                                                      size_t size,
+//                                                      void *hint);
+//           mach_error_t __interception::deallocate_island(void *ptr);
+//         See "interception_mac.h" for more details.
+
+// How to add an interceptor:
+// Suppose you need to wrap/replace system function (generally, from libc):
+//      int foo(const char *bar, double baz);
+// You'll need to:
+//      1) define INTERCEPTOR(int, foo, const char *bar, double baz) { ... } in
+//         your source file.
+//      2) Call "INTERCEPT_FUNCTION(foo)" prior to the first call of "foo".
+//         INTERCEPT_FUNCTION(foo) evaluates to "true" iff the function was
+//         intercepted successfully.
+// You can access original function by calling REAL(foo)(bar, baz).
+// By default, REAL(foo) will be visible only inside your interceptor, and if
+// you want to use it in other parts of RTL, you'll need to:
+//      3a) add DECLARE_REAL(int, foo, const char*, double); to a
+//          header file.
+// However, if the call "INTERCEPT_FUNCTION(foo)" and definition for
+// INTERCEPTOR(..., foo, ...) are in different files, you'll instead need to:
+//      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
+//           DECLARE_REAL(...); are located inside namespaces.
+//        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
+//           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
+// 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.
+
+#if defined(__APPLE__)
+# define WRAP(x) wrap_##x
+# define WRAPPER_NAME(x) "wrap_"#x
+# define INTERCEPTOR_ATTRIBUTE
+#elif defined(_WIN32)
+// TODO(timurrrr): we're likely to use something else later on Windows.
+# define WRAP(x) wrap_##x
+# define WRAPPER_NAME(x) #x
+# define INTERCEPTOR_ATTRIBUTE
+#else
+# define WRAP(x) x
+# define WRAPPER_NAME(x) #x
+# define INTERCEPTOR_ATTRIBUTE __attribute__((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); \
+  }
+
+#define DECLARE_REAL_AND_INTERCEPTOR(ret_type, func, ...); \
+  DECLARE_REAL(ret_type, func, ##__VA_ARGS__); \
+  extern "C" ret_type WRAP(func)(__VA_ARGS__);
+
+// 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)
+// without defining INTERCEPTOR(..., foo, ...). For example, if you override
+// foo with an interceptor for other function.
+#define DEFINE_REAL(ret_type, func, ...); \
+  typedef ret_type (*FUNC_TYPE(func))(__VA_ARGS__); \
+  namespace __interception { \
+    FUNC_TYPE(func) PTR_TO_REAL(func); \
+  }
+
+#define INTERCEPTOR(ret_type, func, ...) \
+  DEFINE_REAL(ret_type, func, __VA_ARGS__); \
+  extern "C" \
+  INTERCEPTOR_ATTRIBUTE \
+  ret_type WRAP(func)(__VA_ARGS__)
+
+#define INCLUDED_FROM_INTERCEPTION_LIB
+
+#if defined(__linux__)
+# include "interception_linux.h"
+# 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)
+  // FIXME: deal with interception on Win.
+# define INTERCEPT_FUNCTON(func) true
+#endif
+
+#undef INCLUDED_FROM_INTERCEPTION_LIB
+
+#endif  // INTERCEPTION_H

Added: compiler-rt/trunk/lib/asan/interception/interception_linux.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/interception/interception_linux.cc?rev=150083&view=auto
==============================================================================
--- compiler-rt/trunk/lib/asan/interception/interception_linux.cc (added)
+++ compiler-rt/trunk/lib/asan/interception/interception_linux.cc Wed Feb  8 13:52:01 2012
@@ -0,0 +1,27 @@
+//===-- interception_linux.cc -----------------------------------*- C++ -*-===//
+//
+//                     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.
+//
+// Linux-specific interception methods.
+//===----------------------------------------------------------------------===//
+
+#ifdef __linux__
+
+#include <dlfcn.h>  // for dlsym
+
+namespace __interception {
+bool GetRealFunctionAddress(const char *func_name, void **func_addr) {
+  *func_addr = dlsym(RTLD_NEXT, func_name);
+  return (*func_addr != NULL);
+}
+}  // namespace __interception
+
+
+#endif  // __linux__

Added: compiler-rt/trunk/lib/asan/interception/interception_linux.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/interception/interception_linux.h?rev=150083&view=auto
==============================================================================
--- compiler-rt/trunk/lib/asan/interception/interception_linux.h (added)
+++ compiler-rt/trunk/lib/asan/interception/interception_linux.h Wed Feb  8 13:52:01 2012
@@ -0,0 +1,33 @@
+//===-- interception_linux.h ------------------------------------*- C++ -*-===//
+//
+//                     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.
+//
+// Linux-specific interception methods.
+//===----------------------------------------------------------------------===//
+
+#ifdef __linux__
+
+#if !defined(INCLUDED_FROM_INTERCEPTION_LIB)
+# error "interception_mac.h should be included from interception library only"
+#endif
+
+#ifndef INTERCEPTION_LINUX_H
+#define INTERCEPTION_LINUX_H
+
+namespace __interception {
+// returns true if a function with the given name was found.
+bool GetRealFunctionAddress(const char *func_name, void **func_addr);
+}  // namespace __interception
+
+#define INTERCEPT_FUNCTION_LINUX(func) \
+    ::__interception::GetRealFunctionAddress(#func, (void**)&REAL(func))
+
+#endif  // INTERCEPTION_LINUX_H
+#endif  // __linux__

Added: compiler-rt/trunk/lib/asan/interception/interception_mac.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/interception/interception_mac.cc?rev=150083&view=auto
==============================================================================
--- compiler-rt/trunk/lib/asan/interception/interception_mac.cc (added)
+++ compiler-rt/trunk/lib/asan/interception/interception_mac.cc Wed Feb  8 13:52:01 2012
@@ -0,0 +1,34 @@
+//===-- interception_mac.cc -------------------------------------*- C++ -*-===//
+//
+//                     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.
+//
+// Mac-specific interception methods.
+//===----------------------------------------------------------------------===//
+
+#ifdef __APPLE__
+
+#define INCLUDED_FROM_INTERCEPTION_LIB
+#include "interception_mac.h"
+#undef INCLUDED_FROM_INTERCEPTION_LIB
+// FIXME(samsonov): Put mach_override/ under interception/
+#include "../mach_override/mach_override.h"
+
+namespace __interception {
+bool OverrideFunction(void *old_func, void *new_func, void **orig_old_func) {
+  *orig_old_func = NULL;
+  int res = __asan_mach_override_ptr_custom(old_func, new_func,
+                                            orig_old_func,
+                                            __interception_allocate_island,
+                                            __interception_deallocate_island);
+  return (res == 0) && (*orig_old_func != NULL);
+}
+}  // namespace __interception
+
+#endif  // __APPLE__

Added: compiler-rt/trunk/lib/asan/interception/interception_mac.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/interception/interception_mac.h?rev=150083&view=auto
==============================================================================
--- compiler-rt/trunk/lib/asan/interception/interception_mac.h (added)
+++ compiler-rt/trunk/lib/asan/interception/interception_mac.h Wed Feb  8 13:52:01 2012
@@ -0,0 +1,47 @@
+//===-- interception_mac.h --------------------------------------*- C++ -*-===//
+//
+//                     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.
+//
+// Mac-specific interception methods.
+//===----------------------------------------------------------------------===//
+
+#ifdef __APPLE__
+
+#if !defined(INCLUDED_FROM_INTERCEPTION_LIB)
+# error "interception_mac.h should be included from interception.h only"
+#endif
+
+#ifndef INTERCEPTION_MAC_H
+#define INTERCEPTION_MAC_H
+
+#include <mach/mach_error.h>
+#include <stddef.h>
+
+// Allocate memory for the escape island. This cannot be moved to
+// mach_override, because each user of interceptors may specify its
+// own memory range for escape islands.
+extern "C" {
+mach_error_t __interception_allocate_island(void **ptr, size_t unused_size,
+                                            void *unused_hint);
+mach_error_t __interception_deallocate_island(void *ptr);
+}  // extern "C"
+
+namespace __interception {
+// returns true if the old function existed.
+bool OverrideFunction(void *old_func, void *new_func, void **orig_old_func);
+}  // namespace __interception
+
+# define OVERRIDE_FUNCTION_MAC(old_func, new_func) \
+    ::__interception::OverrideFunction((void*)old_func, (void*)new_func, \
+                                       (void**)&REAL(old_func))
+# define INTERCEPT_FUNCTION_MAC(func) OVERRIDE_FUNCTION_MAC(func, WRAP(func))
+
+#endif  // INTERCEPTION_MAC_H
+#endif  // __APPLE__





More information about the llvm-commits mailing list