]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/compiler-rt/lib/esan/esan_linux.cpp
Merge ^/head r306412 through r306905.
[FreeBSD/FreeBSD.git] / contrib / compiler-rt / lib / esan / esan_linux.cpp
1 //===-- esan.cpp ----------------------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file is a part of EfficiencySanitizer, a family of performance tuners.
11 //
12 // Linux-specific code for the Esan run-time.
13 //===----------------------------------------------------------------------===//
14
15 #include "sanitizer_common/sanitizer_platform.h"
16 #if SANITIZER_FREEBSD || SANITIZER_LINUX
17
18 #include "esan.h"
19 #include "esan_shadow.h"
20 #include "interception/interception.h"
21 #include "sanitizer_common/sanitizer_common.h"
22 #include <sys/mman.h>
23 #include <errno.h>
24
25 namespace __esan {
26
27 void verifyAddressSpace() {
28 #if SANITIZER_LINUX && defined(__x86_64__)
29   // The kernel determines its mmap base from the stack size limit.
30   // Our Linux 64-bit shadow mapping assumes the stack limit is less than a
31   // terabyte, which keeps the mmap region above 0x7e00'.
32   uptr StackLimit = GetStackSizeLimitInBytes();
33   if (StackSizeIsUnlimited() || StackLimit > MaxStackSize) {
34     VReport(1, "The stack size limit is beyond the maximum supported.\n"
35             "Re-execing with a stack size below 1TB.\n");
36     SetStackSizeLimitInBytes(MaxStackSize);
37     ReExec();
38   }
39 #endif
40 }
41
42 static bool liesWithinSingleAppRegion(uptr Start, SIZE_T Size) {
43   uptr AppStart, AppEnd;
44   for (int i = 0; getAppRegion(i, &AppStart, &AppEnd); ++i) {
45     if (Start >= AppStart && Start + Size - 1 <= AppEnd) {
46       return true;
47     }
48   }
49   return false;
50 }
51
52 bool fixMmapAddr(void **Addr, SIZE_T Size, int Flags) {
53   if (*Addr) {
54     if (!liesWithinSingleAppRegion((uptr)*Addr, Size)) {
55       VPrintf(1, "mmap conflict: [%p-%p) is not in an app region\n",
56               *Addr, (uptr)*Addr + Size);
57       if (Flags & MAP_FIXED) {
58         errno = EINVAL;
59         return false;
60       } else {
61         *Addr = 0;
62       }
63     }
64   }
65   return true;
66 }
67
68 uptr checkMmapResult(uptr Addr, SIZE_T Size) {
69   if ((void *)Addr == MAP_FAILED)
70     return Addr;
71   if (!liesWithinSingleAppRegion(Addr, Size)) {
72     // FIXME: attempt to dynamically add this as an app region if it
73     // fits our shadow criteria.
74     // We could also try to remap somewhere else.
75     Printf("ERROR: unsupported mapping at [%p-%p)\n", Addr, Addr+Size);
76     Die();
77   }
78   return Addr;
79 }
80
81 } // namespace __esan
82
83 #endif // SANITIZER_FREEBSD || SANITIZER_LINUX