summaryrefslogtreecommitdiffstats
path: root/compiler-rt/lib/esan/esan_linux.cpp
diff options
context:
space:
mode:
authorDerek Bruening <bruening@google.com>2016-05-28 00:25:16 +0000
committerDerek Bruening <bruening@google.com>2016-05-28 00:25:16 +0000
commit909d32955b0b5e5aee623d25bbcb1ea9bff3022f (patch)
tree0b5d1040c8b8c48daecc1928baa57423f9f0cb88 /compiler-rt/lib/esan/esan_linux.cpp
parent7401516985bcffeb67db966028d4279058c5b05d (diff)
downloadbcm5719-llvm-909d32955b0b5e5aee623d25bbcb1ea9bff3022f.tar.gz
bcm5719-llvm-909d32955b0b5e5aee623d25bbcb1ea9bff3022f.zip
[esan] Add handling of large stack size rlimits
Summary: Adds detection of large stack size rlimits (over 1 TB or unlimited), which results in an mmap location that our shadow mapping does not support. We re-exec the application in this situation. Adds a test of this behavior. Adds general detection of mmap regions outside of our app regions. In the future we want to try to adaptively handle these but for now we abort. Moves the existing Linux-specific mmap code into a platform-specific file where the new rlimit code lives. Reviewers: eugenis Subscribers: vitalybuka, zhaoqin, kcc, aizatsky, llvm-commits, kubabrecka Differential Revision: http://reviews.llvm.org/D20745 llvm-svn: 271079
Diffstat (limited to 'compiler-rt/lib/esan/esan_linux.cpp')
-rw-r--r--compiler-rt/lib/esan/esan_linux.cpp83
1 files changed, 83 insertions, 0 deletions
diff --git a/compiler-rt/lib/esan/esan_linux.cpp b/compiler-rt/lib/esan/esan_linux.cpp
new file mode 100644
index 00000000000..aa961b66116
--- /dev/null
+++ b/compiler-rt/lib/esan/esan_linux.cpp
@@ -0,0 +1,83 @@
+//===-- esan.cpp ----------------------------------------------------------===//
+//
+// 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 EfficiencySanitizer, a family of performance tuners.
+//
+// Linux-specific code for the Esan run-time.
+//===----------------------------------------------------------------------===//
+
+#include "sanitizer_common/sanitizer_platform.h"
+#if SANITIZER_FREEBSD || SANITIZER_LINUX
+
+#include "esan.h"
+#include "esan_shadow.h"
+#include "interception/interception.h"
+#include "sanitizer_common/sanitizer_common.h"
+#include <sys/mman.h>
+#include <errno.h>
+
+namespace __esan {
+
+void verifyAddressSpace() {
+#if SANITIZER_LINUX && defined(__x86_64__)
+ // The kernel determines its mmap base from the stack size limit.
+ // Our Linux 64-bit shadow mapping assumes the stack limit is less than a
+ // terabyte, which keeps the mmap region above 0x7e00'.
+ uptr StackLimit = GetStackSizeLimitInBytes();
+ if (StackSizeIsUnlimited() || StackLimit > MaxStackSize) {
+ VReport(1, "The stack size limit is beyond the maximum supported.\n"
+ "Re-execing with a stack size below 1TB.\n");
+ SetStackSizeLimitInBytes(MaxStackSize);
+ ReExec();
+ }
+#endif
+}
+
+static bool liesWithinSingleAppRegion(uptr Start, SIZE_T Size) {
+ uptr AppStart, AppEnd;
+ for (int i = 0; getAppRegion(i, &AppStart, &AppEnd); ++i) {
+ if (Start >= AppStart && Start + Size - 1 <= AppEnd) {
+ return true;
+ }
+ }
+ return false;
+}
+
+bool fixMmapAddr(void **Addr, SIZE_T Size, int Flags) {
+ if (*Addr) {
+ if (!liesWithinSingleAppRegion((uptr)*Addr, Size)) {
+ VPrintf(1, "mmap conflict: [%p-%p) is not in an app region\n",
+ *Addr, (uptr)*Addr + Size);
+ if (Flags & MAP_FIXED) {
+ errno = EINVAL;
+ return false;
+ } else {
+ *Addr = 0;
+ }
+ }
+ }
+ return true;
+}
+
+uptr checkMmapResult(uptr Addr, SIZE_T Size) {
+ if ((void *)Addr == MAP_FAILED)
+ return Addr;
+ if (!liesWithinSingleAppRegion(Addr, Size)) {
+ // FIXME: attempt to dynamically add this as an app region if it
+ // fits our shadow criteria.
+ // We could also try to remap somewhere else.
+ Printf("ERROR: unsupported mapping at [%p-%p)\n", Addr, Addr+Size);
+ Die();
+ }
+ return Addr;
+}
+
+} // namespace __esan
+
+#endif // SANITIZER_FREEBSD || SANITIZER_LINUX
OpenPOWER on IntegriCloud