[compiler-rt] r330624 - [HWASan] Introduce non-zero based and dynamic shadow memory (compiler-rt).

Alex Shlyapnikov via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 23 11:19:23 PDT 2018


Author: alekseyshl
Date: Mon Apr 23 11:19:23 2018
New Revision: 330624

URL: http://llvm.org/viewvc/llvm-project?rev=330624&view=rev
Log:
[HWASan] Introduce non-zero based and dynamic shadow memory (compiler-rt).

Retire the fixed shadow memory mapping to avoid conflicts with default
process memory mapping (currently manifests on Android).

Tests on AArch64 show <1% performance loss and code size increase,
making it possible to use dynamic shadow memory by default.

Keep the fixed shadow memory mapping around to be able to run
performance comparison tests later.

Re-commiting D45847 with fixed shadow for x86-64.

Modified:
    compiler-rt/trunk/lib/hwasan/CMakeLists.txt
    compiler-rt/trunk/lib/hwasan/hwasan.cc
    compiler-rt/trunk/lib/hwasan/hwasan.h
    compiler-rt/trunk/lib/hwasan/hwasan_allocator.cc
    compiler-rt/trunk/lib/hwasan/hwasan_interceptors.cc
    compiler-rt/trunk/lib/hwasan/hwasan_interface_internal.h
    compiler-rt/trunk/lib/hwasan/hwasan_linux.cc
    compiler-rt/trunk/lib/hwasan/hwasan_poisoning.cc
    compiler-rt/trunk/lib/hwasan/hwasan_report.cc
    compiler-rt/trunk/lib/hwasan/hwasan_thread.cc

Modified: compiler-rt/trunk/lib/hwasan/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/CMakeLists.txt?rev=330624&r1=330623&r2=330624&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/hwasan/CMakeLists.txt Mon Apr 23 11:19:23 2018
@@ -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

Modified: compiler-rt/trunk/lib/hwasan/hwasan.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan.cc?rev=330624&r1=330623&r2=330624&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan.cc (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan.cc Mon Apr 23 11:19:23 2018
@@ -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
 
 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();
   }

Modified: compiler-rt/trunk/lib/hwasan/hwasan.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan.h?rev=330624&r1=330623&r2=330624&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan.h (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan.h Mon Apr 23 11:19:23 2018
@@ -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();

Modified: compiler-rt/trunk/lib/hwasan/hwasan_allocator.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan_allocator.cc?rev=330624&r1=330623&r2=330624&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan_allocator.cc (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan_allocator.cc Mon Apr 23 11:19:23 2018
@@ -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"
 

Modified: compiler-rt/trunk/lib/hwasan/hwasan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan_interceptors.cc?rev=330624&r1=330623&r2=330624&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan_interceptors.cc Mon Apr 23 11:19:23 2018
@@ -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"

Modified: compiler-rt/trunk/lib/hwasan/hwasan_interface_internal.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan_interface_internal.h?rev=330624&r1=330623&r2=330624&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan_interface_internal.h (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan_interface_internal.h Mon Apr 23 11:19:23 2018
@@ -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);

Modified: compiler-rt/trunk/lib/hwasan/hwasan_linux.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan_linux.cc?rev=330624&r1=330623&r2=330624&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan_linux.cc (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan_linux.cc Mon Apr 23 11:19:23 2018
@@ -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,
 }
 
 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 s
       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);
-  }
-
-  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);
+  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;
+}
+
+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) {

Modified: compiler-rt/trunk/lib/hwasan/hwasan_poisoning.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan_poisoning.cc?rev=330624&r1=330623&r2=330624&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan_poisoning.cc (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan_poisoning.cc Mon Apr 23 11:19:23 2018
@@ -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,
   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);
 }

Modified: compiler-rt/trunk/lib/hwasan/hwasan_report.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan_report.cc?rev=330624&r1=330623&r2=330624&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan_report.cc (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan_report.cc Mon Apr 23 11:19:23 2018
@@ -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"

Modified: compiler-rt/trunk/lib/hwasan/hwasan_thread.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan_thread.cc?rev=330624&r1=330623&r2=330624&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan_thread.cc (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan_thread.cc Mon Apr 23 11:19:23 2018
@@ -1,5 +1,6 @@
 
 #include "hwasan.h"
+#include "hwasan_mapping.h"
 #include "hwasan_thread.h"
 #include "hwasan_poisoning.h"
 #include "hwasan_interface_internal.h"




More information about the llvm-commits mailing list