xref: /netbsd-src/external/gpl3/gcc.old/dist/libsanitizer/tsan/tsan_platform_posix.cc (revision b2c35e17b976cf7ccd7250c86c6f5e95090ed636)
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 
23 namespace __tsan {
24 
25 static const char kShadowMemoryMappingWarning[] =
26     "FATAL: %s can not madvise shadow region [%zx, %zx] with %s (errno: %d)\n";
27 static const char kShadowMemoryMappingHint[] =
28     "HINT: if %s is not supported in your environment, you may set "
29     "TSAN_OPTIONS=%s=0\n";
30 
31 static 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 
42 static 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
53 void 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 
122 static 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 
133 void 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