[asan] Switch to using dynamic shadow offset on iOS
authorAnna Zaks <ganna@apple.com>
Tue, 4 Oct 2016 19:02:53 +0000 (19:02 +0000)
committerAnna Zaks <ganna@apple.com>
Tue, 4 Oct 2016 19:02:53 +0000 (19:02 +0000)
The VM layout is not stable between iOS version releases, so switch to dynamic shadow offset.

Differential Revision: https://reviews.llvm.org/D25218

llvm-svn: 283240

compiler-rt/lib/asan/asan_mapping.h
compiler-rt/lib/sanitizer_common/sanitizer_linux.cc
compiler-rt/lib/sanitizer_common/sanitizer_mac.cc
compiler-rt/lib/sanitizer_common/sanitizer_posix.cc

index 24584e94f7493b2f2094cbbf973c55ee15fe1010..5cbdd34d666e862c255fab617046622adc6176ac 100644 (file)
@@ -168,7 +168,7 @@ static const u64 kWindowsShadowOffset32 = 3ULL << 28;  // 0x30000000
 #    if SANITIZER_IOSSIM
 #      define SHADOW_OFFSET kIosSimShadowOffset64
 #    else
-#      define SHADOW_OFFSET kIosShadowOffset64
+#      define SHADOW_OFFSET __asan_shadow_memory_dynamic_address
 #    endif
 #  elif defined(__aarch64__)
 #    define SHADOW_OFFSET kAArch64_ShadowOffset64
index c2fa4c0da68590b3e502d8802bdf5d9dac13c1a0..b2d469ea391b0bc55da54ce1185cb386d709dd86 100644 (file)
@@ -1389,6 +1389,11 @@ void MaybeReexec() {
   // No need to re-exec on Linux.
 }
 
+uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding) {
+  UNREACHABLE("FindAvailableMemoryRange is not available");
+  return 0;
+}
+
 } // namespace __sanitizer
 
 #endif // SANITIZER_FREEBSD || SANITIZER_LINUX
index 6b513486ca4d0fee4374a3aee44ada27658d8f57..86d4e997131819432addd7e4b4adac90f2087777 100644 (file)
@@ -58,6 +58,7 @@ extern "C" {
 #include <libkern/OSAtomic.h>
 #include <mach-o/dyld.h>
 #include <mach/mach.h>
+#include <mach/mach_vm.h>
 #include <mach/vm_statistics.h>
 #include <pthread.h>
 #include <sched.h>
@@ -742,6 +743,43 @@ char **GetArgv() {
   return *_NSGetArgv();
 }
 
+uptr FindAvailableMemoryRange(uptr shadow_size,
+                              uptr alignment,
+                              uptr left_padding) {
+  typedef vm_region_submap_short_info_data_64_t RegionInfo;
+  enum { kRegionInfoSize = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64 };
+  // Start searching for available memory region past PAGEZERO, which is
+  // 4KB on 32-bit and 4GB on 64-bit.
+  mach_vm_address_t start_address =
+    (SANITIZER_WORDSIZE == 32) ? 0x000000001000 : 0x000100000000;
+
+  mach_vm_address_t address = start_address;
+  mach_vm_address_t free_begin = start_address;
+  kern_return_t kr = KERN_SUCCESS;
+  while (kr == KERN_SUCCESS) {
+    mach_vm_size_t vmsize = 0;
+    natural_t depth = 0;
+    RegionInfo vminfo;
+    mach_msg_type_number_t count = kRegionInfoSize;
+    kr = mach_vm_region_recurse(mach_task_self(), &address, &vmsize, &depth,
+                                (vm_region_info_t)&vminfo, &count);
+    if (free_begin != address) {
+      // We found a free region [free_begin..address-1].
+      uptr shadow_address = RoundUpTo((uptr)free_begin + left_padding,
+                                      alignment);
+      if (shadow_address + shadow_size < (uptr)address) {
+        return shadow_address;
+      }
+    }
+    // Move to the next region.
+    address += vmsize;
+    free_begin = address;
+  }
+
+  // We looked at all free regions and could not find one large enough.
+  return 0;
+}
+
 // FIXME implement on this platform.
 void GetMemoryProfile(fill_profile_f cb, uptr *stats, uptr stats_size) { }
 
index ad5db88295a771885a0f08eef250a2917287499e..c70d5a40cb46d5d1236a7df63165d6e4b2ed254c 100644 (file)
@@ -358,11 +358,6 @@ SignalContext SignalContext::Create(void *siginfo, void *context) {
   return SignalContext(context, addr, pc, sp, bp, is_memory_access, write_flag);
 }
 
-uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding) {
-  UNREACHABLE("FindAvailableMemoryRange is not available");
-  return 0;
-}
-
 } // namespace __sanitizer
 
 #endif // SANITIZER_POSIX