diff options
author | Kostya Serebryany <kcc@google.com> | 2012-12-04 07:00:35 +0000 |
---|---|---|
committer | Kostya Serebryany <kcc@gcc.gnu.org> | 2012-12-04 07:00:35 +0000 |
commit | 8c4d267c6e834ccc20632d2c9077d7622b8145cf (patch) | |
tree | ffc5f7302fa16d7a7c53d7de59d3edaae370fbd3 /libsanitizer | |
parent | 3fa057a43770dbb23a0fb21a94cab1789df3277c (diff) | |
download | gcc-8c4d267c6e834ccc20632d2c9077d7622b8145cf.tar.gz |
[libsanitizer] Fix PR55521 by switching libsanitizer from mach_override to mac interpose functions on darwin
From-SVN: r194120
Diffstat (limited to 'libsanitizer')
-rw-r--r-- | libsanitizer/ChangeLog | 26 | ||||
-rw-r--r-- | libsanitizer/Makefile.am | 4 | ||||
-rw-r--r-- | libsanitizer/Makefile.in | 1 | ||||
-rw-r--r-- | libsanitizer/asan/Makefile.am | 11 | ||||
-rw-r--r-- | libsanitizer/asan/Makefile.in | 42 | ||||
-rw-r--r-- | libsanitizer/asan/asan_intercepted_functions.h | 2 | ||||
-rw-r--r-- | libsanitizer/asan/asan_mac.cc | 2 | ||||
-rw-r--r-- | libsanitizer/asan/dynamic/asan_interceptors_dynamic.cc | 111 | ||||
-rwxr-xr-x | libsanitizer/configure | 22 | ||||
-rw-r--r-- | libsanitizer/configure.ac | 6 | ||||
-rw-r--r-- | libsanitizer/interception/Makefile.am | 4 | ||||
-rw-r--r-- | libsanitizer/interception/Makefile.in | 53 | ||||
-rw-r--r-- | libsanitizer/interception/mach_override/LICENSE.txt | 3 | ||||
-rw-r--r-- | libsanitizer/interception/mach_override/mach_override.c | 970 | ||||
-rw-r--r-- | libsanitizer/interception/mach_override/mach_override.h | 140 | ||||
-rwxr-xr-x | libsanitizer/merge.sh | 1 |
16 files changed, 206 insertions, 1192 deletions
diff --git a/libsanitizer/ChangeLog b/libsanitizer/ChangeLog index f98d8756cbe..d1f8c815ddd 100644 --- a/libsanitizer/ChangeLog +++ b/libsanitizer/ChangeLog @@ -1,3 +1,29 @@ +2012-12-04 Kostya Serebryany kcc@google.com + Jack Howarth <howarth@bromo.med.uc.edu> + + PR 55521/sanitizer + * configure.ac: Define USING_MAC_INTERPOSE when on darwin. + * Makefile.am: Don't build interception subdir when + USING_MAC_INTERPOSE defined. + * asan/Makefile.am: Pass -DMAC_INTERPOSE_FUNCTIONS and + -DMISSING_BLOCKS_SUPPORT when USING_MAC_INTERPOSE defined. + Compile asan_interceptors_dynamic.cc but not libinterception + when USING_MAC_INTERPOSE defined. + * interception/Makefile.am: Remove usage of USING_MACH_OVERRIDE. + * configure: Regenerated. + * Makefile.in: Likewise. + * asan/Makefile.in: Likewise. + * interception/Makefile.in: Likewise. + * asan/asan_intercepted_functions.h: Use MISSING_BLOCKS_SUPPORT. + * asan/asan_mac.cc: Likewise. + * asan/dynamic/asan_interceptors_dynamic.cc: Migrate from llvm + and use MISSING_BLOCKS_SUPPORT. + * merge.sh: Merge lib/asan/dynamic into asan/dynamic. + * interception/mach_override/LICENSE.txt: Remove unused file. + * interception/mach_override/mach_override.c: Likewise. + * interception/mach_override/mach_override.h: Likewise. + * interception/mach_override: Remove unused directory. + 2012-11-28 H.J. Lu <hongjiu.lu@intel.com> * Makefile.am (AM_MAKEFLAGS): Restore CC and CXX. diff --git a/libsanitizer/Makefile.am b/libsanitizer/Makefile.am index 64d3d2eab9a..9a068392017 100644 --- a/libsanitizer/Makefile.am +++ b/libsanitizer/Makefile.am @@ -6,6 +6,10 @@ else SUBDIRS = interception sanitizer_common asan endif +if USING_MAC_INTERPOSE +SUBDIRS = sanitizer_common asan +endif + # Work around what appears to be a GNU make bug handling MAKEFLAGS # values defined in terms of make variables, as is the case for CC and # friends when we are called from the top level Makefile. diff --git a/libsanitizer/Makefile.in b/libsanitizer/Makefile.in index 21c27113c38..4606490762a 100644 --- a/libsanitizer/Makefile.in +++ b/libsanitizer/Makefile.in @@ -246,6 +246,7 @@ top_srcdir = @top_srcdir@ ACLOCAL_AMFLAGS = -I .. -I ../config @TSAN_SUPPORTED_FALSE@SUBDIRS = interception sanitizer_common asan @TSAN_SUPPORTED_TRUE@SUBDIRS = interception sanitizer_common asan tsan +@USING_MAC_INTERPOSE_TRUE@SUBDIRS = sanitizer_common asan # Work around what appears to be a GNU make bug handling MAKEFLAGS # values defined in terms of make variables, as is the case for CC and diff --git a/libsanitizer/asan/Makefile.am b/libsanitizer/asan/Makefile.am index 3da1db38847..7656f9f2140 100644 --- a/libsanitizer/asan/Makefile.am +++ b/libsanitizer/asan/Makefile.am @@ -4,6 +4,9 @@ AM_CPPFLAGS = -I $(top_srcdir)/include -I $(top_srcdir) gcc_version := $(shell cat $(top_srcdir)/../gcc/BASE-VER) DEFS = -D_GNU_SOURCE -D_DEBUG -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -DASAN_HAS_EXCEPTIONS=1 -DASAN_FLEXIBLE_MAPPING_AND_OFFSET=0 -DASAN_NEEDS_SEGV=1 +if USING_MAC_INTERPOSE +DEFS += -DMAC_INTERPOSE_FUNCTIONS -DMISSING_BLOCKS_SUPPORT +endif AM_CXXFLAGS = -Wall -W -Wno-unused-parameter -Wwrite-strings -pedantic -Wno-long-long -fPIC -fno-builtin -fno-exceptions -fomit-frame-pointer -funwind-tables -fvisibility=hidden -Wno-variadic-macros -Wno-c99-extensions ACLOCAL_AMFLAGS = -I $(top_srcdir) -I $(top_srcdir)/config @@ -29,8 +32,14 @@ asan_files = \ asan_thread.cc \ asan_win.cc -libasan_la_SOURCES = $(asan_files) +libasan_la_SOURCES = $(asan_files) +if USING_MAC_INTERPOSE +libasan_la_SOURCES += dynamic/asan_interceptors_dynamic.cc +libasan_la_LIBADD = $(top_builddir)/sanitizer_common/libsanitizer_common.la $(top_builddir)/../libstdc++-v3/src/libstdc++.la +else libasan_la_LIBADD = $(top_builddir)/sanitizer_common/libsanitizer_common.la $(top_builddir)/interception/libinterception.la $(top_builddir)/../libstdc++-v3/src/libstdc++.la +endif + libasan_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version` -lpthread -ldl # Work around what appears to be a GNU make bug handling MAKEFLAGS diff --git a/libsanitizer/asan/Makefile.in b/libsanitizer/asan/Makefile.in index e5e8d407c57..4bd7179c9cf 100644 --- a/libsanitizer/asan/Makefile.in +++ b/libsanitizer/asan/Makefile.in @@ -35,6 +35,8 @@ POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ target_triplet = @target@ +@USING_MAC_INTERPOSE_TRUE@am__append_1 = -DMAC_INTERPOSE_FUNCTIONS -DMISSING_BLOCKS_SUPPORT +@USING_MAC_INTERPOSE_TRUE@am__append_2 = dynamic/asan_interceptors_dynamic.cc subdir = asan DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -74,17 +76,27 @@ am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__installdirs = "$(DESTDIR)$(toolexeclibdir)" LTLIBRARIES = $(toolexeclib_LTLIBRARIES) -libasan_la_DEPENDENCIES = \ - $(top_builddir)/sanitizer_common/libsanitizer_common.la \ - $(top_builddir)/interception/libinterception.la \ - $(top_builddir)/../libstdc++-v3/src/libstdc++.la +@USING_MAC_INTERPOSE_FALSE@libasan_la_DEPENDENCIES = $(top_builddir)/sanitizer_common/libsanitizer_common.la \ +@USING_MAC_INTERPOSE_FALSE@ $(top_builddir)/interception/libinterception.la \ +@USING_MAC_INTERPOSE_FALSE@ $(top_builddir)/../libstdc++-v3/src/libstdc++.la +@USING_MAC_INTERPOSE_TRUE@libasan_la_DEPENDENCIES = $(top_builddir)/sanitizer_common/libsanitizer_common.la \ +@USING_MAC_INTERPOSE_TRUE@ $(top_builddir)/../libstdc++-v3/src/libstdc++.la +am__libasan_la_SOURCES_DIST = asan_allocator.cc asan_interceptors.cc \ + asan_mac.cc asan_malloc_mac.cc asan_new_delete.cc \ + asan_posix.cc asan_rtl.cc asan_stats.cc \ + asan_thread_registry.cc asan_globals.cc asan_linux.cc \ + asan_malloc_linux.cc asan_malloc_win.cc asan_poisoning.cc \ + asan_report.cc asan_stack.cc asan_thread.cc asan_win.cc \ + dynamic/asan_interceptors_dynamic.cc am__objects_1 = asan_allocator.lo asan_interceptors.lo asan_mac.lo \ asan_malloc_mac.lo asan_new_delete.lo asan_posix.lo \ asan_rtl.lo asan_stats.lo asan_thread_registry.lo \ asan_globals.lo asan_linux.lo asan_malloc_linux.lo \ asan_malloc_win.lo asan_poisoning.lo asan_report.lo \ asan_stack.lo asan_thread.lo asan_win.lo -am_libasan_la_OBJECTS = $(am__objects_1) +@USING_MAC_INTERPOSE_TRUE@am__objects_2 = \ +@USING_MAC_INTERPOSE_TRUE@ asan_interceptors_dynamic.lo +am_libasan_la_OBJECTS = $(am__objects_1) $(am__objects_2) libasan_la_OBJECTS = $(am_libasan_la_OBJECTS) libasan_la_LINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXXLD) $(AM_CXXFLAGS) \ @@ -103,7 +115,7 @@ CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(libasan_la_SOURCES) -DIST_SOURCES = $(libasan_la_SOURCES) +DIST_SOURCES = $(am__libasan_la_SOURCES_DIST) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) @@ -127,7 +139,10 @@ CXXCPP = @CXXCPP@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ -DEFS = -D_GNU_SOURCE -D_DEBUG -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -DASAN_HAS_EXCEPTIONS=1 -DASAN_FLEXIBLE_MAPPING_AND_OFFSET=0 -DASAN_NEEDS_SEGV=1 +DEFS = -D_GNU_SOURCE -D_DEBUG -D__STDC_CONSTANT_MACROS \ + -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS \ + -DASAN_HAS_EXCEPTIONS=1 -DASAN_FLEXIBLE_MAPPING_AND_OFFSET=0 \ + -DASAN_NEEDS_SEGV=1 $(am__append_1) DEPDIR = @DEPDIR@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ @@ -262,8 +277,9 @@ asan_files = \ asan_thread.cc \ asan_win.cc -libasan_la_SOURCES = $(asan_files) -libasan_la_LIBADD = $(top_builddir)/sanitizer_common/libsanitizer_common.la $(top_builddir)/interception/libinterception.la $(top_builddir)/../libstdc++-v3/src/libstdc++.la +libasan_la_SOURCES = $(asan_files) $(am__append_2) +@USING_MAC_INTERPOSE_FALSE@libasan_la_LIBADD = $(top_builddir)/sanitizer_common/libsanitizer_common.la $(top_builddir)/interception/libinterception.la $(top_builddir)/../libstdc++-v3/src/libstdc++.la +@USING_MAC_INTERPOSE_TRUE@libasan_la_LIBADD = $(top_builddir)/sanitizer_common/libsanitizer_common.la $(top_builddir)/../libstdc++-v3/src/libstdc++.la libasan_la_LDFLAGS = -version-info `grep -v '^\#' $(srcdir)/libtool-version` -lpthread -ldl # Work around what appears to be a GNU make bug handling MAKEFLAGS @@ -384,6 +400,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_allocator.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_globals.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_interceptors.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_interceptors_dynamic.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_linux.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_mac.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/asan_malloc_linux.Plo@am__quote@ @@ -421,6 +438,13 @@ distclean-compile: @AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCXX_FALSE@ $(LTCXXCOMPILE) -c -o $@ $< +asan_interceptors_dynamic.lo: dynamic/asan_interceptors_dynamic.cc +@am__fastdepCXX_TRUE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -MT asan_interceptors_dynamic.lo -MD -MP -MF $(DEPDIR)/asan_interceptors_dynamic.Tpo -c -o asan_interceptors_dynamic.lo `test -f 'dynamic/asan_interceptors_dynamic.cc' || echo '$(srcdir)/'`dynamic/asan_interceptors_dynamic.cc +@am__fastdepCXX_TRUE@ $(am__mv) $(DEPDIR)/asan_interceptors_dynamic.Tpo $(DEPDIR)/asan_interceptors_dynamic.Plo +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ source='dynamic/asan_interceptors_dynamic.cc' object='asan_interceptors_dynamic.lo' libtool=yes @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCXX_FALSE@ DEPDIR=$(DEPDIR) $(CXXDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCXX_FALSE@ $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) -c -o asan_interceptors_dynamic.lo `test -f 'dynamic/asan_interceptors_dynamic.cc' || echo '$(srcdir)/'`dynamic/asan_interceptors_dynamic.cc + mostlyclean-libtool: -rm -f *.lo diff --git a/libsanitizer/asan/asan_intercepted_functions.h b/libsanitizer/asan/asan_intercepted_functions.h index 62d1994130f..89f91ad6a31 100644 --- a/libsanitizer/asan/asan_intercepted_functions.h +++ b/libsanitizer/asan/asan_intercepted_functions.h @@ -203,7 +203,7 @@ DECLARE_FUNCTION_AND_WRAPPER(void, __CFInitialize, void); DECLARE_FUNCTION_AND_WRAPPER(CFStringRef, CFStringCreateCopy, CFAllocatorRef alloc, CFStringRef str); DECLARE_FUNCTION_AND_WRAPPER(void, free, void* ptr); -#if MAC_INTERPOSE_FUNCTIONS +#if MAC_INTERPOSE_FUNCTIONS && !defined(MISSING_BLOCKS_SUPPORT) DECLARE_FUNCTION_AND_WRAPPER(void, dispatch_group_async, dispatch_group_t dg, dispatch_queue_t dq, void (^work)(void)); diff --git a/libsanitizer/asan/asan_mac.cc b/libsanitizer/asan/asan_mac.cc index 5caf76ba1ff..db0b6d30a8b 100644 --- a/libsanitizer/asan/asan_mac.cc +++ b/libsanitizer/asan/asan_mac.cc @@ -383,7 +383,7 @@ INTERCEPTOR(void, dispatch_group_async_f, dispatch_group_t group, asan_dispatch_call_block_and_release); } -#if MAC_INTERPOSE_FUNCTIONS +#if MAC_INTERPOSE_FUNCTIONS && !defined(MISSING_BLOCKS_SUPPORT) // dispatch_async, dispatch_group_async and others tailcall the corresponding // dispatch_*_f functions. When wrapping functions with mach_override, those // dispatch_*_f are intercepted automatically. But with dylib interposition diff --git a/libsanitizer/asan/dynamic/asan_interceptors_dynamic.cc b/libsanitizer/asan/dynamic/asan_interceptors_dynamic.cc new file mode 100644 index 00000000000..4f0f7bd2d5f --- /dev/null +++ b/libsanitizer/asan/dynamic/asan_interceptors_dynamic.cc @@ -0,0 +1,111 @@ +//===-- 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 { + +#if !MAC_INTERPOSE_FUNCTIONS +# error \ + Dynamic interposing library should be built with -DMAC_INTERPOSE_FUNCTIONS +#endif + +#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), +#if ASAN_INTERCEPT__LONGJMP + INTERPOSE_FUNCTION(_longjmp), +#endif +#if ASAN_INTERCEPT_SIGLONGJMP + INTERPOSE_FUNCTION(siglongjmp), +#endif +#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), +#ifndef MISSING_BLOCKS_SUPPORT + INTERPOSE_FUNCTION(dispatch_group_async), + INTERPOSE_FUNCTION(dispatch_async), + INTERPOSE_FUNCTION(dispatch_after), + INTERPOSE_FUNCTION(dispatch_source_set_event_handler), + INTERPOSE_FUNCTION(dispatch_source_set_cancel_handler), +#endif + INTERPOSE_FUNCTION(signal), + INTERPOSE_FUNCTION(sigaction), + + INTERPOSE_FUNCTION(__CFInitialize), + INTERPOSE_FUNCTION(CFStringCreateCopy), + INTERPOSE_FUNCTION(free), +}; + +} // namespace __asan + +#endif // __APPLE__ diff --git a/libsanitizer/configure b/libsanitizer/configure index 48f984c7bbb..1d64feff57b 100755 --- a/libsanitizer/configure +++ b/libsanitizer/configure @@ -604,8 +604,8 @@ ac_subst_vars='am__EXEEXT_FALSE am__EXEEXT_TRUE LTLIBOBJS LIBOBJS -USING_MACH_OVERRIDE_FALSE -USING_MACH_OVERRIDE_TRUE +USING_MAC_INTERPOSE_FALSE +USING_MAC_INTERPOSE_TRUE TSAN_SUPPORTED_FALSE TSAN_SUPPORTED_TRUE enable_static @@ -14497,15 +14497,15 @@ fi case "$host" in - *-*-darwin*) MACH_OVERRIDE=true ;; - *) MACH_OVERRIDE=false ;; + *-*-darwin*) MAC_INTERPOSE=true ;; + *) MAC_INTERPOSE=false ;; esac - if $MACH_OVERRIDE; then - USING_MACH_OVERRIDE_TRUE= - USING_MACH_OVERRIDE_FALSE='#' + if $MAC_INTERPOSE; then + USING_MAC_INTERPOSE_TRUE= + USING_MAC_INTERPOSE_FALSE='#' else - USING_MACH_OVERRIDE_TRUE='#' - USING_MACH_OVERRIDE_FALSE= + USING_MAC_INTERPOSE_TRUE='#' + USING_MAC_INTERPOSE_FALSE= fi @@ -14685,8 +14685,8 @@ if test -z "${TSAN_SUPPORTED_TRUE}" && test -z "${TSAN_SUPPORTED_FALSE}"; then as_fn_error "conditional \"TSAN_SUPPORTED\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi -if test -z "${USING_MACH_OVERRIDE_TRUE}" && test -z "${USING_MACH_OVERRIDE_FALSE}"; then - as_fn_error "conditional \"USING_MACH_OVERRIDE\" was never defined. +if test -z "${USING_MAC_INTERPOSE_TRUE}" && test -z "${USING_MAC_INTERPOSE_FALSE}"; then + as_fn_error "conditional \"USING_MAC_INTERPOSE\" was never defined. Usually this means the macro was only invoked conditionally." "$LINENO" 5 fi diff --git a/libsanitizer/configure.ac b/libsanitizer/configure.ac index 2d62ec4ecc0..49f9cd730c3 100644 --- a/libsanitizer/configure.ac +++ b/libsanitizer/configure.ac @@ -81,10 +81,10 @@ unset TSAN_SUPPORTED AM_CONDITIONAL(TSAN_SUPPORTED, [test "x$TSAN_SUPPORTED" = "xyes"]) case "$host" in - *-*-darwin*) MACH_OVERRIDE=true ;; - *) MACH_OVERRIDE=false ;; + *-*-darwin*) MAC_INTERPOSE=true ;; + *) MAC_INTERPOSE=false ;; esac -AM_CONDITIONAL(USING_MACH_OVERRIDE, $MACH_OVERRIDE) +AM_CONDITIONAL(USING_MAC_INTERPOSE, $MAC_INTERPOSE) AC_CONFIG_FILES([Makefile]) diff --git a/libsanitizer/interception/Makefile.am b/libsanitizer/interception/Makefile.am index 029417f46e5..a815dcf67bd 100644 --- a/libsanitizer/interception/Makefile.am +++ b/libsanitizer/interception/Makefile.am @@ -14,11 +14,7 @@ interception_files = \ interception_mac.cc \ interception_win.cc -if USING_MACH_OVERRIDE -libinterception_la_SOURCES = $(interception_files) mach_override/mach_override.c -else libinterception_la_SOURCES = $(interception_files) -endif # Work around what appears to be a GNU make bug handling MAKEFLAGS # values defined in terms of make variables, as is the case for CC and diff --git a/libsanitizer/interception/Makefile.in b/libsanitizer/interception/Makefile.in index bd58c4d47a0..f86b41f5c4c 100644 --- a/libsanitizer/interception/Makefile.in +++ b/libsanitizer/interception/Makefile.in @@ -53,29 +53,14 @@ CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = LTLIBRARIES = $(noinst_LTLIBRARIES) libinterception_la_LIBADD = -am__libinterception_la_SOURCES_DIST = interception_linux.cc \ - interception_mac.cc interception_win.cc \ - mach_override/mach_override.c am__objects_1 = interception_linux.lo interception_mac.lo \ interception_win.lo -@USING_MACH_OVERRIDE_FALSE@am_libinterception_la_OBJECTS = \ -@USING_MACH_OVERRIDE_FALSE@ $(am__objects_1) -@USING_MACH_OVERRIDE_TRUE@am_libinterception_la_OBJECTS = \ -@USING_MACH_OVERRIDE_TRUE@ $(am__objects_1) mach_override.lo +am_libinterception_la_OBJECTS = $(am__objects_1) libinterception_la_OBJECTS = $(am_libinterception_la_OBJECTS) DEFAULT_INCLUDES = -I.@am__isrc@ depcomp = $(SHELL) $(top_srcdir)/../depcomp am__depfiles_maybe = depfiles am__mv = mv -f -COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ - $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -LTCOMPILE = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ - --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ - $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -CCLD = $(CC) -LINK = $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ - --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) \ - $(LDFLAGS) -o $@ CXXCOMPILE = $(CXX) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) \ $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CXXFLAGS) $(CXXFLAGS) LTCXXCOMPILE = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ @@ -86,7 +71,7 @@ CXXLINK = $(LIBTOOL) --tag=CXX $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) \ --mode=link $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) \ $(LDFLAGS) -o $@ SOURCES = $(libinterception_la_SOURCES) -DIST_SOURCES = $(am__libinterception_la_SOURCES_DIST) +DIST_SOURCES = $(libinterception_la_SOURCES) ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) @@ -230,8 +215,7 @@ interception_files = \ interception_mac.cc \ interception_win.cc -@USING_MACH_OVERRIDE_FALSE@libinterception_la_SOURCES = $(interception_files) -@USING_MACH_OVERRIDE_TRUE@libinterception_la_SOURCES = $(interception_files) mach_override/mach_override.c +libinterception_la_SOURCES = $(interception_files) # Work around what appears to be a GNU make bug handling MAKEFLAGS # values defined in terms of make variables, as is the case for CC and @@ -277,7 +261,7 @@ MAKEOVERRIDES = all: all-am .SUFFIXES: -.SUFFIXES: .c .cc .lo .o .obj +.SUFFIXES: .cc .lo .o .obj $(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ @@ -329,35 +313,6 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/interception_linux.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/interception_mac.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/interception_win.Plo@am__quote@ -@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mach_override.Plo@am__quote@ - -.c.o: -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(COMPILE) -c $< - -.c.obj: -@am__fastdepCC_TRUE@ $(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'` - -.c.lo: -@am__fastdepCC_TRUE@ $(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $< - -mach_override.lo: mach_override/mach_override.c -@am__fastdepCC_TRUE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT mach_override.lo -MD -MP -MF $(DEPDIR)/mach_override.Tpo -c -o mach_override.lo `test -f 'mach_override/mach_override.c' || echo '$(srcdir)/'`mach_override/mach_override.c -@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/mach_override.Tpo $(DEPDIR)/mach_override.Plo -@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='mach_override/mach_override.c' object='mach_override.lo' libtool=yes @AMDEPBACKSLASH@ -@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ -@am__fastdepCC_FALSE@ $(LIBTOOL) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o mach_override.lo `test -f 'mach_override/mach_override.c' || echo '$(srcdir)/'`mach_override/mach_override.c .cc.o: @am__fastdepCXX_TRUE@ $(CXXCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< diff --git a/libsanitizer/interception/mach_override/LICENSE.txt b/libsanitizer/interception/mach_override/LICENSE.txt deleted file mode 100644 index 9446965176c..00000000000 --- a/libsanitizer/interception/mach_override/LICENSE.txt +++ /dev/null @@ -1,3 +0,0 @@ -Copyright (c) 2003-2009 Jonathan 'Wolf' Rentzsch: <http://rentzsch.com> -Some rights reserved: <http://opensource.org/licenses/mit-license.php> - diff --git a/libsanitizer/interception/mach_override/mach_override.c b/libsanitizer/interception/mach_override/mach_override.c deleted file mode 100644 index 7511a7bebb8..00000000000 --- a/libsanitizer/interception/mach_override/mach_override.c +++ /dev/null @@ -1,970 +0,0 @@ -/******************************************************************************* - mach_override.c - Copyright (c) 2003-2009 Jonathan 'Wolf' Rentzsch: <http://rentzsch.com> - Some rights reserved: <http://opensource.org/licenses/mit-license.php> - - ***************************************************************************/ -#ifdef __APPLE__ - -#include "mach_override.h" - -#include <mach-o/dyld.h> -#include <mach/mach_host.h> -#include <mach/mach_init.h> -#include <mach/vm_map.h> -#include <sys/mman.h> - -#include <CoreServices/CoreServices.h> - -//#define DEBUG_DISASM 1 -#undef DEBUG_DISASM - -/************************** -* -* Constants -* -**************************/ -#pragma mark - -#pragma mark (Constants) - -#if defined(__ppc__) || defined(__POWERPC__) - -static -long kIslandTemplate[] = { - 0x9001FFFC, // stw r0,-4(SP) - 0x3C00DEAD, // lis r0,0xDEAD - 0x6000BEEF, // ori r0,r0,0xBEEF - 0x7C0903A6, // mtctr r0 - 0x8001FFFC, // lwz r0,-4(SP) - 0x60000000, // nop ; optionally replaced - 0x4E800420 // bctr -}; - -#define kAddressHi 3 -#define kAddressLo 5 -#define kInstructionHi 10 -#define kInstructionLo 11 - -#elif defined(__i386__) - -#define kOriginalInstructionsSize 16 - -static -unsigned char kIslandTemplate[] = { - // kOriginalInstructionsSize nop instructions so that we - // should have enough space to host original instructions - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - // Now the real jump instruction - 0xE9, 0xEF, 0xBE, 0xAD, 0xDE -}; - -#define kInstructions 0 -#define kJumpAddress kInstructions + kOriginalInstructionsSize + 1 -#elif defined(__x86_64__) - -#define kOriginalInstructionsSize 32 - -#define kJumpAddress kOriginalInstructionsSize + 6 - -static -unsigned char kIslandTemplate[] = { - // kOriginalInstructionsSize nop instructions so that we - // should have enough space to host original instructions - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, - // Now the real jump instruction - 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00 -}; - -#endif - -#define kAllocateHigh 1 -#define kAllocateNormal 0 - -/************************** -* -* Data Types -* -**************************/ -#pragma mark - -#pragma mark (Data Types) - -typedef struct { - char instructions[sizeof(kIslandTemplate)]; - int allocatedHigh; -} BranchIsland; - -/************************** -* -* Funky Protos -* -**************************/ -#pragma mark - -#pragma mark (Funky Protos) - - - static mach_error_t -allocateBranchIsland( - BranchIsland **island, - int allocateHigh, - void *originalFunctionAddress); - - static mach_error_t -freeBranchIsland( - BranchIsland *island ); - - static mach_error_t -defaultIslandMalloc( - void **ptr, size_t unused_size, void *hint); - - static mach_error_t -defaultIslandFree( - void *ptr); - -#if defined(__ppc__) || defined(__POWERPC__) - static mach_error_t -setBranchIslandTarget( - BranchIsland *island, - const void *branchTo, - long instruction ); -#endif - -#if defined(__i386__) || defined(__x86_64__) -static mach_error_t -setBranchIslandTarget_i386( - BranchIsland *island, - const void *branchTo, - char* instructions ); -// Can't be made static because there's no C implementation for atomic_mov64 -// on i386. -void -atomic_mov64( - uint64_t *targetAddress, - uint64_t value ) __attribute__((visibility("hidden"))); - - static Boolean -eatKnownInstructions( - unsigned char *code, - uint64_t *newInstruction, - int *howManyEaten, - char *originalInstructions, - int *originalInstructionCount, - uint8_t *originalInstructionSizes ); - - static void -fixupInstructions( - void *originalFunction, - void *escapeIsland, - void *instructionsToFix, - int instructionCount, - uint8_t *instructionSizes ); - -#ifdef DEBUG_DISASM - static void -dump16Bytes( - void *ptr); -#endif // DEBUG_DISASM -#endif - -/******************************************************************************* -* -* Interface -* -*******************************************************************************/ -#pragma mark - -#pragma mark (Interface) - -#if defined(__i386__) || defined(__x86_64__) -static mach_error_t makeIslandExecutable(void *address) { - mach_error_t err = err_none; - vm_size_t pageSize; - host_page_size( mach_host_self(), &pageSize ); - uintptr_t page = (uintptr_t)address & ~(uintptr_t)(pageSize-1); - int e = err_none; - e |= mprotect((void *)page, pageSize, PROT_EXEC | PROT_READ | PROT_WRITE); - e |= msync((void *)page, pageSize, MS_INVALIDATE ); - if (e) { - err = err_cannot_override; - } - return err; -} -#endif - - static mach_error_t -defaultIslandMalloc( - void **ptr, size_t unused_size, void *hint) { - return allocateBranchIsland( (BranchIsland**)ptr, kAllocateHigh, hint ); -} - static mach_error_t -defaultIslandFree( - void *ptr) { - return freeBranchIsland(ptr); -} - - mach_error_t -__asan_mach_override_ptr( - void *originalFunctionAddress, - const void *overrideFunctionAddress, - void **originalFunctionReentryIsland ) -{ - return __asan_mach_override_ptr_custom(originalFunctionAddress, - overrideFunctionAddress, - originalFunctionReentryIsland, - defaultIslandMalloc, - defaultIslandFree); -} - - mach_error_t -__asan_mach_override_ptr_custom( - void *originalFunctionAddress, - const void *overrideFunctionAddress, - void **originalFunctionReentryIsland, - island_malloc *alloc, - island_free *dealloc) -{ - assert( originalFunctionAddress ); - assert( overrideFunctionAddress ); - - // this addresses overriding such functions as AudioOutputUnitStart() - // test with modified DefaultOutputUnit project -#if defined(__x86_64__) - for(;;){ - if(*(uint16_t*)originalFunctionAddress==0x25FF) // jmp qword near [rip+0x????????] - originalFunctionAddress=*(void**)((char*)originalFunctionAddress+6+*(int32_t *)((uint16_t*)originalFunctionAddress+1)); - else break; - } -#elif defined(__i386__) - for(;;){ - if(*(uint16_t*)originalFunctionAddress==0x25FF) // jmp *0x???????? - originalFunctionAddress=**(void***)((uint16_t*)originalFunctionAddress+1); - else break; - } -#endif -#ifdef DEBUG_DISASM - { - fprintf(stderr, "Replacing function at %p\n", originalFunctionAddress); - fprintf(stderr, "First 16 bytes of the function: "); - unsigned char *orig = (unsigned char *)originalFunctionAddress; - int i; - for (i = 0; i < 16; i++) { - fprintf(stderr, "%x ", (unsigned int) orig[i]); - } - fprintf(stderr, "\n"); - fprintf(stderr, - "To disassemble, save the following function as disas.c" - " and run:\n gcc -c disas.c && gobjdump -d disas.o\n" - "The first 16 bytes of the original function will start" - " after four nop instructions.\n"); - fprintf(stderr, "\nvoid foo() {\n asm volatile(\"nop;nop;nop;nop;\");\n"); - int j = 0; - for (j = 0; j < 2; j++) { - fprintf(stderr, " asm volatile(\".byte "); - for (i = 8 * j; i < 8 * (j+1) - 1; i++) { - fprintf(stderr, "0x%x, ", (unsigned int) orig[i]); - } - fprintf(stderr, "0x%x;\");\n", (unsigned int) orig[8 * (j+1) - 1]); - } - fprintf(stderr, "}\n\n"); - } -#endif - - long *originalFunctionPtr = (long*) originalFunctionAddress; - mach_error_t err = err_none; - -#if defined(__ppc__) || defined(__POWERPC__) - // Ensure first instruction isn't 'mfctr'. - #define kMFCTRMask 0xfc1fffff - #define kMFCTRInstruction 0x7c0903a6 - - long originalInstruction = *originalFunctionPtr; - if( !err && ((originalInstruction & kMFCTRMask) == kMFCTRInstruction) ) - err = err_cannot_override; -#elif defined(__i386__) || defined(__x86_64__) - int eatenCount = 0; - int originalInstructionCount = 0; - char originalInstructions[kOriginalInstructionsSize]; - uint8_t originalInstructionSizes[kOriginalInstructionsSize]; - uint64_t jumpRelativeInstruction = 0; // JMP - - Boolean overridePossible = eatKnownInstructions ((unsigned char *)originalFunctionPtr, - &jumpRelativeInstruction, &eatenCount, - originalInstructions, &originalInstructionCount, - originalInstructionSizes ); -#ifdef DEBUG_DISASM - if (!overridePossible) fprintf(stderr, "overridePossible = false @%d\n", __LINE__); -#endif - if (eatenCount > kOriginalInstructionsSize) { -#ifdef DEBUG_DISASM - fprintf(stderr, "Too many instructions eaten\n"); -#endif - overridePossible = false; - } - if (!overridePossible) err = err_cannot_override; - if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LINE__); -#endif - - // Make the original function implementation writable. - if( !err ) { - err = vm_protect( mach_task_self(), - (vm_address_t) originalFunctionPtr, 8, false, - (VM_PROT_ALL | VM_PROT_COPY) ); - if( err ) - err = vm_protect( mach_task_self(), - (vm_address_t) originalFunctionPtr, 8, false, - (VM_PROT_DEFAULT | VM_PROT_COPY) ); - } - if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LINE__); - - // Allocate and target the escape island to the overriding function. - BranchIsland *escapeIsland = NULL; - if( !err ) - err = alloc( (void**)&escapeIsland, sizeof(BranchIsland), originalFunctionAddress ); - if ( err ) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LINE__); - -#if defined(__ppc__) || defined(__POWERPC__) - if( !err ) - err = setBranchIslandTarget( escapeIsland, overrideFunctionAddress, 0 ); - - // Build the branch absolute instruction to the escape island. - long branchAbsoluteInstruction = 0; // Set to 0 just to silence warning. - if( !err ) { - long escapeIslandAddress = ((long) escapeIsland) & 0x3FFFFFF; - branchAbsoluteInstruction = 0x48000002 | escapeIslandAddress; - } -#elif defined(__i386__) || defined(__x86_64__) - if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LINE__); - - if( !err ) - err = setBranchIslandTarget_i386( escapeIsland, overrideFunctionAddress, 0 ); - - if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LINE__); - // Build the jump relative instruction to the escape island -#endif - - -#if defined(__i386__) || defined(__x86_64__) - if (!err) { - uint32_t addressOffset = ((char*)escapeIsland - (char*)originalFunctionPtr - 5); - addressOffset = OSSwapInt32(addressOffset); - - jumpRelativeInstruction |= 0xE900000000000000LL; - jumpRelativeInstruction |= ((uint64_t)addressOffset & 0xffffffff) << 24; - jumpRelativeInstruction = OSSwapInt64(jumpRelativeInstruction); - } -#endif - - // Optionally allocate & return the reentry island. This may contain relocated - // jmp instructions and so has all the same addressing reachability requirements - // the escape island has to the original function, except the escape island is - // technically our original function. - BranchIsland *reentryIsland = NULL; - if( !err && originalFunctionReentryIsland ) { - err = alloc( (void**)&reentryIsland, sizeof(BranchIsland), escapeIsland); - if( !err ) - *originalFunctionReentryIsland = reentryIsland; - } - -#if defined(__ppc__) || defined(__POWERPC__) - // Atomically: - // o If the reentry island was allocated: - // o Insert the original instruction into the reentry island. - // o Target the reentry island at the 2nd instruction of the - // original function. - // o Replace the original instruction with the branch absolute. - if( !err ) { - int escapeIslandEngaged = false; - do { - if( reentryIsland ) - err = setBranchIslandTarget( reentryIsland, - (void*) (originalFunctionPtr+1), originalInstruction ); - if( !err ) { - escapeIslandEngaged = CompareAndSwap( originalInstruction, - branchAbsoluteInstruction, - (UInt32*)originalFunctionPtr ); - if( !escapeIslandEngaged ) { - // Someone replaced the instruction out from under us, - // re-read the instruction, make sure it's still not - // 'mfctr' and try again. - originalInstruction = *originalFunctionPtr; - if( (originalInstruction & kMFCTRMask) == kMFCTRInstruction) - err = err_cannot_override; - } - } - } while( !err && !escapeIslandEngaged ); - } -#elif defined(__i386__) || defined(__x86_64__) - // Atomically: - // o If the reentry island was allocated: - // o Insert the original instructions into the reentry island. - // o Target the reentry island at the first non-replaced - // instruction of the original function. - // o Replace the original first instructions with the jump relative. - // - // Note that on i386, we do not support someone else changing the code under our feet - if ( !err ) { - fixupInstructions(originalFunctionPtr, reentryIsland, originalInstructions, - originalInstructionCount, originalInstructionSizes ); - - if( reentryIsland ) - err = setBranchIslandTarget_i386( reentryIsland, - (void*) ((char *)originalFunctionPtr+eatenCount), originalInstructions ); - // try making islands executable before planting the jmp -#if defined(__x86_64__) || defined(__i386__) - if( !err ) - err = makeIslandExecutable(escapeIsland); - if( !err && reentryIsland ) - err = makeIslandExecutable(reentryIsland); -#endif - if ( !err ) - atomic_mov64((uint64_t *)originalFunctionPtr, jumpRelativeInstruction); - } -#endif - - // Clean up on error. - if( err ) { - if( reentryIsland ) - dealloc( reentryIsland ); - if( escapeIsland ) - dealloc( escapeIsland ); - } - -#ifdef DEBUG_DISASM - { - fprintf(stderr, "First 16 bytes of the function after slicing: "); - unsigned char *orig = (unsigned char *)originalFunctionAddress; - int i; - for (i = 0; i < 16; i++) { - fprintf(stderr, "%x ", (unsigned int) orig[i]); - } - fprintf(stderr, "\n"); - } -#endif - return err; -} - -/******************************************************************************* -* -* Implementation -* -*******************************************************************************/ -#pragma mark - -#pragma mark (Implementation) - -/***************************************************************************//** - Implementation: Allocates memory for a branch island. - - @param island <- The allocated island. - @param allocateHigh -> Whether to allocate the island at the end of the - address space (for use with the branch absolute - instruction). - @result <- mach_error_t - - ***************************************************************************/ - - static mach_error_t -allocateBranchIsland( - BranchIsland **island, - int allocateHigh, - void *originalFunctionAddress) -{ - assert( island ); - - mach_error_t err = err_none; - - if( allocateHigh ) { - vm_size_t pageSize; - err = host_page_size( mach_host_self(), &pageSize ); - if( !err ) { - assert( sizeof( BranchIsland ) <= pageSize ); -#if defined(__ppc__) || defined(__POWERPC__) - vm_address_t first = 0xfeffffff; - vm_address_t last = 0xfe000000 + pageSize; -#elif defined(__x86_64__) - vm_address_t first = ((uint64_t)originalFunctionAddress & ~(uint64_t)(((uint64_t)1 << 31) - 1)) | ((uint64_t)1 << 31); // start in the middle of the page? - vm_address_t last = 0x0; -#else - vm_address_t first = 0xffc00000; - vm_address_t last = 0xfffe0000; -#endif - - vm_address_t page = first; - int allocated = 0; - vm_map_t task_self = mach_task_self(); - - while( !err && !allocated && page != last ) { - - err = vm_allocate( task_self, &page, pageSize, 0 ); - if( err == err_none ) - allocated = 1; - else if( err == KERN_NO_SPACE ) { -#if defined(__x86_64__) - page -= pageSize; -#else - page += pageSize; -#endif - err = err_none; - } - } - if( allocated ) - *island = (BranchIsland*) page; - else if( !allocated && !err ) - err = KERN_NO_SPACE; - } - } else { - void *block = malloc( sizeof( BranchIsland ) ); - if( block ) - *island = block; - else - err = KERN_NO_SPACE; - } - if( !err ) - (**island).allocatedHigh = allocateHigh; - - return err; -} - -/***************************************************************************//** - Implementation: Deallocates memory for a branch island. - - @param island -> The island to deallocate. - @result <- mach_error_t - - ***************************************************************************/ - - static mach_error_t -freeBranchIsland( - BranchIsland *island ) -{ - assert( island ); - assert( (*(long*)&island->instructions[0]) == kIslandTemplate[0] ); - assert( island->allocatedHigh ); - - mach_error_t err = err_none; - - if( island->allocatedHigh ) { - vm_size_t pageSize; - err = host_page_size( mach_host_self(), &pageSize ); - if( !err ) { - assert( sizeof( BranchIsland ) <= pageSize ); - err = vm_deallocate( - mach_task_self(), - (vm_address_t) island, pageSize ); - } - } else { - free( island ); - } - - return err; -} - -/***************************************************************************//** - Implementation: Sets the branch island's target, with an optional - instruction. - - @param island -> The branch island to insert target into. - @param branchTo -> The address of the target. - @param instruction -> Optional instruction to execute prior to branch. Set - to zero for nop. - @result <- mach_error_t - - ***************************************************************************/ -#if defined(__ppc__) || defined(__POWERPC__) - static mach_error_t -setBranchIslandTarget( - BranchIsland *island, - const void *branchTo, - long instruction ) -{ - // Copy over the template code. - bcopy( kIslandTemplate, island->instructions, sizeof( kIslandTemplate ) ); - - // Fill in the address. - ((short*)island->instructions)[kAddressLo] = ((long) branchTo) & 0x0000FFFF; - ((short*)island->instructions)[kAddressHi] - = (((long) branchTo) >> 16) & 0x0000FFFF; - - // Fill in the (optional) instuction. - if( instruction != 0 ) { - ((short*)island->instructions)[kInstructionLo] - = instruction & 0x0000FFFF; - ((short*)island->instructions)[kInstructionHi] - = (instruction >> 16) & 0x0000FFFF; - } - - //MakeDataExecutable( island->instructions, sizeof( kIslandTemplate ) ); - msync( island->instructions, sizeof( kIslandTemplate ), MS_INVALIDATE ); - - return err_none; -} -#endif - -#if defined(__i386__) - static mach_error_t -setBranchIslandTarget_i386( - BranchIsland *island, - const void *branchTo, - char* instructions ) -{ - - // Copy over the template code. - bcopy( kIslandTemplate, island->instructions, sizeof( kIslandTemplate ) ); - - // copy original instructions - if (instructions) { - bcopy (instructions, island->instructions + kInstructions, kOriginalInstructionsSize); - } - - // Fill in the address. - int32_t addressOffset = (char *)branchTo - (island->instructions + kJumpAddress + 4); - *((int32_t *)(island->instructions + kJumpAddress)) = addressOffset; - - msync( island->instructions, sizeof( kIslandTemplate ), MS_INVALIDATE ); - return err_none; -} - -#elif defined(__x86_64__) -static mach_error_t -setBranchIslandTarget_i386( - BranchIsland *island, - const void *branchTo, - char* instructions ) -{ - // Copy over the template code. - bcopy( kIslandTemplate, island->instructions, sizeof( kIslandTemplate ) ); - - // Copy original instructions. - if (instructions) { - bcopy (instructions, island->instructions, kOriginalInstructionsSize); - } - - // Fill in the address. - *((uint64_t *)(island->instructions + kJumpAddress)) = (uint64_t)branchTo; - msync( island->instructions, sizeof( kIslandTemplate ), MS_INVALIDATE ); - - return err_none; -} -#endif - - -#if defined(__i386__) || defined(__x86_64__) -// simplistic instruction matching -typedef struct { - unsigned int length; // max 15 - unsigned char mask[15]; // sequence of bytes in memory order - unsigned char constraint[15]; // sequence of bytes in memory order -} AsmInstructionMatch; - -#if defined(__i386__) -static AsmInstructionMatch possibleInstructions[] = { - { 0x5, {0xFF, 0x00, 0x00, 0x00, 0x00}, {0xE9, 0x00, 0x00, 0x00, 0x00} }, // jmp 0x???????? - { 0x5, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, {0x55, 0x89, 0xe5, 0xc9, 0xc3} }, // push %esp; mov %esp,%ebp; leave; ret - { 0x1, {0xFF}, {0x90} }, // nop - { 0x1, {0xF8}, {0x50} }, // push %reg - { 0x2, {0xFF, 0xFF}, {0x89, 0xE5} }, // mov %esp,%ebp - { 0x3, {0xFF, 0xFF, 0xFF}, {0x89, 0x1C, 0x24} }, // mov %ebx,(%esp) - { 0x3, {0xFF, 0xFF, 0x00}, {0x83, 0xEC, 0x00} }, // sub 0x??, %esp - { 0x6, {0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00}, {0x81, 0xEC, 0x00, 0x00, 0x00, 0x00} }, // sub 0x??, %esp with 32bit immediate - { 0x2, {0xFF, 0xFF}, {0x31, 0xC0} }, // xor %eax, %eax - { 0x3, {0xFF, 0x4F, 0x00}, {0x8B, 0x45, 0x00} }, // mov $imm(%ebp), %reg - { 0x3, {0xFF, 0x4C, 0x00}, {0x8B, 0x40, 0x00} }, // mov $imm(%eax-%edx), %reg - { 0x3, {0xFF, 0xCF, 0x00}, {0x8B, 0x4D, 0x00} }, // mov $imm(%rpb), %reg - { 0x3, {0xFF, 0x4F, 0x00}, {0x8A, 0x4D, 0x00} }, // mov $imm(%ebp), %cl - { 0x4, {0xFF, 0xFF, 0xFF, 0x00}, {0x8B, 0x4C, 0x24, 0x00} }, // mov $imm(%esp), %ecx - { 0x4, {0xFF, 0x00, 0x00, 0x00}, {0x8B, 0x00, 0x00, 0x00} }, // mov r16,r/m16 or r32,r/m32 - { 0x5, {0xFF, 0x00, 0x00, 0x00, 0x00}, {0xB9, 0x00, 0x00, 0x00, 0x00} }, // mov $imm, %ecx - { 0x5, {0xFF, 0x00, 0x00, 0x00, 0x00}, {0xB8, 0x00, 0x00, 0x00, 0x00} }, // mov $imm, %eax - { 0x4, {0xFF, 0xFF, 0xFF, 0x00}, {0x66, 0x0F, 0xEF, 0x00} }, // pxor xmm2/128, xmm1 - { 0x2, {0xFF, 0xFF}, {0xDB, 0xE3} }, // fninit - { 0x5, {0xFF, 0x00, 0x00, 0x00, 0x00}, {0xE8, 0x00, 0x00, 0x00, 0x00} }, // call $imm - { 0x4, {0xFF, 0xFF, 0xFF, 0x00}, {0x0F, 0xBE, 0x55, 0x00} }, // movsbl $imm(%ebp), %edx - { 0x0, {0x00}, {0x00} } -}; -#elif defined(__x86_64__) -// TODO(glider): disassembling the "0x48, 0x89" sequences is trickier than it's done below. -// If it stops working, refer to http://ref.x86asm.net/geek.html#modrm_byte_32_64 to do it -// more accurately. -// Note: 0x48 is in fact the REX.W prefix, but it might be wrong to treat it as a separate -// instruction. -static AsmInstructionMatch possibleInstructions[] = { - { 0x5, {0xFF, 0x00, 0x00, 0x00, 0x00}, {0xE9, 0x00, 0x00, 0x00, 0x00} }, // jmp 0x???????? - { 0x1, {0xFF}, {0x90} }, // nop - { 0x1, {0xF8}, {0x50} }, // push %rX - { 0x1, {0xFF}, {0x65} }, // GS prefix - { 0x3, {0xFF, 0xFF, 0xFF}, {0x48, 0x89, 0xE5} }, // mov %rsp,%rbp - { 0x4, {0xFF, 0xFF, 0xFF, 0x00}, {0x48, 0x83, 0xEC, 0x00} }, // sub 0x??, %rsp - { 0x4, {0xFB, 0xFF, 0x07, 0x00}, {0x48, 0x89, 0x05, 0x00} }, // move onto rbp - { 0x3, {0xFB, 0xFF, 0x00}, {0x48, 0x89, 0x00} }, // mov %reg, %reg - { 0x3, {0xFB, 0xFF, 0x00}, {0x49, 0x89, 0x00} }, // mov %reg, %reg (REX.WB) - { 0x2, {0xFF, 0x00}, {0x41, 0x00} }, // push %rXX - { 0x2, {0xFF, 0x00}, {0x84, 0x00} }, // test %rX8,%rX8 - { 0x2, {0xFF, 0x00}, {0x85, 0x00} }, // test %rX,%rX - { 0x2, {0xFF, 0x00}, {0x77, 0x00} }, // ja $i8 - { 0x2, {0xFF, 0x00}, {0x74, 0x00} }, // je $i8 - { 0x5, {0xF8, 0x00, 0x00, 0x00, 0x00}, {0xB8, 0x00, 0x00, 0x00, 0x00} }, // mov $imm, %reg - { 0x3, {0xFF, 0xFF, 0x00}, {0xFF, 0x77, 0x00} }, // pushq $imm(%rdi) - { 0x2, {0xFF, 0xFF}, {0x31, 0xC0} }, // xor %eax, %eax - { 0x5, {0xFF, 0x00, 0x00, 0x00, 0x00}, {0x25, 0x00, 0x00, 0x00, 0x00} }, // and $imm, %eax - { 0x3, {0xFF, 0xFF, 0xFF}, {0x80, 0x3F, 0x00} }, // cmpb $imm, (%rdi) - - { 0x8, {0xFF, 0xFF, 0xCF, 0xFF, 0x00, 0x00, 0x00, 0x00}, - {0x48, 0x8B, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00}, }, // mov $imm, %{rax,rdx,rsp,rsi} - { 0x4, {0xFF, 0xFF, 0xFF, 0x00}, {0x48, 0x83, 0xFA, 0x00}, }, // cmp $i8, %rdx - { 0x4, {0xFF, 0xFF, 0x00, 0x00}, {0x83, 0x7f, 0x00, 0x00}, }, // cmpl $imm, $imm(%rdi) - { 0xa, {0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, - {0x48, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} }, // mov $imm, %rax - { 0x6, {0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00}, - {0x81, 0xE6, 0x00, 0x00, 0x00, 0x00} }, // and $imm, %esi - { 0x6, {0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00}, - {0xFF, 0x25, 0x00, 0x00, 0x00, 0x00} }, // jmpq *(%rip) - { 0x4, {0xFF, 0xFF, 0xFF, 0x00}, {0x66, 0x0F, 0xEF, 0x00} }, // pxor xmm2/128, xmm1 - { 0x2, {0xFF, 0x00}, {0x89, 0x00} }, // mov r/m32,r32 or r/m16,r16 - { 0x3, {0xFF, 0xFF, 0xFF}, {0x49, 0x89, 0xF8} }, // mov %rdi,%r8 - { 0x4, {0xFF, 0xFF, 0xFF, 0xFF}, {0x40, 0x0F, 0xBE, 0xCE} }, // movsbl %sil,%ecx - { 0x7, {0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00}, - {0x48, 0x8D, 0x05, 0x00, 0x00, 0x00, 0x00} }, // lea $imm(%rip),%rax - { 0x3, {0xFF, 0xFF, 0xFF}, {0x0F, 0xBE, 0xCE} }, // movsbl, %dh, %ecx - { 0x3, {0xFF, 0xFF, 0x00}, {0xFF, 0x77, 0x00} }, // pushq $imm(%rdi) - { 0x2, {0xFF, 0xFF}, {0xDB, 0xE3} }, // fninit - { 0x3, {0xFF, 0xFF, 0xFF}, {0x48, 0x85, 0xD2} }, // test %rdx,%rdx - { 0x0, {0x00}, {0x00} } -}; -#endif - -static Boolean codeMatchesInstruction(unsigned char *code, AsmInstructionMatch* instruction) -{ - Boolean match = true; - - size_t i; - assert(instruction); -#ifdef DEBUG_DISASM - fprintf(stderr, "Matching: "); -#endif - for (i=0; i<instruction->length; i++) { - unsigned char mask = instruction->mask[i]; - unsigned char constraint = instruction->constraint[i]; - unsigned char codeValue = code[i]; -#ifdef DEBUG_DISASM - fprintf(stderr, "%x ", (unsigned)codeValue); -#endif - match = ((codeValue & mask) == constraint); - if (!match) break; - } -#ifdef DEBUG_DISASM - if (match) { - fprintf(stderr, " OK\n"); - } else { - fprintf(stderr, " FAIL\n"); - } -#endif - return match; -} - -#if defined(__i386__) || defined(__x86_64__) - static Boolean -eatKnownInstructions( - unsigned char *code, - uint64_t *newInstruction, - int *howManyEaten, - char *originalInstructions, - int *originalInstructionCount, - uint8_t *originalInstructionSizes ) -{ - Boolean allInstructionsKnown = true; - int totalEaten = 0; - unsigned char* ptr = code; - int remainsToEat = 5; // a JMP instruction takes 5 bytes - int instructionIndex = 0; - - if (howManyEaten) *howManyEaten = 0; - if (originalInstructionCount) *originalInstructionCount = 0; - while (remainsToEat > 0) { - Boolean curInstructionKnown = false; - - // See if instruction matches one we know - AsmInstructionMatch* curInstr = possibleInstructions; - do { - if ((curInstructionKnown = codeMatchesInstruction(ptr, curInstr))) break; - curInstr++; - } while (curInstr->length > 0); - - // if all instruction matches failed, we don't know current instruction then, stop here - if (!curInstructionKnown) { - allInstructionsKnown = false; - fprintf(stderr, "mach_override: some instructions unknown! Need to update mach_override.c\n"); - break; - } - - // At this point, we've matched curInstr - int eaten = curInstr->length; - ptr += eaten; - remainsToEat -= eaten; - totalEaten += eaten; - - if (originalInstructionSizes) originalInstructionSizes[instructionIndex] = eaten; - instructionIndex += 1; - if (originalInstructionCount) *originalInstructionCount = instructionIndex; - } - - - if (howManyEaten) *howManyEaten = totalEaten; - - if (originalInstructions) { - Boolean enoughSpaceForOriginalInstructions = (totalEaten < kOriginalInstructionsSize); - - if (enoughSpaceForOriginalInstructions) { - memset(originalInstructions, 0x90 /* NOP */, kOriginalInstructionsSize); // fill instructions with NOP - bcopy(code, originalInstructions, totalEaten); - } else { -#ifdef DEBUG_DISASM - fprintf(stderr, "Not enough space in island to store original instructions. Adapt the island definition and kOriginalInstructionsSize\n"); -#endif - return false; - } - } - - if (allInstructionsKnown) { - // save last 3 bytes of first 64bits of codre we'll replace - uint64_t currentFirst64BitsOfCode = *((uint64_t *)code); - currentFirst64BitsOfCode = OSSwapInt64(currentFirst64BitsOfCode); // back to memory representation - currentFirst64BitsOfCode &= 0x0000000000FFFFFFLL; - - // keep only last 3 instructions bytes, first 5 will be replaced by JMP instr - *newInstruction &= 0xFFFFFFFFFF000000LL; // clear last 3 bytes - *newInstruction |= (currentFirst64BitsOfCode & 0x0000000000FFFFFFLL); // set last 3 bytes - } - - return allInstructionsKnown; -} - - static void -fixupInstructions( - void *originalFunction, - void *escapeIsland, - void *instructionsToFix, - int instructionCount, - uint8_t *instructionSizes ) -{ - void *initialOriginalFunction = originalFunction; - int index, fixed_size, code_size = 0; - for (index = 0;index < instructionCount;index += 1) - code_size += instructionSizes[index]; - -#ifdef DEBUG_DISASM - void *initialInstructionsToFix = instructionsToFix; - fprintf(stderr, "BEFORE FIXING:\n"); - dump16Bytes(initialOriginalFunction); - dump16Bytes(initialInstructionsToFix); -#endif // DEBUG_DISASM - - for (index = 0;index < instructionCount;index += 1) - { - fixed_size = instructionSizes[index]; - if ((*(uint8_t*)instructionsToFix == 0xE9) || // 32-bit jump relative - (*(uint8_t*)instructionsToFix == 0xE8)) // 32-bit call relative - { - uint32_t offset = (uintptr_t)originalFunction - (uintptr_t)escapeIsland; - uint32_t *jumpOffsetPtr = (uint32_t*)((uintptr_t)instructionsToFix + 1); - *jumpOffsetPtr += offset; - } - if ((*(uint8_t*)instructionsToFix == 0x74) || // Near jump if equal (je), 2 bytes. - (*(uint8_t*)instructionsToFix == 0x77)) // Near jump if above (ja), 2 bytes. - { - // We replace a near je/ja instruction, "7P JJ", with a 32-bit je/ja, "0F 8P WW XX YY ZZ". - // This is critical, otherwise a near jump will likely fall outside the original function. - uint32_t offset = (uintptr_t)initialOriginalFunction - (uintptr_t)escapeIsland; - uint32_t jumpOffset = *(uint8_t*)((uintptr_t)instructionsToFix + 1); - *((uint8_t*)instructionsToFix + 1) = *(uint8_t*)instructionsToFix + 0x10; - *(uint8_t*)instructionsToFix = 0x0F; - uint32_t *jumpOffsetPtr = (uint32_t*)((uintptr_t)instructionsToFix + 2 ); - *jumpOffsetPtr = offset + jumpOffset; - fixed_size = 6; - } - - originalFunction = (void*)((uintptr_t)originalFunction + instructionSizes[index]); - escapeIsland = (void*)((uintptr_t)escapeIsland + instructionSizes[index]); - instructionsToFix = (void*)((uintptr_t)instructionsToFix + fixed_size); - - // Expanding short instructions into longer ones may overwrite the next instructions, - // so we must restore them. - code_size -= fixed_size; - if ((code_size > 0) && (fixed_size != instructionSizes[index])) { - bcopy(originalFunction, instructionsToFix, code_size); - } - } -#ifdef DEBUG_DISASM - fprintf(stderr, "AFTER_FIXING:\n"); - dump16Bytes(initialOriginalFunction); - dump16Bytes(initialInstructionsToFix); -#endif // DEBUG_DISASM -} - -#ifdef DEBUG_DISASM -#define HEX_DIGIT(x) ((((x) % 16) < 10) ? ('0' + ((x) % 16)) : ('A' + ((x) % 16 - 10))) - - static void -dump16Bytes( - void *ptr) { - int i; - char buf[3]; - uint8_t *bytes = (uint8_t*)ptr; - for (i = 0; i < 16; i++) { - buf[0] = HEX_DIGIT(bytes[i] / 16); - buf[1] = HEX_DIGIT(bytes[i] % 16); - buf[2] = ' '; - write(2, buf, 3); - } - write(2, "\n", 1); -} -#endif // DEBUG_DISASM -#endif - -#if defined(__i386__) -__asm( - ".text;" - ".align 2, 0x90;" - "_atomic_mov64:;" - " pushl %ebp;" - " movl %esp, %ebp;" - " pushl %esi;" - " pushl %ebx;" - " pushl %ecx;" - " pushl %eax;" - " pushl %edx;" - - // atomic push of value to an address - // we use cmpxchg8b, which compares content of an address with - // edx:eax. If they are equal, it atomically puts 64bit value - // ecx:ebx in address. - // We thus put contents of address in edx:eax to force ecx:ebx - // in address - " mov 8(%ebp), %esi;" // esi contains target address - " mov 12(%ebp), %ebx;" - " mov 16(%ebp), %ecx;" // ecx:ebx now contains value to put in target address - " mov (%esi), %eax;" - " mov 4(%esi), %edx;" // edx:eax now contains value currently contained in target address - " lock; cmpxchg8b (%esi);" // atomic move. - - // restore registers - " popl %edx;" - " popl %eax;" - " popl %ecx;" - " popl %ebx;" - " popl %esi;" - " popl %ebp;" - " ret" -); -#elif defined(__x86_64__) -void atomic_mov64( - uint64_t *targetAddress, - uint64_t value ) -{ - *targetAddress = value; -} -#endif -#endif -#endif // __APPLE__ diff --git a/libsanitizer/interception/mach_override/mach_override.h b/libsanitizer/interception/mach_override/mach_override.h deleted file mode 100644 index 7e60cdcd619..00000000000 --- a/libsanitizer/interception/mach_override/mach_override.h +++ /dev/null @@ -1,140 +0,0 @@ -/******************************************************************************* - mach_override.h - Copyright (c) 2003-2009 Jonathan 'Wolf' Rentzsch: <http://rentzsch.com> - Some rights reserved: <http://opensource.org/licenses/mit-license.php> - - ***************************************************************************/ - -/***************************************************************************//** - @mainpage mach_override - @author Jonathan 'Wolf' Rentzsch: <http://rentzsch.com> - - This package, coded in C to the Mach API, allows you to override ("patch") - program- and system-supplied functions at runtime. You can fully replace - functions with your implementations, or merely head- or tail-patch the - original implementations. - - Use it by #include'ing mach_override.h from your .c, .m or .mm file(s). - - @todo Discontinue use of Carbon's MakeDataExecutable() and - CompareAndSwap() calls and start using the Mach equivalents, if they - exist. If they don't, write them and roll them in. That way, this - code will be pure Mach, which will make it easier to use everywhere. - Update: MakeDataExecutable() has been replaced by - msync(MS_INVALIDATE). There is an OSCompareAndSwap in libkern, but - I'm currently unsure if I can link against it. May have to roll in - my own version... - @todo Stop using an entire 4K high-allocated VM page per 28-byte escape - branch island. Done right, this will dramatically speed up escape - island allocations when they number over 250. Then again, if you're - overriding more than 250 functions, maybe speed isn't your main - concern... - @todo Add detection of: b, bl, bla, bc, bcl, bcla, bcctrl, bclrl - first-instructions. Initially, we should refuse to override - functions beginning with these instructions. Eventually, we should - dynamically rewrite them to make them position-independent. - @todo Write mach_unoverride(), which would remove an override placed on a - function. Must be multiple-override aware, which means an almost - complete rewrite under the covers, because the target address can't - be spread across two load instructions like it is now since it will - need to be atomically updatable. - @todo Add non-rentry variants of overrides to test_mach_override. - - ***************************************************************************/ - -#ifdef __APPLE__ - -#ifndef _mach_override_ -#define _mach_override_ - -#include <sys/types.h> -#include <mach/error.h> - -#ifdef __cplusplus - extern "C" { -#endif - -/** - Returned if the function to be overrided begins with a 'mfctr' instruction. -*/ -#define err_cannot_override (err_local|1) - -/************************************************************************************//** - Dynamically overrides the function implementation referenced by - originalFunctionAddress with the implentation pointed to by overrideFunctionAddress. - Optionally returns a pointer to a "reentry island" which, if jumped to, will resume - the original implementation. - - @param originalFunctionAddress -> Required address of the function to - override (with overrideFunctionAddress). - @param overrideFunctionAddress -> Required address to the overriding - function. - @param originalFunctionReentryIsland <- Optional pointer to pointer to the - reentry island. Can be NULL. - @result <- err_cannot_override if the original - function's implementation begins with - the 'mfctr' instruction. - - ************************************************************************************/ - -// We're prefixing mach_override_ptr() with "__asan_" to avoid name conflicts with other -// mach_override_ptr() implementations that may appear in the client program. - mach_error_t -__asan_mach_override_ptr( - void *originalFunctionAddress, - const void *overrideFunctionAddress, - void **originalFunctionReentryIsland ); - -// Allow to use custom allocation and deallocation routines with mach_override_ptr(). -// This should help to speed up the things on x86_64. -typedef mach_error_t island_malloc( void **ptr, size_t size, void *hint ); -typedef mach_error_t island_free( void *ptr ); - - mach_error_t -__asan_mach_override_ptr_custom( - void *originalFunctionAddress, - const void *overrideFunctionAddress, - void **originalFunctionReentryIsland, - island_malloc *alloc, - island_free *dealloc ); - -/************************************************************************************//** - - - ************************************************************************************/ - -#ifdef __cplusplus - -#define MACH_OVERRIDE( ORIGINAL_FUNCTION_RETURN_TYPE, ORIGINAL_FUNCTION_NAME, ORIGINAL_FUNCTION_ARGS, ERR ) \ - { \ - static ORIGINAL_FUNCTION_RETURN_TYPE (*ORIGINAL_FUNCTION_NAME##_reenter)ORIGINAL_FUNCTION_ARGS; \ - static bool ORIGINAL_FUNCTION_NAME##_overriden = false; \ - class mach_override_class__##ORIGINAL_FUNCTION_NAME { \ - public: \ - static kern_return_t override(void *originalFunctionPtr) { \ - kern_return_t result = err_none; \ - if (!ORIGINAL_FUNCTION_NAME##_overriden) { \ - ORIGINAL_FUNCTION_NAME##_overriden = true; \ - result = mach_override_ptr( (void*)originalFunctionPtr, \ - (void*)mach_override_class__##ORIGINAL_FUNCTION_NAME::replacement, \ - (void**)&ORIGINAL_FUNCTION_NAME##_reenter ); \ - } \ - return result; \ - } \ - static ORIGINAL_FUNCTION_RETURN_TYPE replacement ORIGINAL_FUNCTION_ARGS { - -#define END_MACH_OVERRIDE( ORIGINAL_FUNCTION_NAME ) \ - } \ - }; \ - \ - err = mach_override_class__##ORIGINAL_FUNCTION_NAME::override((void*)ORIGINAL_FUNCTION_NAME); \ - } - -#endif - -#ifdef __cplusplus - } -#endif -#endif // _mach_override_ - -#endif // __APPLE__ diff --git a/libsanitizer/merge.sh b/libsanitizer/merge.sh index 297af56e790..0f75431cf68 100755 --- a/libsanitizer/merge.sh +++ b/libsanitizer/merge.sh @@ -66,6 +66,7 @@ CUR_REV=$(get_current_rev) echo Current upstream revision: $CUR_REV merge include/sanitizer include/sanitizer merge lib/asan asan +merge lib/asan/dynamic asan/dynamic merge lib/tsan/rtl tsan merge lib/sanitizer_common sanitizer_common merge lib/interception interception |