[llvm-commits] [compiler-rt] r162091 - in /compiler-rt/trunk/lib: asan/CMakeLists.txt asan/asan_interceptors.cc asan/asan_malloc_mac.cc asan/dynamic/ asan/dynamic/asan_interceptors_dynamic.cc interception/interception.h
Alexander Potapenko
glider at google.com
Fri Aug 17 02:00:08 PDT 2012
Author: glider
Date: Fri Aug 17 04:00:08 2012
New Revision: 162091
URL: http://llvm.org/viewvc/llvm-project?rev=162091&view=rev
Log:
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.
Added:
compiler-rt/trunk/lib/asan/dynamic/
compiler-rt/trunk/lib/asan/dynamic/asan_interceptors_dynamic.cc
Modified:
compiler-rt/trunk/lib/asan/CMakeLists.txt
compiler-rt/trunk/lib/asan/asan_interceptors.cc
compiler-rt/trunk/lib/asan/asan_malloc_mac.cc
compiler-rt/trunk/lib/interception/interception.h
Modified: compiler-rt/trunk/lib/asan/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/CMakeLists.txt?rev=162091&r1=162090&r2=162091&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/asan/CMakeLists.txt Fri Aug 17 04:00:08 2012
@@ -22,6 +22,11 @@
asan_win.cc
)
+set(ASAN_DYLIB_SOURCES
+ ${ASAN_SOURCES}
+ dynamic/asan_interceptors_dynamic.cc
+ )
+
include_directories(..)
set(ASAN_CFLAGS
@@ -33,6 +38,12 @@
-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 @@
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()
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=162091&r1=162090&r2=162091&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_interceptors.cc Fri Aug 17 04:00:08 2012
@@ -206,6 +206,9 @@
}
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(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(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(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 @@
#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 @@
#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 @@
#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(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(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 @@
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 @@
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.
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=162091&r1=162090&r2=162091&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_malloc_mac.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_malloc_mac.cc Fri Aug 17 04:00:08 2012
@@ -95,10 +95,14 @@
// 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 {
Added: compiler-rt/trunk/lib/asan/dynamic/asan_interceptors_dynamic.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/dynamic/asan_interceptors_dynamic.cc?rev=162091&view=auto
==============================================================================
--- compiler-rt/trunk/lib/asan/dynamic/asan_interceptors_dynamic.cc (added)
+++ compiler-rt/trunk/lib/asan/dynamic/asan_interceptors_dynamic.cc Fri Aug 17 04:00:08 2012
@@ -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__
Modified: compiler-rt/trunk/lib/interception/interception.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/interception/interception.h?rev=162091&r1=162090&r2=162091&view=diff
==============================================================================
--- compiler-rt/trunk/lib/interception/interception.h (original)
+++ compiler-rt/trunk/lib/interception/interception.h Fri Aug 17 04:00:08 2012
@@ -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
-
-#define DECLARE_REAL(ret_type, func, ...) \
- typedef ret_type (*FUNC_TYPE(func))(__VA_ARGS__); \
- namespace __interception { \
- extern FUNC_TYPE(func) PTR_TO_REAL(func); \
- }
+#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); \
+ }
+#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)
More information about the llvm-commits
mailing list