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