[Sanitizer] Using huge page on FreeBSD for shadow mapping

- Unless explicit configuration, using FreeBSD super pages feature for shadow mapping.
- asan only for now.

Reviewers: dim, emaste, vitalybuka

Reviewed By: vitalybuka

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

git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@370008 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/asan/asan_shadow_setup.cpp b/lib/asan/asan_shadow_setup.cpp
index fc9bf51..1732493 100644
--- a/lib/asan/asan_shadow_setup.cpp
+++ b/lib/asan/asan_shadow_setup.cpp
@@ -30,14 +30,13 @@
   CHECK_EQ(((end + 1) % GetMmapGranularity()), 0);
   uptr size = end - beg + 1;
   DecreaseTotalMmap(size);  // Don't count the shadow against mmap_limit_mb.
-  if (!MmapFixedNoReserve(beg, size, name)) {
+  if (!MmapFixedSuperNoReserve(beg, size, name)) {
     Report(
         "ReserveShadowMemoryRange failed while trying to map 0x%zx bytes. "
         "Perhaps you're using ulimit -v\n",
         size);
     Abort();
   }
-  SetShadowRegionHugePageMode(beg, size);
   if (common_flags()->use_madv_dontdump) DontDumpShadowMemory(beg, size);
 }
 
diff --git a/lib/sanitizer_common/sanitizer_common.h b/lib/sanitizer_common/sanitizer_common.h
index 4f0f16d..7a83be3 100644
--- a/lib/sanitizer_common/sanitizer_common.h
+++ b/lib/sanitizer_common/sanitizer_common.h
@@ -100,6 +100,8 @@
 void *MmapOrDieOnFatalError(uptr size, const char *mem_type);
 bool MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name = nullptr)
      WARN_UNUSED_RESULT;
+bool MmapFixedSuperNoReserve(uptr fixed_addr, uptr size, const char *name = nullptr)
+     WARN_UNUSED_RESULT;
 void *MmapNoReserveOrDie(uptr size, const char *mem_type);
 void *MmapFixedOrDie(uptr fixed_addr, uptr size, const char *name = nullptr);
 // Behaves just like MmapFixedOrDie, but tolerates out of memory condition, in
diff --git a/lib/sanitizer_common/sanitizer_posix_libcdep.cpp b/lib/sanitizer_common/sanitizer_posix_libcdep.cpp
index 1bbbf8a..0c167af 100644
--- a/lib/sanitizer_common/sanitizer_posix_libcdep.cpp
+++ b/lib/sanitizer_common/sanitizer_posix_libcdep.cpp
@@ -304,11 +304,11 @@
   MemoryMappingLayout::CacheMemoryMappings();
 }
 
-bool MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name) {
+static bool MmapFixed(uptr fixed_addr, uptr size, int additional_flags, const char *name) {
   size = RoundUpTo(size, GetPageSizeCached());
   fixed_addr = RoundDownTo(fixed_addr, GetPageSizeCached());
   uptr p = MmapNamed((void *)fixed_addr, size, PROT_READ | PROT_WRITE,
-                     MAP_PRIVATE | MAP_FIXED | MAP_NORESERVE | MAP_ANON, name);
+                     MAP_PRIVATE | MAP_FIXED | additional_flags | MAP_ANON, name);
   int reserrno;
   if (internal_iserror(p, &reserrno)) {
     Report("ERROR: %s failed to "
@@ -320,6 +320,25 @@
   return true;
 }
 
+bool MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name) {
+  return MmapFixed(fixed_addr, size, MAP_NORESERVE, name);
+}
+
+bool MmapFixedSuperNoReserve(uptr fixed_addr, uptr size, const char *name) {
+#if SANITIZER_FREEBSD
+  int flags = 0;
+  if (common_flags()->no_huge_pages_for_shadow)
+    return MmapFixedNoReserve(fixed_addr, size, name);
+  // MAP_NORESERVE is implicit with FreeBSD
+  return MmapFixed(fixed_addr, size, MAP_ALIGNED_SUPER, name);
+#else
+  bool r = MmapFixedNoReserve(fixed_addr, size, name);
+  if (r)
+   SetShadowRegionHugePageMode(fixed_addr,size);
+  return r;
+#endif
+}
+
 uptr ReservedAddressRange::Init(uptr size, const char *name, uptr fixed_addr) {
   base_ = fixed_addr ? MmapFixedNoAccess(fixed_addr, size, name)
                      : MmapNoAccess(size);
diff --git a/lib/sanitizer_common/sanitizer_win.cpp b/lib/sanitizer_common/sanitizer_win.cpp
index c98e3d4..9f72ec1 100644
--- a/lib/sanitizer_common/sanitizer_win.cpp
+++ b/lib/sanitizer_common/sanitizer_win.cpp
@@ -239,6 +239,11 @@
   return true;
 }
 
+bool MmapFixedSuperNoReserve(uptr fixed_addr, uptr size, const char *name) {
+  // FIXME: Windows support large pages too. Might be worth checking
+  return MmapFixedNoReserve(fixed_addr, size, name);
+}
+
 // Memory space mapped by 'MmapFixedOrDie' must have been reserved by
 // 'MmapFixedNoAccess'.
 void *MmapFixedOrDie(uptr fixed_addr, uptr size, const char *name) {