forked from OSchip/llvm-project
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:
parent
c4540bc6a3
commit
c62210e3ff
|
@ -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()
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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__
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue