summaryrefslogtreecommitdiffstats
path: root/compiler-rt
diff options
context:
space:
mode:
Diffstat (limited to 'compiler-rt')
-rw-r--r--compiler-rt/lib/asan/CMakeLists.txt1
-rw-r--r--compiler-rt/lib/asan/asan_init_version.h7
-rw-r--r--compiler-rt/lib/asan/asan_linux.cc32
-rw-r--r--compiler-rt/lib/asan/asan_mapping.h8
-rw-r--r--compiler-rt/lib/asan/asan_premap_shadow.cc69
-rw-r--r--compiler-rt/lib/asan/asan_premap_shadow.h28
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_common.h1
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_flags.h4
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cc4
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_linux.cc18
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_mac.cc4
-rw-r--r--compiler-rt/lib/sanitizer_common/sanitizer_win.cc4
12 files changed, 170 insertions, 10 deletions
diff --git a/compiler-rt/lib/asan/CMakeLists.txt b/compiler-rt/lib/asan/CMakeLists.txt
index 334235746a0..9291e71099f 100644
--- a/compiler-rt/lib/asan/CMakeLists.txt
+++ b/compiler-rt/lib/asan/CMakeLists.txt
@@ -21,6 +21,7 @@ set(ASAN_SOURCES
asan_memory_profile.cc
asan_poisoning.cc
asan_posix.cc
+ asan_premap_shadow.cc
asan_report.cc
asan_rtl.cc
asan_shadow_setup.cc
diff --git a/compiler-rt/lib/asan/asan_init_version.h b/compiler-rt/lib/asan/asan_init_version.h
index f48cc19cc51..c49fcd74024 100644
--- a/compiler-rt/lib/asan/asan_init_version.h
+++ b/compiler-rt/lib/asan/asan_init_version.h
@@ -15,6 +15,8 @@
#ifndef ASAN_INIT_VERSION_H
#define ASAN_INIT_VERSION_H
+#include "sanitizer_common/sanitizer_platform.h"
+
extern "C" {
// Every time the ASan ABI changes we also change the version number in the
// __asan_init function name. Objects built with incompatible ASan ABI
@@ -32,7 +34,12 @@ extern "C" {
// v6=>v7: added 'odr_indicator' to __asan_global
// v7=>v8: added '__asan_(un)register_image_globals' functions for dead
// stripping support on Mach-O platforms
+#if SANITIZER_WORDSIZE == 32 && SANITIZER_ANDROID
+ // v8=>v9: 32-bit Android switched to dynamic shadow
+ #define __asan_version_mismatch_check __asan_version_mismatch_check_v9
+#else
#define __asan_version_mismatch_check __asan_version_mismatch_check_v8
+#endif
}
#endif // ASAN_INIT_VERSION_H
diff --git a/compiler-rt/lib/asan/asan_linux.cc b/compiler-rt/lib/asan/asan_linux.cc
index a949a9888e2..902c64cc4e0 100644
--- a/compiler-rt/lib/asan/asan_linux.cc
+++ b/compiler-rt/lib/asan/asan_linux.cc
@@ -17,6 +17,7 @@
#include "asan_interceptors.h"
#include "asan_internal.h"
+#include "asan_premap_shadow.h"
#include "asan_thread.h"
#include "sanitizer_common/sanitizer_flags.h"
#include "sanitizer_common/sanitizer_freebsd.h"
@@ -81,10 +82,37 @@ void *AsanDoesNotSupportStaticLinkage() {
return &_DYNAMIC; // defined in link.h
}
+#if ASAN_PREMAP_SHADOW
uptr FindDynamicShadowStart() {
- UNREACHABLE("FindDynamicShadowStart is not available");
- return 0;
+ uptr granularity = GetMmapGranularity();
+ uptr shadow_start = reinterpret_cast<uptr>(&__asan_shadow);
+ uptr shadow_size = PremapShadowSize();
+ UnmapOrDie((void *)(shadow_start - granularity), shadow_size + granularity);
+ // MmapNoAccess does not touch TotalMmap, but UnmapOrDie decreases it.
+ // Compensate.
+ IncreaseTotalMmap(shadow_size + granularity);
+ return shadow_start;
}
+#else
+uptr FindDynamicShadowStart() {
+ uptr granularity = GetMmapGranularity();
+ uptr alignment = granularity * 8;
+ uptr left_padding = granularity;
+ uptr shadow_size = kHighShadowEnd + left_padding;
+ uptr map_size = shadow_size + alignment;
+
+ uptr map_start = (uptr)MmapNoAccess(map_size);
+ CHECK_NE(map_start, ~(uptr)0);
+
+ uptr shadow_start = RoundUpTo(map_start, alignment);
+ UnmapOrDie((void *)map_start, map_size);
+ // MmapNoAccess does not touch TotalMmap, but UnmapOrDie decreases it.
+ // Compensate.
+ IncreaseTotalMmap(map_size);
+
+ return shadow_start;
+}
+#endif
void AsanApplyToGlobals(globals_op_fptr op, const void *needle) {
UNIMPLEMENTED();
diff --git a/compiler-rt/lib/asan/asan_mapping.h b/compiler-rt/lib/asan/asan_mapping.h
index fcd95114e1c..febe090e2ea 100644
--- a/compiler-rt/lib/asan/asan_mapping.h
+++ b/compiler-rt/lib/asan/asan_mapping.h
@@ -156,7 +156,7 @@ static const u64 kWindowsShadowOffset32 = 3ULL << 28; // 0x30000000
# define SHADOW_OFFSET (0)
#elif SANITIZER_WORDSIZE == 32
# if SANITIZER_ANDROID
-# define SHADOW_OFFSET (0)
+# define SHADOW_OFFSET __asan_shadow_memory_dynamic_address
# elif defined(__mips__)
# define SHADOW_OFFSET kMIPS32_ShadowOffset32
# elif SANITIZER_FREEBSD
@@ -200,6 +200,12 @@ static const u64 kWindowsShadowOffset32 = 3ULL << 28; // 0x30000000
# endif
#endif
+#if SANITIZER_ANDROID && defined(__arm__)
+# define ASAN_PREMAP_SHADOW 1
+#else
+# define ASAN_PREMAP_SHADOW 0
+#endif
+
#define SHADOW_GRANULARITY (1ULL << SHADOW_SCALE)
#define MEM_TO_SHADOW(mem) (((mem) >> SHADOW_SCALE) + (SHADOW_OFFSET))
diff --git a/compiler-rt/lib/asan/asan_premap_shadow.cc b/compiler-rt/lib/asan/asan_premap_shadow.cc
new file mode 100644
index 00000000000..0e66eeef126
--- /dev/null
+++ b/compiler-rt/lib/asan/asan_premap_shadow.cc
@@ -0,0 +1,69 @@
+//===-- asan_premap_shadow.cc ---------------------------------------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Reserve shadow memory with an ifunc resolver.
+//===----------------------------------------------------------------------===//
+
+#include "asan_mapping.h"
+
+#if ASAN_PREMAP_SHADOW
+
+#include "asan_premap_shadow.h"
+#include "sanitizer_common/sanitizer_posix.h"
+
+namespace __asan {
+
+// The code in this file needs to run in an unrelocated binary. It may not
+// access any external symbol, including its own non-hidden globals.
+
+// Conservative upper limit.
+uptr PremapShadowSize() {
+ return GetMaxVirtualAddress() >> SHADOW_SCALE;
+}
+
+// Returns an address aligned to 8 pages, such that one page on the left and
+// PremapShadowSize() bytes on the right of it are mapped r/o.
+uptr PremapShadow() {
+ uptr granularity = GetMmapGranularity();
+ uptr alignment = granularity * 8;
+ uptr left_padding = granularity;
+ uptr shadow_size = PremapShadowSize();
+ uptr map_size = shadow_size + left_padding + alignment;
+
+ uptr map_start = (uptr)MmapNoAccess(map_size);
+ CHECK_NE(map_start, ~(uptr)0);
+
+ uptr shadow_start = RoundUpTo(map_start + left_padding, alignment);
+ uptr shadow_end = shadow_start + shadow_size;
+ internal_munmap(reinterpret_cast<void *>(map_start),
+ shadow_start - left_padding - map_start);
+ internal_munmap(reinterpret_cast<void *>(shadow_end),
+ map_start + map_size - shadow_end);
+ return shadow_start;
+}
+
+} // namespace __asan
+
+extern "C" {
+decltype(__asan_shadow)* __asan_premap_shadow() {
+ // The resolver may be called multiple times. Map the shadow just once.
+ static uptr premapped_shadow = 0;
+ if (!premapped_shadow) premapped_shadow = __asan::PremapShadow();
+ return reinterpret_cast<decltype(__asan_shadow)*>(premapped_shadow);
+}
+
+// __asan_shadow is a "function" that has the same address as the first byte of
+// the shadow mapping.
+INTERFACE_ATTRIBUTE __attribute__((ifunc("__asan_premap_shadow"))) void
+__asan_shadow();
+}
+
+#endif // ASAN_PREMAP_SHADOW
diff --git a/compiler-rt/lib/asan/asan_premap_shadow.h b/compiler-rt/lib/asan/asan_premap_shadow.h
new file mode 100644
index 00000000000..6349e04ae44
--- /dev/null
+++ b/compiler-rt/lib/asan/asan_premap_shadow.h
@@ -0,0 +1,28 @@
+//===-- asan_mapping.h ------------------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of AddressSanitizer, an address sanity checker.
+//
+// Premap shadow range with an ifunc resolver.
+//===----------------------------------------------------------------------===//
+
+
+#ifndef ASAN_PREMAP_SHADOW_H
+#define ASAN_PREMAP_SHADOW_H
+
+#if ASAN_PREMAP_SHADOW
+namespace __asan {
+// Conservative upper limit.
+uptr PremapShadowSize();
+}
+#endif
+
+extern "C" INTERFACE_ATTRIBUTE void __asan_shadow();
+
+#endif // ASAN_PREMAP_SHADOW_H
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_common.h b/compiler-rt/lib/sanitizer_common/sanitizer_common.h
index 9fb615f9668..746ba226cd5 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_common.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_common.h
@@ -73,6 +73,7 @@ INLINE uptr GetPageSizeCached() {
return PageSizeCached;
}
uptr GetMmapGranularity();
+uptr GetMaxVirtualAddress();
uptr GetMaxUserVirtualAddress();
// Threads
tid_t GetTid();
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_flags.h b/compiler-rt/lib/sanitizer_common/sanitizer_flags.h
index c2ec29d1656..f42d21931a1 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_flags.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_flags.h
@@ -34,7 +34,9 @@ struct CommonFlags {
};
// Functions to get/set global CommonFlags shared by all sanitizer runtimes:
-extern CommonFlags common_flags_dont_use;
+// FIXME: hidden needed for asan_premap_shadow. Consider building with
+// -fvisibility=hidden.
+extern CommonFlags common_flags_dont_use __attribute__((visibility("hidden")));
inline const CommonFlags *common_flags() {
return &common_flags_dont_use;
}
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cc b/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cc
index 97dff0d8bb6..c03c9939cea 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_fuchsia.cc
@@ -191,6 +191,10 @@ uptr GetMaxUserVirtualAddress() {
return ShadowBounds.memory_limit - 1;
}
+uptr GetMaxVirtualAddress() {
+ return GetMaxUserVirtualAddress();
+}
+
static void *DoAnonymousMmapOrDie(uptr size, const char *mem_type,
bool raw_report, bool die_for_nomem) {
size = RoundUpTo(size, PAGE_SIZE);
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc
index ea1e79556ab..6274b248edb 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cc
@@ -954,7 +954,7 @@ static uptr GetKernelAreaSize() {
}
#endif // SANITIZER_WORDSIZE == 32
-uptr GetMaxUserVirtualAddress() {
+uptr GetMaxVirtualAddress() {
#if SANITIZER_NETBSD && defined(__x86_64__)
return 0x7f7ffffff000ULL; // (0x00007f8000000000 - PAGE_SIZE)
#elif SANITIZER_WORDSIZE == 64
@@ -978,15 +978,21 @@ uptr GetMaxUserVirtualAddress() {
# if defined(__s390__)
return (1ULL << 31) - 1; // 0x7fffffff;
# else
- uptr res = (1ULL << 32) - 1; // 0xffffffff;
- if (!common_flags()->full_address_space)
- res -= GetKernelAreaSize();
- CHECK_LT(reinterpret_cast<uptr>(&res), res);
- return res;
+ return (1ULL << 32) - 1; // 0xffffffff;
# endif
#endif // SANITIZER_WORDSIZE
}
+uptr GetMaxUserVirtualAddress() {
+ uptr addr = GetMaxVirtualAddress();
+#if SANITIZER_WORDSIZE == 32 && !defined(__s390__)
+ if (!common_flags()->full_address_space)
+ addr -= GetKernelAreaSize();
+ CHECK_LT(reinterpret_cast<uptr>(&addr), addr);
+#endif
+ return addr;
+}
+
uptr GetPageSize() {
// Android post-M sysconf(_SC_PAGESIZE) crashes if called from .preinit_array.
#if SANITIZER_ANDROID
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc b/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc
index 284b6cfc75f..195a52c4771 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_mac.cc
@@ -864,6 +864,10 @@ uptr GetMaxUserVirtualAddress() {
#endif // SANITIZER_WORDSIZE
}
+uptr GetMaxVirtualAddress() {
+ return GetMaxUserVirtualAddress();
+}
+
uptr FindAvailableMemoryRange(uptr shadow_size,
uptr alignment,
uptr left_padding,
diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_win.cc b/compiler-rt/lib/sanitizer_common/sanitizer_win.cc
index 1186971f77b..dee1add8203 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_win.cc
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_win.cc
@@ -70,6 +70,10 @@ uptr GetMaxUserVirtualAddress() {
return (uptr)si.lpMaximumApplicationAddress;
}
+uptr GetMaxVirtualAddress() {
+ return GetMaxUserVirtualAddress();
+}
+
bool FileExists(const char *filename) {
return ::GetFileAttributesA(filename) != INVALID_FILE_ATTRIBUTES;
}
OpenPOWER on IntegriCloud