summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--compiler-rt/lib/hwasan/CMakeLists.txt3
-rw-r--r--compiler-rt/lib/hwasan/hwasan.cc15
-rw-r--r--compiler-rt/lib/hwasan/hwasan.h12
-rw-r--r--compiler-rt/lib/hwasan/hwasan_allocator.cc1
-rw-r--r--compiler-rt/lib/hwasan/hwasan_dynamic_shadow.cc132
-rw-r--r--compiler-rt/lib/hwasan/hwasan_dynamic_shadow.h27
-rw-r--r--compiler-rt/lib/hwasan/hwasan_interceptors.cc1
-rw-r--r--compiler-rt/lib/hwasan/hwasan_interface_internal.h4
-rw-r--r--compiler-rt/lib/hwasan/hwasan_linux.cc198
-rw-r--r--compiler-rt/lib/hwasan/hwasan_mapping.h81
-rw-r--r--compiler-rt/lib/hwasan/hwasan_poisoning.cc3
-rw-r--r--compiler-rt/lib/hwasan/hwasan_report.cc1
-rw-r--r--compiler-rt/lib/hwasan/hwasan_thread.cc1
13 files changed, 409 insertions, 70 deletions
diff --git a/compiler-rt/lib/hwasan/CMakeLists.txt b/compiler-rt/lib/hwasan/CMakeLists.txt
index 88a1e8c5388..a808d9e2333 100644
--- a/compiler-rt/lib/hwasan/CMakeLists.txt
+++ b/compiler-rt/lib/hwasan/CMakeLists.txt
@@ -4,11 +4,12 @@ include_directories(..)
set(HWASAN_RTL_SOURCES
hwasan.cc
hwasan_allocator.cc
+ hwasan_dynamic_shadow.cc
hwasan_interceptors.cc
hwasan_linux.cc
+ hwasan_poisoning.cc
hwasan_report.cc
hwasan_thread.cc
- hwasan_poisoning.cc
)
set(HWASAN_RTL_CXX_SOURCES
diff --git a/compiler-rt/lib/hwasan/hwasan.cc b/compiler-rt/lib/hwasan/hwasan.cc
index 5aa69a51039..d300e0bde41 100644
--- a/compiler-rt/lib/hwasan/hwasan.cc
+++ b/compiler-rt/lib/hwasan/hwasan.cc
@@ -13,6 +13,7 @@
//===----------------------------------------------------------------------===//
#include "hwasan.h"
+#include "hwasan_mapping.h"
#include "hwasan_thread.h"
#include "hwasan_poisoning.h"
#include "sanitizer_common/sanitizer_atomic.h"
@@ -157,6 +158,8 @@ static void HWAsanCheckFailed(const char *file, int line, const char *cond,
using namespace __hwasan;
+uptr __hwasan_shadow_memory_dynamic_address; // Global interface symbol.
+
void __hwasan_init() {
CHECK(!hwasan_init_is_running);
if (hwasan_inited) return;
@@ -179,11 +182,13 @@ void __hwasan_init() {
DisableCoreDumperIfNecessary();
if (!InitShadow()) {
- Printf("FATAL: HWAddressSanitizer can not mmap the shadow memory.\n");
- Printf("FATAL: Make sure to compile with -fPIE and to link with -pie.\n");
- Printf("FATAL: Disabling ASLR is known to cause this error.\n");
- Printf("FATAL: If running under GDB, try "
- "'set disable-randomization off'.\n");
+ Printf("FATAL: HWAddressSanitizer cannot mmap the shadow memory.\n");
+ if (HWASAN_FIXED_MAPPING) {
+ Printf("FATAL: Make sure to compile with -fPIE and to link with -pie.\n");
+ Printf("FATAL: Disabling ASLR is known to cause this error.\n");
+ Printf("FATAL: If running under GDB, try "
+ "'set disable-randomization off'.\n");
+ }
DumpProcessMap();
Die();
}
diff --git a/compiler-rt/lib/hwasan/hwasan.h b/compiler-rt/lib/hwasan/hwasan.h
index 604c9702448..3c6b44f7f11 100644
--- a/compiler-rt/lib/hwasan/hwasan.h
+++ b/compiler-rt/lib/hwasan/hwasan.h
@@ -32,16 +32,6 @@
typedef u8 tag_t;
-// Reasonable values are 4 (for 1/16th shadow) and 6 (for 1/64th).
-const uptr kShadowScale = 4;
-const uptr kShadowAlignment = 1UL << kShadowScale;
-
-#define MEM_TO_SHADOW_OFFSET(mem) ((uptr)(mem) >> kShadowScale)
-#define MEM_TO_SHADOW(mem) ((uptr)(mem) >> kShadowScale)
-#define SHADOW_TO_MEM(shadow) ((uptr)(shadow) << kShadowScale)
-
-#define MEM_IS_APP(mem) MemIsApp((uptr)(mem))
-
// TBI (Top Byte Ignore) feature of AArch64: bits [63:56] are ignored in address
// translation and can be used to store a tag.
const unsigned kAddressTagShift = 56;
@@ -69,8 +59,6 @@ extern int hwasan_inited;
extern bool hwasan_init_is_running;
extern int hwasan_report_count;
-bool MemIsApp(uptr p);
-
bool ProtectRange(uptr beg, uptr end);
bool InitShadow();
char *GetProcSelfMaps();
diff --git a/compiler-rt/lib/hwasan/hwasan_allocator.cc b/compiler-rt/lib/hwasan/hwasan_allocator.cc
index d1df1452f95..3a9da80d928 100644
--- a/compiler-rt/lib/hwasan/hwasan_allocator.cc
+++ b/compiler-rt/lib/hwasan/hwasan_allocator.cc
@@ -20,6 +20,7 @@
#include "sanitizer_common/sanitizer_stackdepot.h"
#include "hwasan.h"
#include "hwasan_allocator.h"
+#include "hwasan_mapping.h"
#include "hwasan_thread.h"
#include "hwasan_poisoning.h"
diff --git a/compiler-rt/lib/hwasan/hwasan_dynamic_shadow.cc b/compiler-rt/lib/hwasan/hwasan_dynamic_shadow.cc
new file mode 100644
index 00000000000..17338003aa6
--- /dev/null
+++ b/compiler-rt/lib/hwasan/hwasan_dynamic_shadow.cc
@@ -0,0 +1,132 @@
+//===-- hwasan_dynamic_shadow.cc --------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file is a part of HWAddressSanitizer. It reserves dynamic shadow memory
+/// region and handles ifunc resolver case, when necessary.
+///
+//===----------------------------------------------------------------------===//
+
+#include "hwasan_dynamic_shadow.h"
+#include "hwasan_mapping.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include "sanitizer_common/sanitizer_posix.h"
+
+// The code in this file needs to run in an unrelocated binary. It should not
+// access any external symbol, including its own non-hidden globals.
+
+namespace __hwasan {
+
+static void UnmapFromTo(uptr from, uptr to) {
+ if (to == from)
+ return;
+ CHECK(to >= from);
+ uptr res = internal_munmap(reinterpret_cast<void *>(from), to - from);
+ if (UNLIKELY(internal_iserror(res))) {
+ Report("ERROR: %s failed to unmap 0x%zx (%zd) bytes at address %p\n",
+ SanitizerToolName, to - from, to - from, from);
+ CHECK("unable to unmap" && 0);
+ }
+}
+
+// Returns an address aligned to 8 pages, such that one page on the left and
+// shadow_size_bytes bytes on the right of it are mapped r/o.
+static uptr MapDynamicShadow(uptr shadow_size_bytes) {
+ const uptr granularity = GetMmapGranularity();
+ const uptr alignment = granularity * SHADOW_GRANULARITY;
+ const uptr left_padding = granularity;
+ const uptr shadow_size =
+ RoundUpTo(shadow_size_bytes, granularity);
+ const uptr map_size = shadow_size + left_padding + alignment;
+
+ const uptr map_start = (uptr)MmapNoAccess(map_size);
+ CHECK_NE(map_start, ~(uptr)0);
+
+ const uptr shadow_start = RoundUpTo(map_start + left_padding, alignment);
+
+ UnmapFromTo(map_start, shadow_start - left_padding);
+ UnmapFromTo(shadow_start + shadow_size, map_start + map_size);
+
+ return shadow_start;
+}
+
+} // namespace __hwasan
+
+#if HWASAN_PREMAP_SHADOW
+
+extern "C" {
+
+INTERFACE_ATTRIBUTE void __hwasan_shadow();
+decltype(__hwasan_shadow)* __hwasan_premap_shadow();
+
+} // extern "C"
+
+namespace __hwasan {
+
+// Conservative upper limit.
+static uptr PremapShadowSize() {
+ return RoundUpTo(GetMaxVirtualAddress() >> kShadowScale,
+ GetMmapGranularity());
+}
+
+static uptr PremapShadow() {
+ return MapDynamicShadow(PremapShadowSize());
+}
+
+static bool IsPremapShadowAvailable() {
+ const uptr shadow = reinterpret_cast<uptr>(&__hwasan_shadow);
+ const uptr resolver = reinterpret_cast<uptr>(&__hwasan_premap_shadow);
+ // shadow == resolver is how Android KitKat and older handles ifunc.
+ // shadow == 0 just in case.
+ return shadow != 0 && shadow != resolver;
+}
+
+static uptr FindPremappedShadowStart(uptr shadow_size_bytes) {
+ const uptr granularity = GetMmapGranularity();
+ const uptr shadow_start = reinterpret_cast<uptr>(&__hwasan_shadow);
+ const uptr premap_shadow_size = PremapShadowSize();
+ const uptr shadow_size = RoundUpTo(shadow_size_bytes, granularity);
+
+ // We may have mapped too much. Release extra memory.
+ UnmapFromTo(shadow_start + shadow_size, shadow_start + premap_shadow_size);
+ return shadow_start;
+}
+
+} // namespace __hwasan
+
+extern "C" {
+
+decltype(__hwasan_shadow)* __hwasan_premap_shadow() {
+ // The resolver might be called multiple times. Map the shadow just once.
+ static __sanitizer::uptr shadow = 0;
+ if (!shadow)
+ shadow = __hwasan::PremapShadow();
+ return reinterpret_cast<decltype(__hwasan_shadow)*>(shadow);
+}
+
+// __hwasan_shadow is a "function" that has the same address as the first byte
+// of the shadow mapping.
+INTERFACE_ATTRIBUTE __attribute__((ifunc("__hwasan_premap_shadow")))
+void __hwasan_shadow();
+
+} // extern "C"
+
+#endif // HWASAN_PREMAP_SHADOW
+
+namespace __hwasan {
+
+uptr FindDynamicShadowStart(uptr shadow_size_bytes) {
+#if HWASAN_PREMAP_SHADOW
+ if (IsPremapShadowAvailable())
+ return FindPremappedShadowStart(shadow_size_bytes);
+#endif
+ return MapDynamicShadow(shadow_size_bytes);
+}
+
+} // namespace __hwasan
diff --git a/compiler-rt/lib/hwasan/hwasan_dynamic_shadow.h b/compiler-rt/lib/hwasan/hwasan_dynamic_shadow.h
new file mode 100644
index 00000000000..b5e9e1dd6a0
--- /dev/null
+++ b/compiler-rt/lib/hwasan/hwasan_dynamic_shadow.h
@@ -0,0 +1,27 @@
+//===-- hwasan_dynamic_shadow.h ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file is a part of HWAddressSanitizer. It reserves dynamic shadow memory
+/// region.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef HWASAN_PREMAP_SHADOW_H
+#define HWASAN_PREMAP_SHADOW_H
+
+#include "sanitizer_common/sanitizer_internal_defs.h"
+
+namespace __hwasan {
+
+uptr FindDynamicShadowStart(uptr shadow_size_bytes);
+
+} // namespace __hwasan
+
+#endif // HWASAN_PREMAP_SHADOW_H
diff --git a/compiler-rt/lib/hwasan/hwasan_interceptors.cc b/compiler-rt/lib/hwasan/hwasan_interceptors.cc
index 7b89e56f5ba..dfd35b59cec 100644
--- a/compiler-rt/lib/hwasan/hwasan_interceptors.cc
+++ b/compiler-rt/lib/hwasan/hwasan_interceptors.cc
@@ -17,6 +17,7 @@
#include "interception/interception.h"
#include "hwasan.h"
+#include "hwasan_mapping.h"
#include "hwasan_thread.h"
#include "hwasan_poisoning.h"
#include "sanitizer_common/sanitizer_platform_limits_posix.h"
diff --git a/compiler-rt/lib/hwasan/hwasan_interface_internal.h b/compiler-rt/lib/hwasan/hwasan_interface_internal.h
index 54639f9c171..b4e5c80904d 100644
--- a/compiler-rt/lib/hwasan/hwasan_interface_internal.h
+++ b/compiler-rt/lib/hwasan/hwasan_interface_internal.h
@@ -18,6 +18,7 @@
#include "sanitizer_common/sanitizer_internal_defs.h"
extern "C" {
+
SANITIZER_INTERFACE_ATTRIBUTE
void __hwasan_init();
@@ -32,6 +33,9 @@ using __sanitizer::u16;
using __sanitizer::u8;
SANITIZER_INTERFACE_ATTRIBUTE
+extern uptr __hwasan_shadow_memory_dynamic_address;
+
+SANITIZER_INTERFACE_ATTRIBUTE
void __hwasan_loadN(uptr, uptr);
SANITIZER_INTERFACE_ATTRIBUTE
void __hwasan_load1(uptr);
diff --git a/compiler-rt/lib/hwasan/hwasan_linux.cc b/compiler-rt/lib/hwasan/hwasan_linux.cc
index 69e4a8d483c..693e3b5b30f 100644
--- a/compiler-rt/lib/hwasan/hwasan_linux.cc
+++ b/compiler-rt/lib/hwasan/hwasan_linux.cc
@@ -1,4 +1,4 @@
-//===-- hwasan_linux.cc -----------------------------------------------------===//
+//===-- hwasan_linux.cc -----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
@@ -6,35 +6,39 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-//
-// This file is a part of HWAddressSanitizer.
-//
-// Linux-, NetBSD- and FreeBSD-specific code.
+///
+/// \file
+/// This file is a part of HWAddressSanitizer and contains Linux-, NetBSD- and
+/// FreeBSD-specific code.
+///
//===----------------------------------------------------------------------===//
#include "sanitizer_common/sanitizer_platform.h"
#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD
#include "hwasan.h"
+#include "hwasan_dynamic_shadow.h"
+#include "hwasan_interface_internal.h"
+#include "hwasan_mapping.h"
#include "hwasan_thread.h"
#include <elf.h>
#include <link.h>
#include <pthread.h>
+#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
-#include <signal.h>
+#include <sys/resource.h>
+#include <sys/time.h>
#include <unistd.h>
#include <unwind.h>
-#include <sys/time.h>
-#include <sys/resource.h>
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_procmaps.h"
namespace __hwasan {
-void ReserveShadowMemoryRange(uptr beg, uptr end, const char *name) {
+static void ReserveShadowMemoryRange(uptr beg, uptr end, const char *name) {
CHECK_EQ((beg % GetMmapGranularity()), 0);
CHECK_EQ(((end + 1) % GetMmapGranularity()), 0);
uptr size = end - beg + 1;
@@ -52,8 +56,11 @@ void ReserveShadowMemoryRange(uptr beg, uptr end, const char *name) {
}
static void ProtectGap(uptr addr, uptr size) {
+ if (!size)
+ return;
void *res = MmapFixedNoAccess(addr, size, "shadow gap");
- if (addr == (uptr)res) return;
+ if (addr == (uptr)res)
+ return;
// A few pages at the start of the address space can not be protected.
// But we really want to protect as much as possible, to prevent this memory
// being returned as a result of a non-FIXED mmap().
@@ -63,69 +70,158 @@ static void ProtectGap(uptr addr, uptr size) {
addr += step;
size -= step;
void *res = MmapFixedNoAccess(addr, size, "shadow gap");
- if (addr == (uptr)res) return;
+ if (addr == (uptr)res)
+ return;
}
}
Report(
- "ERROR: Failed to protect the shadow gap. "
- "HWASan cannot proceed correctly. ABORTING.\n");
+ "ERROR: Failed to protect shadow gap [%p, %p]. "
+ "HWASan cannot proceed correctly. ABORTING.\n", (void *)addr,
+ (void *)(addr + size));
DumpProcessMap();
Die();
}
-// LowMem covers as much of the first 4GB as possible.
-const uptr kLowMemEnd = 1UL << 32;
-const uptr kLowShadowEnd = kLowMemEnd >> kShadowScale;
-const uptr kLowShadowStart = kLowShadowEnd >> kShadowScale;
+static uptr kLowMemStart;
+static uptr kLowMemEnd;
+static uptr kLowShadowEnd;
+static uptr kLowShadowStart;
static uptr kHighShadowStart;
static uptr kHighShadowEnd;
static uptr kHighMemStart;
+static uptr kHighMemEnd;
-bool InitShadow() {
- const uptr maxVirtualAddress = GetMaxUserVirtualAddress();
+static void PrintRange(uptr start, uptr end, const char *name) {
+ Printf("|| [%p, %p] || %.*s ||\n", (void *)start, (void *)end, 10, name);
+}
+
+static void PrintAddressSpaceLayout() {
+ PrintRange(kHighMemStart, kHighMemEnd, "HighMem");
+ if (kHighShadowEnd + 1 < kHighMemStart)
+ PrintRange(kHighShadowEnd + 1, kHighMemStart - 1, "ShadowGap");
+ else
+ CHECK_EQ(kHighShadowEnd + 1, kHighMemStart);
+ PrintRange(kHighShadowStart, kHighShadowEnd, "HighShadow");
+ if (SHADOW_OFFSET) {
+ if (kLowShadowEnd + 1 < kHighShadowStart)
+ PrintRange(kLowShadowEnd + 1, kHighShadowStart - 1, "ShadowGap");
+ else
+ CHECK_EQ(kLowMemEnd + 1, kHighShadowStart);
+ PrintRange(kLowShadowStart, kLowShadowEnd, "LowShadow");
+ if (kLowMemEnd + 1 < kLowShadowStart)
+ PrintRange(kLowMemEnd + 1, kLowShadowStart - 1, "ShadowGap");
+ else
+ CHECK_EQ(kLowMemEnd + 1, kLowShadowStart);
+ PrintRange(kLowMemStart, kLowMemEnd, "LowMem");
+ CHECK_EQ(0, kLowMemStart);
+ } else {
+ if (kLowMemEnd + 1 < kHighShadowStart)
+ PrintRange(kLowMemEnd + 1, kHighShadowStart - 1, "ShadowGap");
+ else
+ CHECK_EQ(kLowMemEnd + 1, kHighShadowStart);
+ PrintRange(kLowMemStart, kLowMemEnd, "LowMem");
+ CHECK_EQ(kLowShadowEnd + 1, kLowMemStart);
+ PrintRange(kLowShadowStart, kLowShadowEnd, "LowShadow");
+ PrintRange(0, kLowShadowStart - 1, "ShadowGap");
+ }
+}
+static uptr GetHighMemEnd() {
// HighMem covers the upper part of the address space.
- kHighShadowEnd = (maxVirtualAddress >> kShadowScale) + 1;
- kHighShadowStart = Max(kLowMemEnd, kHighShadowEnd >> kShadowScale);
- CHECK(kHighShadowStart < kHighShadowEnd);
-
- kHighMemStart = kHighShadowStart << kShadowScale;
- CHECK(kHighShadowEnd <= kHighMemStart);
-
- if (Verbosity()) {
- Printf("|| `[%p, %p]` || HighMem ||\n", (void *)kHighMemStart,
- (void *)maxVirtualAddress);
- if (kHighMemStart > kHighShadowEnd)
- Printf("|| `[%p, %p]` || ShadowGap2 ||\n", (void *)kHighShadowEnd,
- (void *)kHighMemStart);
- Printf("|| `[%p, %p]` || HighShadow ||\n", (void *)kHighShadowStart,
- (void *)kHighShadowEnd);
- if (kHighShadowStart > kLowMemEnd)
- Printf("|| `[%p, %p]` || ShadowGap2 ||\n", (void *)kHighShadowEnd,
- (void *)kHighMemStart);
- Printf("|| `[%p, %p]` || LowMem ||\n", (void *)kLowShadowEnd,
- (void *)kLowMemEnd);
- Printf("|| `[%p, %p]` || LowShadow ||\n", (void *)kLowShadowStart,
- (void *)kLowShadowEnd);
- Printf("|| `[%p, %p]` || ShadowGap1 ||\n", (void *)0,
- (void *)kLowShadowStart);
+ uptr max_address = GetMaxUserVirtualAddress();
+ if (SHADOW_OFFSET)
+ // Adjust max address to make sure that kHighMemEnd and kHighMemStart are
+ // properly aligned:
+ max_address |= SHADOW_GRANULARITY * GetMmapGranularity() - 1;
+ return max_address;
+}
+
+static void InitializeShadowBaseAddress(uptr shadow_size_bytes) {
+ // Set the shadow memory address to uninitialized.
+ __hwasan_shadow_memory_dynamic_address = kDefaultShadowSentinel;
+ uptr shadow_start = SHADOW_OFFSET;
+ // Detect if a dynamic shadow address must be used and find the available
+ // location when necessary. When dynamic address is used, the macro
+ // kLowShadowBeg expands to __hwasan_shadow_memory_dynamic_address which
+ // was just set to kDefaultShadowSentinel.
+ if (shadow_start == kDefaultShadowSentinel) {
+ __hwasan_shadow_memory_dynamic_address = 0;
+ CHECK_EQ(0, SHADOW_OFFSET);
+ shadow_start = FindDynamicShadowStart(shadow_size_bytes);
}
+ // Update the shadow memory address (potentially) used by instrumentation.
+ __hwasan_shadow_memory_dynamic_address = shadow_start;
+}
- ReserveShadowMemoryRange(kLowShadowStart, kLowShadowEnd - 1, "low shadow");
- ReserveShadowMemoryRange(kHighShadowStart, kHighShadowEnd - 1, "high shadow");
- ProtectGap(0, kLowShadowStart);
- if (kHighShadowStart > kLowMemEnd)
- ProtectGap(kLowMemEnd, kHighShadowStart - kLowMemEnd);
- if (kHighMemStart > kHighShadowEnd)
- ProtectGap(kHighShadowEnd, kHighMemStart - kHighShadowEnd);
+bool InitShadow() {
+ // Define the entire memory range.
+ kHighMemEnd = GetHighMemEnd();
+
+ // Determine shadow memory base offset.
+ InitializeShadowBaseAddress(MEM_TO_SHADOW_SIZE(kHighMemEnd));
+
+ // Place the low memory first.
+ if (SHADOW_OFFSET) {
+ kLowMemEnd = SHADOW_OFFSET - 1;
+ kLowMemStart = 0;
+ } else {
+ // LowMem covers as much of the first 4GB as possible.
+ kLowMemEnd = (1UL << 32) - 1;
+ kLowMemStart = MEM_TO_SHADOW(kLowMemEnd) + 1;
+ }
+
+ // Define the low shadow based on the already placed low memory.
+ kLowShadowEnd = MEM_TO_SHADOW(kLowMemEnd);
+ kLowShadowStart = SHADOW_OFFSET ? SHADOW_OFFSET : MEM_TO_SHADOW(kLowMemStart);
+
+ // High shadow takes whatever memory is left up there (making sure it is not
+ // interfering with low memory in the fixed case).
+ kHighShadowEnd = MEM_TO_SHADOW(kHighMemEnd);
+ kHighShadowStart = Max(kLowMemEnd, MEM_TO_SHADOW(kHighShadowEnd)) + 1;
+
+ // High memory starts where allocated shadow allows.
+ kHighMemStart = SHADOW_TO_MEM(kHighShadowStart);
+
+ // Check the sanity of the defined memory ranges (there might be gaps).
+ CHECK_EQ(kHighMemStart % GetMmapGranularity(), 0);
+ CHECK_GT(kHighMemStart, kHighShadowEnd);
+ CHECK_GT(kHighShadowEnd, kHighShadowStart);
+ CHECK_GT(kHighShadowStart, kLowMemEnd);
+ CHECK_GT(kLowMemEnd, kLowMemStart);
+ CHECK_GT(kLowShadowEnd, kLowShadowStart);
+ if (SHADOW_OFFSET)
+ CHECK_GT(kLowShadowStart, kLowMemEnd);
+ else
+ CHECK_GT(kLowMemEnd, kLowShadowStart);
+
+ if (Verbosity())
+ PrintAddressSpaceLayout();
+
+ // Reserve shadow memory.
+ ReserveShadowMemoryRange(kLowShadowStart, kLowShadowEnd, "low shadow");
+ ReserveShadowMemoryRange(kHighShadowStart, kHighShadowEnd, "high shadow");
+
+ // Protect all the gaps.
+ ProtectGap(0, Min(kLowMemStart, kLowShadowStart));
+ if (SHADOW_OFFSET) {
+ if (kLowMemEnd + 1 < kLowShadowStart)
+ ProtectGap(kLowMemEnd + 1, kLowShadowStart - kLowMemEnd - 1);
+ if (kLowShadowEnd + 1 < kHighShadowStart)
+ ProtectGap(kLowShadowEnd + 1, kHighShadowStart - kLowShadowEnd - 1);
+ } else {
+ if (kLowMemEnd + 1 < kHighShadowStart)
+ ProtectGap(kLowMemEnd + 1, kHighShadowStart - kLowMemEnd - 1);
+ }
+ if (kHighShadowEnd + 1 < kHighMemStart)
+ ProtectGap(kHighShadowEnd + 1, kHighMemStart - kHighShadowEnd - 1);
return true;
}
bool MemIsApp(uptr p) {
CHECK(GetTagFromPointer(p) == 0);
- return p >= kHighMemStart || (p >= kLowShadowEnd && p < kLowMemEnd);
+ return p >= kHighMemStart || (p >= kLowMemStart && p <= kLowMemEnd);
}
static void HwasanAtExit(void) {
diff --git a/compiler-rt/lib/hwasan/hwasan_mapping.h b/compiler-rt/lib/hwasan/hwasan_mapping.h
new file mode 100644
index 00000000000..6064b7c36aa
--- /dev/null
+++ b/compiler-rt/lib/hwasan/hwasan_mapping.h
@@ -0,0 +1,81 @@
+//===-- hwasan_mapping.h ----------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This file is a part of HWAddressSanitizer and defines memory mapping.
+///
+//===----------------------------------------------------------------------===//
+
+#ifndef HWASAN_MAPPING_H
+#define HWASAN_MAPPING_H
+
+#include "sanitizer_common/sanitizer_internal_defs.h"
+
+// Typical mapping on Linux/x86_64 with fixed shadow mapping:
+// || [0x080000000000, 0x7fffffffffff] || HighMem ||
+// || [0x008000000000, 0x07ffffffffff] || HighShadow ||
+// || [0x000100000000, 0x007fffffffff] || ShadowGap ||
+// || [0x000010000000, 0x0000ffffffff] || LowMem ||
+// || [0x000001000000, 0x00000fffffff] || LowShadow ||
+// || [0x000000000000, 0x000000ffffff] || ShadowGap ||
+//
+// and with dynamic shadow mapped at [0x770d59f40000, 0x7f0d59f40000]:
+// || [0x7f0d59f40000, 0x7fffffffffff] || HighMem ||
+// || [0x7efe2f934000, 0x7f0d59f3ffff] || HighShadow ||
+// || [0x7e7e2f934000, 0x7efe2f933fff] || ShadowGap ||
+// || [0x770d59f40000, 0x7e7e2f933fff] || LowShadow ||
+// || [0x000000000000, 0x770d59f3ffff] || LowMem ||
+
+// Typical mapping on Android/AArch64 (39-bit VMA):
+// || [0x001000000000, 0x007fffffffff] || HighMem ||
+// || [0x000800000000, 0x000fffffffff] || ShadowGap ||
+// || [0x000100000000, 0x0007ffffffff] || HighShadow ||
+// || [0x000010000000, 0x0000ffffffff] || LowMem ||
+// || [0x000001000000, 0x00000fffffff] || LowShadow ||
+// || [0x000000000000, 0x000000ffffff] || ShadowGap ||
+//
+// and with dynamic shadow mapped: [0x007477480000, 0x007c77480000]:
+// || [0x007c77480000, 0x007fffffffff] || HighMem ||
+// || [0x007c3ebc8000, 0x007c7747ffff] || HighShadow ||
+// || [0x007bbebc8000, 0x007c3ebc7fff] || ShadowGap ||
+// || [0x007477480000, 0x007bbebc7fff] || LowShadow ||
+// || [0x000000000000, 0x00747747ffff] || LowMem ||
+
+static constexpr __sanitizer::u64 kDefaultShadowSentinel = ~(__sanitizer::u64)0;
+
+// Reasonable values are 4 (for 1/16th shadow) and 6 (for 1/64th).
+constexpr __sanitizer::uptr kShadowScale = 4;
+constexpr __sanitizer::uptr kShadowAlignment = 1ULL << kShadowScale;
+
+#define HWASAN_FIXED_MAPPING 0
+
+#if HWASAN_FIXED_MAPPING
+# define SHADOW_OFFSET (0)
+# define HWASAN_PREMAP_SHADOW 0
+#else
+# define SHADOW_OFFSET (__hwasan_shadow_memory_dynamic_address)
+# define HWASAN_PREMAP_SHADOW 1
+#endif
+
+#define SHADOW_GRANULARITY (1ULL << kShadowScale)
+
+#define MEM_TO_SHADOW(mem) (((uptr)(mem) >> kShadowScale) + SHADOW_OFFSET)
+#define SHADOW_TO_MEM(shadow) (((uptr)(shadow) - SHADOW_OFFSET) << kShadowScale)
+
+#define MEM_TO_SHADOW_SIZE(size) ((uptr)(size) >> kShadowScale)
+
+#define MEM_IS_APP(mem) MemIsApp((uptr)(mem))
+
+namespace __hwasan {
+
+bool MemIsApp(uptr p);
+
+} // namespace __hwasan
+
+#endif // HWASAN_MAPPING_H
diff --git a/compiler-rt/lib/hwasan/hwasan_poisoning.cc b/compiler-rt/lib/hwasan/hwasan_poisoning.cc
index 411fd05b10d..b99d8ed0be7 100644
--- a/compiler-rt/lib/hwasan/hwasan_poisoning.cc
+++ b/compiler-rt/lib/hwasan/hwasan_poisoning.cc
@@ -13,6 +13,7 @@
#include "hwasan_poisoning.h"
+#include "hwasan_mapping.h"
#include "interception/interception.h"
#include "sanitizer_common/sanitizer_common.h"
@@ -22,7 +23,7 @@ uptr TagMemoryAligned(uptr p, uptr size, tag_t tag) {
CHECK(IsAligned(p, kShadowAlignment));
CHECK(IsAligned(size, kShadowAlignment));
uptr shadow_start = MEM_TO_SHADOW(p);
- uptr shadow_size = MEM_TO_SHADOW_OFFSET(size);
+ uptr shadow_size = MEM_TO_SHADOW_SIZE(size);
internal_memset((void *)shadow_start, tag, shadow_size);
return AddTagToPointer(p, tag);
}
diff --git a/compiler-rt/lib/hwasan/hwasan_report.cc b/compiler-rt/lib/hwasan/hwasan_report.cc
index a3c6709491d..438a153f0ca 100644
--- a/compiler-rt/lib/hwasan/hwasan_report.cc
+++ b/compiler-rt/lib/hwasan/hwasan_report.cc
@@ -14,6 +14,7 @@
#include "hwasan.h"
#include "hwasan_allocator.h"
+#include "hwasan_mapping.h"
#include "sanitizer_common/sanitizer_allocator_internal.h"
#include "sanitizer_common/sanitizer_common.h"
#include "sanitizer_common/sanitizer_flags.h"
diff --git a/compiler-rt/lib/hwasan/hwasan_thread.cc b/compiler-rt/lib/hwasan/hwasan_thread.cc
index 75b831b3192..b50c0fc76be 100644
--- a/compiler-rt/lib/hwasan/hwasan_thread.cc
+++ b/compiler-rt/lib/hwasan/hwasan_thread.cc
@@ -1,5 +1,6 @@
#include "hwasan.h"
+#include "hwasan_mapping.h"
#include "hwasan_thread.h"
#include "hwasan_poisoning.h"
#include "hwasan_interface_internal.h"
OpenPOWER on IntegriCloud