[llvm-commits] PATCH: AddressSanitizer: start factoring out interception machinery (issue 5642046)
samsonov at google.com
samsonov at google.com
Tue Feb 7 04:30:28 PST 2012
Reviewers: kcc, ramosian.glider, timurrrr_at_google_com,
Please review this at http://codereview.appspot.com/5642046/
Affected files:
M Makefile.mk
M Makefile.old
M asan_interceptors.cc
M asan_interceptors.h
M asan_mac.cc
M asan_malloc_mac.cc
A interception/Makefile.mk
A interception/interception.h
A interception/interception_linux.cc
A interception/interception_mac.cc
-------------- next part --------------
Index: Makefile.mk
===================================================================
--- Makefile.mk (revision 149970)
+++ Makefile.mk (working copy)
@@ -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)
Index: Makefile.old
===================================================================
--- Makefile.old (revision 149970)
+++ Makefile.old (working copy)
@@ -178,6 +178,7 @@
asan_stats.h \
asan_thread.h \
asan_thread_registry.h \
+ interception/interception.h \
mach_override/mach_override.h
LIBASAN_OBJ=$(BIN)/asan_rtl$(SUFF).o \
@@ -195,6 +196,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
@@ -226,6 +229,7 @@
$(BIN):
mkdir -p $(BIN)
+ mkdir -p $(BIN)/interception
mkdir -p $(BIN)/mach_override
clang:
@@ -329,6 +333,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:
Index: asan_interceptors.cc
===================================================================
--- asan_interceptors.cc (revision 149970)
+++ asan_interceptors.cc (working copy)
@@ -21,75 +21,23 @@
#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>
+#endif // __APPLE__
-#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
-
namespace __asan {
// Instruments read/write access to a single byte in memory.
@@ -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);
+ 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));
- 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(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");
Index: asan_interceptors.h
===================================================================
--- asan_interceptors.h (revision 149970)
+++ asan_interceptors.h (working copy)
@@ -15,67 +15,8 @@
#define ASAN_INTERCEPTORS_H
#include "asan_internal.h"
+#include "interception/interception.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__)
-
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);
DECLARE_REAL(void*, memset, void *block, int c, size_t size);
Index: asan_mac.cc
===================================================================
--- asan_mac.cc (revision 149970)
+++ asan_mac.cc (working copy)
@@ -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,47 +312,6 @@
}
}
-// The range of pages to be used by __asan_mach_override_ptr 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.
-#if __WORDSIZE == 32
-#define kIslandEnd (0xffdf0000 - kPageSize)
-#define kIslandBeg (kIslandEnd - 256 * kPageSize)
-#else
-#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) {
- if (!island_allocator_pos) {
- island_allocator_pos =
- asan_mmap((void*)kIslandBeg, kIslandEnd - kIslandBeg,
- PROT_READ | PROT_WRITE | PROT_EXEC,
- MAP_PRIVATE | MAP_ANON | MAP_FIXED,
- -1, 0);
- if (island_allocator_pos != (void*)kIslandBeg) {
- return KERN_NO_SPACE;
- }
- };
- *ptr = island_allocator_pos;
- island_allocator_pos = (char*)island_allocator_pos + kPageSize;
- return err_none;
-}
-
-extern "C"
-mach_error_t __asan_deallocate_island(void *ptr) {
- // Do nothing.
- // TODO(glider): allow to free and reuse the island memory.
- return err_none;
-}
-
// Support for the following functions from libdispatch on Mac OS:
// dispatch_async_f()
// dispatch_async()
Index: interception/Makefile.mk
===================================================================
--- interception/Makefile.mk (revision 0)
+++ interception/Makefile.mk (revision 0)
@@ -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=%)
Index: interception/interception_linux.cc
===================================================================
--- interception/interception_linux.cc (revision 0)
+++ interception/interception_linux.cc (revision 0)
@@ -0,0 +1,22 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+// Author: samsonov at google.com (Alexey Samsonov)
+
+#ifdef __linux__
+
+#include "interception.h"
+#include <dlfcn.h> // for dlsym
+
+extern "C"
+bool OverrideFunction(void *old_func, void *new_func, void **orig_old_func) {
+ // not implemented
+ return false;
+}
+
+extern "C"
+bool GetRealFunctionAddress(const char *func_name,
+ void **func_addr) {
+ *func_addr = dlsym(RTLD_NEXT, func_name);
+ return (*func_addr != NULL);
+}
+
+#endif // __linux__
Index: interception/interception_mac.cc
===================================================================
--- interception/interception_mac.cc (revision 0)
+++ interception/interception_mac.cc (revision 0)
@@ -0,0 +1,83 @@
+//===-- 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__
+
+#include "interception.h"
+#include "../mach_override/mach_override.h"
+#include <stddef.h> // for NULL
+#include <sys/mman.h> // for mmap
+
+// The range of pages to be used by __asan_mach_override_ptr 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 const size_t kPageSizeBits = 12;
+static const size_t kPageSize = 1UL << kPageSizeBits;
+static void *island_allocator_pos = NULL;
+
+#if __WORDSIZE == 32
+# define kIslandEnd (0xffdf0000 - kPageSize)
+# define kIslandBeg (kIslandEnd - 256 * kPageSize)
+#else
+# 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) {
+ if (!island_allocator_pos) {
+ island_allocator_pos =
+ mmap((void*)kIslandBeg, kIslandEnd - kIslandBeg,
+ PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_PRIVATE | MAP_ANON | MAP_FIXED,
+ -1, 0);
+ if (island_allocator_pos != (void*)kIslandBeg) {
+ return KERN_NO_SPACE;
+ }
+ };
+ *ptr = island_allocator_pos;
+ island_allocator_pos = (char*)island_allocator_pos + kPageSize;
+ return err_none;
+}
+
+extern "C"
+mach_error_t __asan_deallocate_island(void *ptr) {
+ // Do nothing.
+ // TODO(glider): allow to free and reuse the island memory.
+ return err_none;
+}
+
+extern "C"
+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,
+ __asan_allocate_island,
+ __asan_deallocate_island);
+ return (res == 0) && (*orig_old_func != NULL);
+}
+
+extern "C"
+bool GetRealFunctionAddress(const char *func_name, void **func_addr) {
+ // not implemented
+ return false;
+}
+
+#endif // __APPLE__
Index: interception/interception.h
===================================================================
--- interception/interception.h (revision 0)
+++ interception/interception.h (revision 0)
@@ -0,0 +1,117 @@
+//===-- 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
+
+// How to use:
+// 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 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.
+
+// Notes: 1. Things may not work properly if macro INTERCEPT(...) {...} or
+// DECLARE_REAL(...); will be 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 REAL(x) real_##x
+#define FUNC_TYPE(x) x##_f
+
+#define DECLARE_REAL(ret_type, func, ...); \
+ typedef ret_type (*FUNC_TYPE(func))(__VA_ARGS__); \
+ 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__); \
+ 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__)
+
+extern "C" {
+// returns true if the old function existed.
+bool OverrideFunction(void *old_func, void *new_func, void **orig_old_func);
+// returns true if a function with the given name was found.
+bool GetRealFunctionAddress(const char *func_name, void **func_addr);
+} // extern "C"
+
+#if defined(__linux__)
+# define INTERCEPT_FUNCTION(func) \
+ GetRealFunctionAddress(#func, (void**)&REAL(func))
+#elif defined(__APPLE__)
+# define OVERRIDE_FUNCTION(old_func, new_func) \
+ OverrideFunction((void*)old_func, (void*)new_func, (void**)&REAL(old_func))
+# define INTERCEPT_FUNCTION(func) OVERRIDE_FUNCTION(func, WRAP(func))
+#else // defined(_WIN32)
+ // FIXME: deal with interception on Win.
+# define INTERCEPT_FUNCTON(func) true
+#endif
+
+#endif // INTERCEPTION_H
Index: asan_malloc_mac.cc
===================================================================
--- asan_malloc_mac.cc (revision 149970)
+++ asan_malloc_mac.cc (working copy)
@@ -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;
More information about the llvm-commits
mailing list