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)MmapFixedNoAccess(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 152