summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--compiler-rt/lib/asan/asan_interceptors.cc29
-rw-r--r--compiler-rt/lib/asan/asan_mac.cc33
-rw-r--r--compiler-rt/lib/asan/asan_mac.h10
3 files changed, 58 insertions, 14 deletions
diff --git a/compiler-rt/lib/asan/asan_interceptors.cc b/compiler-rt/lib/asan/asan_interceptors.cc
index 5cbf3f3e6dc..81d261ef9e4 100644
--- a/compiler-rt/lib/asan/asan_interceptors.cc
+++ b/compiler-rt/lib/asan/asan_interceptors.cc
@@ -43,24 +43,25 @@
// After interception, the calls to system functions will be substituted by
// calls to our interceptors. We store pointers to system function f()
// in __asan::real_f().
-//
-// TODO(glider): mach_override_ptr() tends to spend too much time
-// in allocateBranchIsland(). This should be ok for real-word
-// application, but slows down our tests which fork too many children.
#ifdef __APPLE__
#include "mach_override/mach_override.h"
#define WRAPPER_NAME(x) "wrap_"#x
-#define OVERRIDE_FUNCTION(oldfunc, newfunc) \
- CHECK(0 == __asan_mach_override_ptr((void*)(oldfunc), \
- (void*)(newfunc), \
- (void**)&real_##oldfunc)); \
- CHECK(real_##oldfunc != NULL);
-
-#define OVERRIDE_FUNCTION_IF_EXISTS(oldfunc, newfunc) \
- do { __asan_mach_override_ptr((void*)(oldfunc), \
- (void*)(newfunc), \
- (void**)&real_##oldfunc); } while (0)
+#define OVERRIDE_FUNCTION(oldfunc, newfunc) \
+ do {CHECK(0 == __asan_mach_override_ptr_custom((void*)(oldfunc), \
+ (void*)(newfunc), \
+ (void**)&real_##oldfunc, \
+ __asan_allocate_island, \
+ __asan_deallocate_island)); \
+ CHECK(real_##oldfunc != NULL); } while(0)
+
+#define OVERRIDE_FUNCTION_IF_EXISTS(oldfunc, newfunc) \
+ do { __asan_mach_override_ptr_custom((void*)(oldfunc), \
+ (void*)(newfunc), \
+ (void**)&real_##oldfunc, \
+ __asan_allocate_island, \
+ __asan_deallocate_island); \
+ } while (0)
#define INTERCEPT_FUNCTION(func) \
OVERRIDE_FUNCTION(func, WRAP(func))
diff --git a/compiler-rt/lib/asan/asan_mac.cc b/compiler-rt/lib/asan/asan_mac.cc
index 4bfe74cb487..0bf978214b8 100644
--- a/compiler-rt/lib/asan/asan_mac.cc
+++ b/compiler-rt/lib/asan/asan_mac.cc
@@ -32,6 +32,8 @@
namespace __asan {
+void *island_allocator_pos = NULL;
+
extern dispatch_async_f_f real_dispatch_async_f;
extern dispatch_sync_f_f real_dispatch_sync_f;
extern dispatch_after_f_f real_dispatch_after_f;
@@ -172,6 +174,37 @@ void AsanLock::Unlock() {
OSSpinLockUnlock((OSSpinLock*)&opaque_storage_);
}
+// The range of pages to be used by __asan_mach_override_ptr for escape
+// islands.
+// TODO(glider): instead of mapping a fixed range we must find a range of
+// unmapped pages in vmmap and take them.
+#define kIslandEnd (0x7fffffdf0000 - kPageSize)
+#define kIslandBeg (kIslandEnd - 256 * kPageSize)
+
+extern "C"
+mach_error_t __asan_allocate_island(void **ptr,
+ size_t unused_size,
+ void *unused_hint) {
+ if (!island_allocator_pos) {
+ if ((void*)-1 == asan_mmap((void*)kIslandBeg, kIslandEnd - kIslandBeg,
+ PROT_READ | PROT_WRITE | PROT_EXEC,
+ MAP_PRIVATE | MAP_ANON | MAP_FIXED,
+ -1, 0)) {
+ return KERN_NO_SPACE;
+ }
+ island_allocator_pos = (void*)kIslandBeg;
+ };
+ *ptr = island_allocator_pos;
+ island_allocator_pos = (char*)island_allocator_pos + kPageSize;
+ return err_none;
+}
+
+extern "C"
+mach_error_t __asan_deallocate_island(void *ptr) {
+ // Do nothing.
+ // TODO(glider): allow to free and reuse the island memory.
+ return err_none;
+}
// Support for the following functions from libdispatch on Mac OS:
// dispatch_async_f()
diff --git a/compiler-rt/lib/asan/asan_mac.h b/compiler-rt/lib/asan/asan_mac.h
index 32739e766cc..7c941f81b83 100644
--- a/compiler-rt/lib/asan/asan_mac.h
+++ b/compiler-rt/lib/asan/asan_mac.h
@@ -20,6 +20,7 @@
// TODO(glider): need to check if the OS X version is 10.6 or greater.
#include <dispatch/dispatch.h>
+#include <mach/mach_error.h>
#include <setjmp.h>
typedef void* pthread_workqueue_t;
@@ -54,6 +55,15 @@ typedef struct {
extern "C" {
+
+// Allocate memory for the escape island. This cannot be moved to
+// mach_override, because the allocator needs to know about the ASan shadow
+// mappings.
+// TODO(glider): in order to place a relative jump the allocated memory should
+// be within 2 Gb from the hint address.
+mach_error_t __asan_allocate_island(void **ptr, size_t unused_size, void *unused_hint);
+mach_error_t __asan_deallocate_island(void *ptr);
+
// dispatch_barrier_async_f() is not declared in <dispatch/dispatch.h>.
void dispatch_barrier_async_f(dispatch_queue_t dq,
void *ctxt, dispatch_function_t func);
OpenPOWER on IntegriCloud