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