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_errno.h" 20 #include "sanitizer_common/sanitizer_libc.h" 21 #include "sanitizer_common/sanitizer_procmaps.h" 22 #include "tsan_platform.h" 23 #include "tsan_rtl.h" 24 25 namespace __tsan { 26 27 static const char kShadowMemoryMappingWarning[] = 28 "FATAL: %s can not madvise shadow region [%zx, %zx] with %s (errno: %d)\n"; 29 static const char kShadowMemoryMappingHint[] = 30 "HINT: if %s is not supported in your environment, you may set " 31 "TSAN_OPTIONS=%s=0\n"; 32 33 static void NoHugePagesInShadow(uptr addr, uptr size) { 34 if (common_flags()->no_huge_pages_for_shadow) 35 if (!NoHugePagesInRegion(addr, size)) { 36 Printf(kShadowMemoryMappingWarning, SanitizerToolName, addr, addr + size, 37 "MADV_NOHUGEPAGE", errno); 38 Printf(kShadowMemoryMappingHint, "MADV_NOHUGEPAGE", 39 "no_huge_pages_for_shadow"); 40 Die(); 41 } 42 } 43 44 static void DontDumpShadow(uptr addr, uptr size) { 45 if (common_flags()->use_madv_dontdump) 46 if (!DontDumpShadowMemory(addr, size)) { 47 Printf(kShadowMemoryMappingWarning, SanitizerToolName, addr, addr + size, 48 "MADV_DONTDUMP", errno); 49 Printf(kShadowMemoryMappingHint, "MADV_DONTDUMP", "use_madv_dontdump"); 50 Die(); 51 } 52 } 53 54 #if !SANITIZER_GO 55 void InitializeShadowMemory() { 56 // Map memory shadow. 57 if (!MmapFixedNoReserve(ShadowBeg(), ShadowEnd() - ShadowBeg(), "shadow")) { 58 Printf("FATAL: ThreadSanitizer can not mmap the shadow memory\n"); 59 Printf("FATAL: Make sure to compile with -fPIE and to link with -pie.\n"); 60 Die(); 61 } 62 // This memory range is used for thread stacks and large user mmaps. 63 // Frequently a thread uses only a small part of stack and similarly 64 // a program uses a small part of large mmap. On some programs 65 // we see 20% memory usage reduction without huge pages for this range. 66 // FIXME: don't use constants here. 67 #if defined(__x86_64__) 68 const uptr kMadviseRangeBeg = 0x7f0000000000ull; 69 const uptr kMadviseRangeSize = 0x010000000000ull; 70 #elif defined(__mips64) 71 const uptr kMadviseRangeBeg = 0xff00000000ull; 72 const uptr kMadviseRangeSize = 0x0100000000ull; 73 #elif defined(__aarch64__) && defined(__APPLE__) 74 uptr kMadviseRangeBeg = LoAppMemBeg(); 75 uptr kMadviseRangeSize = LoAppMemEnd() - LoAppMemBeg(); 76 #elif defined(__aarch64__) 77 uptr kMadviseRangeBeg = 0; 78 uptr kMadviseRangeSize = 0; 79 if (vmaSize == 39) { 80 kMadviseRangeBeg = 0x7d00000000ull; 81 kMadviseRangeSize = 0x0300000000ull; 82 } else if (vmaSize == 42) { 83 kMadviseRangeBeg = 0x3f000000000ull; 84 kMadviseRangeSize = 0x01000000000ull; 85 } else { 86 DCHECK(0); 87 } 88 #elif defined(__powerpc64__) 89 uptr kMadviseRangeBeg = 0; 90 uptr kMadviseRangeSize = 0; 91 if (vmaSize == 44) { 92 kMadviseRangeBeg = 0x0f60000000ull; 93 kMadviseRangeSize = 0x0010000000ull; 94 } else if (vmaSize == 46) { 95 kMadviseRangeBeg = 0x3f0000000000ull; 96 kMadviseRangeSize = 0x010000000000ull; 97 } else { 98 DCHECK(0); 99 } 100 #endif 101 NoHugePagesInShadow(MemToShadow(kMadviseRangeBeg), 102 kMadviseRangeSize * kShadowMultiplier); 103 DontDumpShadow(ShadowBeg(), ShadowEnd() - ShadowBeg()); 104 DPrintf("memory shadow: %zx-%zx (%zuGB)\n", 105 ShadowBeg(), ShadowEnd(), 106 (ShadowEnd() - ShadowBeg()) >> 30); 107 108 // Map meta shadow. 109 const uptr meta = MetaShadowBeg(); 110 const uptr meta_size = MetaShadowEnd() - meta; 111 if (!MmapFixedNoReserve(meta, meta_size, "meta shadow")) { 112 Printf("FATAL: ThreadSanitizer can not mmap the shadow memory\n"); 113 Printf("FATAL: Make sure to compile with -fPIE and to link with -pie.\n"); 114 Die(); 115 } 116 NoHugePagesInShadow(meta, meta_size); 117 DontDumpShadow(meta, meta_size); 118 DPrintf("meta shadow: %zx-%zx (%zuGB)\n", 119 meta, meta + meta_size, meta_size >> 30); 120 121 InitializeShadowMemoryPlatform(); 122 } 123 124 static void ProtectRange(uptr beg, uptr end) { 125 CHECK_LE(beg, end); 126 if (beg == end) 127 return; 128 if (beg != (uptr)MmapFixedNoAccess(beg, end - beg)) { 129 Printf("FATAL: ThreadSanitizer can not protect [%zx,%zx]\n", beg, end); 130 Printf("FATAL: Make sure you are not using unlimited stack\n"); 131 Die(); 132 } 133 } 134 135 void CheckAndProtect() { 136 // Ensure that the binary is indeed compiled with -pie. 137 MemoryMappingLayout proc_maps(true); 138 MemoryMappedSegment segment; 139 while (proc_maps.Next(&segment)) { 140 if (IsAppMem(segment.start)) continue; 141 if (segment.start >= HeapMemEnd() && segment.start < HeapEnd()) continue; 142 if (segment.protection == 0) // Zero page or mprotected. 143 continue; 144 if (segment.start >= VdsoBeg()) // vdso 145 break; 146 Printf("FATAL: ThreadSanitizer: unexpected memory mapping %p-%p\n", 147 segment.start, segment.end); 148 Die(); 149 } 150 151 #if defined(__aarch64__) && defined(__APPLE__) 152 ProtectRange(HeapMemEnd(), ShadowBeg()); 153 ProtectRange(ShadowEnd(), MetaShadowBeg()); 154 ProtectRange(MetaShadowEnd(), TraceMemBeg()); 155 #else 156 ProtectRange(LoAppMemEnd(), ShadowBeg()); 157 ProtectRange(ShadowEnd(), MetaShadowBeg()); 158 #ifdef TSAN_MID_APP_RANGE 159 ProtectRange(MetaShadowEnd(), MidAppMemBeg()); 160 ProtectRange(MidAppMemEnd(), TraceMemBeg()); 161 #else 162 ProtectRange(MetaShadowEnd(), TraceMemBeg()); 163 #endif 164 // Memory for traces is mapped lazily in MapThreadTrace. 165 // Protect the whole range for now, so that user does not map something here. 166 ProtectRange(TraceMemBeg(), TraceMemEnd()); 167 ProtectRange(TraceMemEnd(), HeapMemBeg()); 168 ProtectRange(HeapEnd(), HiAppMemBeg()); 169 #endif 170 } 171 #endif 172 173 } // namespace __tsan 174 175 #endif // SANITIZER_POSIX 176