AddressSanitizer: start factoring out interception machinery

llvm-svn: 150083
This commit is contained in:
Alexey Samsonov 2012-02-08 19:52:01 +00:00
parent 27c8f620ee
commit 8489f2a564
13 changed files with 363 additions and 177 deletions

View File

@ -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 @@ Implementation := Generic
# 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=%)

View File

@ -178,6 +178,9 @@ RTL_HDR=asan_allocator.h \
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 @@ LIBASAN_OBJ=$(BIN)/asan_rtl$(SUFF).o \
$(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 @@ t64: b64
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 @@ lib64:
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 @@ ADDRESS_SANITIZER_CPP=../../../../lib/Transforms/Instrumentation/AddressSanitize
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:

View File

@ -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 @@ INTERCEPTOR(size_t, strnlen, const char *s, size_t maxlen) {
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 @@ void InitializeAsanInterceptors() {
// 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 @@ void InitializeAsanInterceptors() {
// 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");

View File

@ -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);

View File

@ -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 @@ void AsanStackTrace::GetStackTrace(size_t max_s, uintptr_t pc, uintptr_t bp) {
}
}
// 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 @@ mach_error_t __asan_allocate_island(void **ptr,
}
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;

View File

@ -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 @@ typedef struct {
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);

View File

@ -310,7 +310,7 @@ extern bool kCFUseCollectableAllocator; // is GC on?
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 @@ void ReplaceSystemMalloc() {
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;

View File

@ -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=%)

View File

@ -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

View File

@ -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__

View File

@ -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__

View File

@ -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__

View File

@ -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__