1799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar//===-- tsan_platform_posix.cc --------------------------------------------===// 2799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// 3799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// The LLVM Compiler Infrastructure 4799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// 5799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// This file is distributed under the University of Illinois Open Source 6799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// License. See LICENSE.TXT for details. 7799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// 8799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar//===----------------------------------------------------------------------===// 9799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// 10799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// This file is a part of ThreadSanitizer (TSan), a race detector. 11799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// 12799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar// POSIX-specific code. 13799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar//===----------------------------------------------------------------------===// 14799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 15799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#include "sanitizer_common/sanitizer_platform.h" 16799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#if SANITIZER_POSIX 17799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 18799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#include "sanitizer_common/sanitizer_common.h" 19799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#include "sanitizer_common/sanitizer_libc.h" 20799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#include "sanitizer_common/sanitizer_procmaps.h" 21799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#include "tsan_platform.h" 22799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#include "tsan_rtl.h" 23799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 24799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarnamespace __tsan { 25799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 26799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#ifndef SANITIZER_GO 27799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarvoid InitializeShadowMemory() { 28799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // Map memory shadow. 29799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar uptr shadow = 30799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar (uptr)MmapFixedNoReserve(ShadowBeg(), ShadowEnd() - ShadowBeg(), 31799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar "shadow"); 32799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if (shadow != ShadowBeg()) { 33799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar Printf("FATAL: ThreadSanitizer can not mmap the shadow memory\n"); 34799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar Printf("FATAL: Make sure to compile with -fPIE and " 35799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar "to link with -pie (%p, %p).\n", shadow, ShadowBeg()); 36799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar Die(); 37799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar } 38799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // This memory range is used for thread stacks and large user mmaps. 39799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // Frequently a thread uses only a small part of stack and similarly 40799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // a program uses a small part of large mmap. On some programs 41799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // we see 20% memory usage reduction without huge pages for this range. 42799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // FIXME: don't use constants here. 43799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#if defined(__x86_64__) 44799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar const uptr kMadviseRangeBeg = 0x7f0000000000ull; 45799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar const uptr kMadviseRangeSize = 0x010000000000ull; 46799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#elif defined(__mips64) 47799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar const uptr kMadviseRangeBeg = 0xff00000000ull; 48799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar const uptr kMadviseRangeSize = 0x0100000000ull; 49799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#elif defined(__aarch64__) 50799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar uptr kMadviseRangeBeg = 0; 51799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar uptr kMadviseRangeSize = 0; 52799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if (vmaSize == 39) { 53799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar kMadviseRangeBeg = 0x7d00000000ull; 54799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar kMadviseRangeSize = 0x0300000000ull; 55799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar } else if (vmaSize == 42) { 56799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar kMadviseRangeBeg = 0x3f000000000ull; 57799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar kMadviseRangeSize = 0x01000000000ull; 58799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar } else { 59799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar DCHECK(0); 60799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar } 61799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#elif defined(__powerpc64__) 62799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar uptr kMadviseRangeBeg = 0; 63799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar uptr kMadviseRangeSize = 0; 64799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if (vmaSize == 44) { 65799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar kMadviseRangeBeg = 0x0f60000000ull; 66799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar kMadviseRangeSize = 0x0010000000ull; 67799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar } else if (vmaSize == 46) { 68799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar kMadviseRangeBeg = 0x3f0000000000ull; 69799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar kMadviseRangeSize = 0x010000000000ull; 70799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar } else { 71799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar DCHECK(0); 72799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar } 73799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#endif 74799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar NoHugePagesInRegion(MemToShadow(kMadviseRangeBeg), 75799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar kMadviseRangeSize * kShadowMultiplier); 76799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // Meta shadow is compressing and we don't flush it, 77799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // so it makes sense to mark it as NOHUGEPAGE to not over-allocate memory. 78799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // On one program it reduces memory consumption from 5GB to 2.5GB. 79799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar NoHugePagesInRegion(MetaShadowBeg(), MetaShadowEnd() - MetaShadowBeg()); 80799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if (common_flags()->use_madv_dontdump) 81799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar DontDumpShadowMemory(ShadowBeg(), ShadowEnd() - ShadowBeg()); 82799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar DPrintf("memory shadow: %zx-%zx (%zuGB)\n", 83799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar ShadowBeg(), ShadowEnd(), 84799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar (ShadowEnd() - ShadowBeg()) >> 30); 85799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 86799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // Map meta shadow. 87799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar uptr meta_size = MetaShadowEnd() - MetaShadowBeg(); 88799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar uptr meta = 89799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar (uptr)MmapFixedNoReserve(MetaShadowBeg(), meta_size, "meta shadow"); 90799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if (meta != MetaShadowBeg()) { 91799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar Printf("FATAL: ThreadSanitizer can not mmap the shadow memory\n"); 92799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar Printf("FATAL: Make sure to compile with -fPIE and " 93799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar "to link with -pie (%p, %p).\n", meta, MetaShadowBeg()); 94799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar Die(); 95799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar } 96799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if (common_flags()->use_madv_dontdump) 97799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar DontDumpShadowMemory(meta, meta_size); 98799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar DPrintf("meta shadow: %zx-%zx (%zuGB)\n", 99799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar meta, meta + meta_size, meta_size >> 30); 100799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 101799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar InitializeShadowMemoryPlatform(); 102799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar} 103799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 104799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarstatic void ProtectRange(uptr beg, uptr end) { 105799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar CHECK_LE(beg, end); 106799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if (beg == end) 107799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar return; 108c58a43648cd6121c51a2e795a28e2ef90d7813e6Pirama Arumuga Nainar if (beg != (uptr)MmapFixedNoAccess(beg, end - beg)) { 109799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar Printf("FATAL: ThreadSanitizer can not protect [%zx,%zx]\n", beg, end); 110799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar Printf("FATAL: Make sure you are not using unlimited stack\n"); 111799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar Die(); 112799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar } 113799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar} 114799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 115799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainarvoid CheckAndProtect() { 116799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // Ensure that the binary is indeed compiled with -pie. 117799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar MemoryMappingLayout proc_maps(true); 118799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar uptr p, end, prot; 119799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar while (proc_maps.Next(&p, &end, 0, 0, 0, &prot)) { 120799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if (IsAppMem(p)) 121799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar continue; 122799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if (p >= HeapMemEnd() && 123799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar p < HeapEnd()) 124799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar continue; 125799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if (prot == 0) // Zero page or mprotected. 126799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar continue; 127799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar if (p >= VdsoBeg()) // vdso 128799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar break; 129799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar Printf("FATAL: ThreadSanitizer: unexpected memory mapping %p-%p\n", p, end); 130799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar Die(); 131799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar } 132799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 133799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar ProtectRange(LoAppMemEnd(), ShadowBeg()); 134799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar ProtectRange(ShadowEnd(), MetaShadowBeg()); 135799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#ifdef TSAN_MID_APP_RANGE 136799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar ProtectRange(MetaShadowEnd(), MidAppMemBeg()); 137799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar ProtectRange(MidAppMemEnd(), TraceMemBeg()); 138799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#else 139799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar ProtectRange(MetaShadowEnd(), TraceMemBeg()); 140799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#endif 141799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // Memory for traces is mapped lazily in MapThreadTrace. 142799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar // Protect the whole range for now, so that user does not map something here. 143799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar ProtectRange(TraceMemBeg(), TraceMemEnd()); 144799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar ProtectRange(TraceMemEnd(), HeapMemBeg()); 145799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar ProtectRange(HeapEnd(), HiAppMemBeg()); 146799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar} 147799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#endif 148799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 149799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar} // namespace __tsan 150799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar 151799172d60d32feb1acba1a6867f3a9c39a999e5cPirama Arumuga Nainar#endif // SANITIZER_POSIX 152