Pirama Arumuga Nainar | 799172d | 2016-03-03 15:50:30 -0800 | [diff] [blame^] | 1 | //===-- tsan_platform_posix.cc --------------------------------------------===// |
| 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 ThreadSanitizer (TSan), a race detector. |
| 11 | // |
| 12 | // POSIX-specific code. |
| 13 | //===----------------------------------------------------------------------===// |
| 14 | |
| 15 | #include "sanitizer_common/sanitizer_platform.h" |
| 16 | #if SANITIZER_POSIX |
| 17 | |
| 18 | #include "sanitizer_common/sanitizer_common.h" |
| 19 | #include "sanitizer_common/sanitizer_libc.h" |
| 20 | #include "sanitizer_common/sanitizer_procmaps.h" |
| 21 | #include "tsan_platform.h" |
| 22 | #include "tsan_rtl.h" |
| 23 | |
| 24 | namespace __tsan { |
| 25 | |
| 26 | #ifndef SANITIZER_GO |
| 27 | void InitializeShadowMemory() { |
| 28 | // Map memory shadow. |
| 29 | uptr shadow = |
| 30 | (uptr)MmapFixedNoReserve(ShadowBeg(), ShadowEnd() - ShadowBeg(), |
| 31 | "shadow"); |
| 32 | if (shadow != ShadowBeg()) { |
| 33 | Printf("FATAL: ThreadSanitizer can not mmap the shadow memory\n"); |
| 34 | Printf("FATAL: Make sure to compile with -fPIE and " |
| 35 | "to link with -pie (%p, %p).\n", shadow, ShadowBeg()); |
| 36 | Die(); |
| 37 | } |
| 38 | // This memory range is used for thread stacks and large user mmaps. |
| 39 | // Frequently a thread uses only a small part of stack and similarly |
| 40 | // a program uses a small part of large mmap. On some programs |
| 41 | // we see 20% memory usage reduction without huge pages for this range. |
| 42 | // FIXME: don't use constants here. |
| 43 | #if defined(__x86_64__) |
| 44 | const uptr kMadviseRangeBeg = 0x7f0000000000ull; |
| 45 | const uptr kMadviseRangeSize = 0x010000000000ull; |
| 46 | #elif defined(__mips64) |
| 47 | const uptr kMadviseRangeBeg = 0xff00000000ull; |
| 48 | const uptr kMadviseRangeSize = 0x0100000000ull; |
| 49 | #elif defined(__aarch64__) |
| 50 | uptr kMadviseRangeBeg = 0; |
| 51 | uptr kMadviseRangeSize = 0; |
| 52 | if (vmaSize == 39) { |
| 53 | kMadviseRangeBeg = 0x7d00000000ull; |
| 54 | kMadviseRangeSize = 0x0300000000ull; |
| 55 | } else if (vmaSize == 42) { |
| 56 | kMadviseRangeBeg = 0x3f000000000ull; |
| 57 | kMadviseRangeSize = 0x01000000000ull; |
| 58 | } else { |
| 59 | DCHECK(0); |
| 60 | } |
| 61 | #elif defined(__powerpc64__) |
| 62 | uptr kMadviseRangeBeg = 0; |
| 63 | uptr kMadviseRangeSize = 0; |
| 64 | if (vmaSize == 44) { |
| 65 | kMadviseRangeBeg = 0x0f60000000ull; |
| 66 | kMadviseRangeSize = 0x0010000000ull; |
| 67 | } else if (vmaSize == 46) { |
| 68 | kMadviseRangeBeg = 0x3f0000000000ull; |
| 69 | kMadviseRangeSize = 0x010000000000ull; |
| 70 | } else { |
| 71 | DCHECK(0); |
| 72 | } |
| 73 | #endif |
| 74 | NoHugePagesInRegion(MemToShadow(kMadviseRangeBeg), |
| 75 | kMadviseRangeSize * kShadowMultiplier); |
| 76 | // Meta shadow is compressing and we don't flush it, |
| 77 | // so it makes sense to mark it as NOHUGEPAGE to not over-allocate memory. |
| 78 | // On one program it reduces memory consumption from 5GB to 2.5GB. |
| 79 | NoHugePagesInRegion(MetaShadowBeg(), MetaShadowEnd() - MetaShadowBeg()); |
| 80 | if (common_flags()->use_madv_dontdump) |
| 81 | DontDumpShadowMemory(ShadowBeg(), ShadowEnd() - ShadowBeg()); |
| 82 | DPrintf("memory shadow: %zx-%zx (%zuGB)\n", |
| 83 | ShadowBeg(), ShadowEnd(), |
| 84 | (ShadowEnd() - ShadowBeg()) >> 30); |
| 85 | |
| 86 | // Map meta shadow. |
| 87 | uptr meta_size = MetaShadowEnd() - MetaShadowBeg(); |
| 88 | uptr meta = |
| 89 | (uptr)MmapFixedNoReserve(MetaShadowBeg(), meta_size, "meta shadow"); |
| 90 | if (meta != MetaShadowBeg()) { |
| 91 | Printf("FATAL: ThreadSanitizer can not mmap the shadow memory\n"); |
| 92 | Printf("FATAL: Make sure to compile with -fPIE and " |
| 93 | "to link with -pie (%p, %p).\n", meta, MetaShadowBeg()); |
| 94 | Die(); |
| 95 | } |
| 96 | if (common_flags()->use_madv_dontdump) |
| 97 | DontDumpShadowMemory(meta, meta_size); |
| 98 | DPrintf("meta shadow: %zx-%zx (%zuGB)\n", |
| 99 | meta, meta + meta_size, meta_size >> 30); |
| 100 | |
| 101 | InitializeShadowMemoryPlatform(); |
| 102 | } |
| 103 | |
| 104 | static void ProtectRange(uptr beg, uptr end) { |
| 105 | CHECK_LE(beg, end); |
| 106 | if (beg == end) |
| 107 | return; |
| 108 | if (beg != (uptr)MmapNoAccess(beg, end - beg)) { |
| 109 | Printf("FATAL: ThreadSanitizer can not protect [%zx,%zx]\n", beg, end); |
| 110 | Printf("FATAL: Make sure you are not using unlimited stack\n"); |
| 111 | Die(); |
| 112 | } |
| 113 | } |
| 114 | |
| 115 | void CheckAndProtect() { |
| 116 | // Ensure that the binary is indeed compiled with -pie. |
| 117 | MemoryMappingLayout proc_maps(true); |
| 118 | uptr p, end, prot; |
| 119 | while (proc_maps.Next(&p, &end, 0, 0, 0, &prot)) { |
| 120 | if (IsAppMem(p)) |
| 121 | continue; |
| 122 | if (p >= HeapMemEnd() && |
| 123 | p < HeapEnd()) |
| 124 | continue; |
| 125 | if (prot == 0) // Zero page or mprotected. |
| 126 | continue; |
| 127 | if (p >= VdsoBeg()) // vdso |
| 128 | break; |
| 129 | Printf("FATAL: ThreadSanitizer: unexpected memory mapping %p-%p\n", p, end); |
| 130 | Die(); |
| 131 | } |
| 132 | |
| 133 | ProtectRange(LoAppMemEnd(), ShadowBeg()); |
| 134 | ProtectRange(ShadowEnd(), MetaShadowBeg()); |
| 135 | #ifdef TSAN_MID_APP_RANGE |
| 136 | ProtectRange(MetaShadowEnd(), MidAppMemBeg()); |
| 137 | ProtectRange(MidAppMemEnd(), TraceMemBeg()); |
| 138 | #else |
| 139 | ProtectRange(MetaShadowEnd(), TraceMemBeg()); |
| 140 | #endif |
| 141 | // Memory for traces is mapped lazily in MapThreadTrace. |
| 142 | // Protect the whole range for now, so that user does not map something here. |
| 143 | ProtectRange(TraceMemBeg(), TraceMemEnd()); |
| 144 | ProtectRange(TraceMemEnd(), HeapMemBeg()); |
| 145 | ProtectRange(HeapEnd(), HiAppMemBeg()); |
| 146 | } |
| 147 | #endif |
| 148 | |
| 149 | } // namespace __tsan |
| 150 | |
| 151 | #endif // SANITIZER_POSIX |