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.

llvm-svn: 162091
This commit is contained in:
Alexander Potapenko 2012-08-17 09:00:08 +00:00
parent c4540bc6a3
commit c62210e3ff
5 changed files with 195 additions and 15 deletions

View File

@ -22,6 +22,11 @@ set(ASAN_SOURCES
asan_win.cc
)
set(ASAN_DYLIB_SOURCES
${ASAN_SOURCES}
dynamic/asan_interceptors_dynamic.cc
)
include_directories(..)
set(ASAN_CFLAGS
@ -33,6 +38,12 @@ set(ASAN_CFLAGS
-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 @@ set_property(TARGET ${ASAN_RUNTIME_LIBRARIES} APPEND PROPERTY
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()

View File

@ -206,6 +206,9 @@ static inline int CharCaseCmp(unsigned char c1, unsigned char c2) {
}
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(void*, memset, void *block, int c, uptr size) {
}
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(char*, strncat, char *to, const char *from, uptr size) {
}
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(int, strcmp, const char *s1, const char *s2) {
}
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 @@ INTERCEPTOR(char*, strcpy, char *to, const char *from) { // NOLINT
#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 @@ INTERCEPTOR(char*, strdup, const char *s) {
#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 @@ INTERCEPTOR(int, strncasecmp, const char *s1, const char *s2, uptr n) {
#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(long, strtol, const char *nptr, // NOLINT
}
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(int, atoi, const char *nptr) {
}
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 @@ void InitializeAsanInterceptors() {
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 @@ void InitializeAsanInterceptors() {
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.

View File

@ -95,10 +95,14 @@ namespace __asan {
// 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 {

View File

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

View File

@ -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
#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); \
}
# 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)