Daily bump.
[official-gcc.git] / libsanitizer / tsan / tsan_platform_linux.cc
blob062e84615cc77de475abd494c0d9f22c7d30b5a8
1 //===-- tsan_platform_linux.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 // Linux-specific code.
11 //===----------------------------------------------------------------------===//
14 #include "sanitizer_common/sanitizer_platform.h"
15 #if SANITIZER_LINUX
17 #include "sanitizer_common/sanitizer_common.h"
18 #include "sanitizer_common/sanitizer_libc.h"
19 #include "sanitizer_common/sanitizer_procmaps.h"
20 #include "sanitizer_common/sanitizer_stoptheworld.h"
21 #include "tsan_platform.h"
22 #include "tsan_rtl.h"
23 #include "tsan_flags.h"
25 #include <fcntl.h>
26 #include <pthread.h>
27 #include <signal.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <stdarg.h>
32 #include <sys/mman.h>
33 #include <sys/prctl.h>
34 #include <sys/syscall.h>
35 #include <sys/socket.h>
36 #include <sys/time.h>
37 #include <sys/types.h>
38 #include <sys/resource.h>
39 #include <sys/stat.h>
40 #include <unistd.h>
41 #include <errno.h>
42 #include <sched.h>
43 #include <dlfcn.h>
44 #define __need_res_state
45 #include <resolv.h>
46 #include <malloc.h>
48 #ifdef sa_handler
49 # undef sa_handler
50 #endif
52 #ifdef sa_sigaction
53 # undef sa_sigaction
54 #endif
56 extern "C" struct mallinfo __libc_mallinfo();
58 namespace __tsan {
60 const uptr kPageSize = 4096;
62 void FillProfileCallback(uptr start, uptr rss, bool file,
63 uptr *mem, uptr stats_size) {
64 CHECK_EQ(7, stats_size);
65 mem[6] += rss; // total
66 start >>= 40;
67 if (start < 0x10) // shadow
68 mem[0] += rss;
69 else if (start >= 0x20 && start < 0x30) // compat modules
70 mem[file ? 1 : 2] += rss;
71 else if (start >= 0x7e) // modules
72 mem[file ? 1 : 2] += rss;
73 else if (start >= 0x60 && start < 0x62) // traces
74 mem[3] += rss;
75 else if (start >= 0x7d && start < 0x7e) // heap
76 mem[4] += rss;
77 else // other
78 mem[5] += rss;
81 void WriteMemoryProfile(char *buf, uptr buf_size) {
82 uptr mem[7] = {};
83 __sanitizer::GetMemoryProfile(FillProfileCallback, mem, 7);
84 char *buf_pos = buf;
85 char *buf_end = buf + buf_size;
86 buf_pos += internal_snprintf(buf_pos, buf_end - buf_pos,
87 "RSS %zd MB: shadow:%zd file:%zd mmap:%zd trace:%zd heap:%zd other:%zd\n",
88 mem[6] >> 20, mem[0] >> 20, mem[1] >> 20, mem[2] >> 20,
89 mem[3] >> 20, mem[4] >> 20, mem[5] >> 20);
90 struct mallinfo mi = __libc_mallinfo();
91 buf_pos += internal_snprintf(buf_pos, buf_end - buf_pos,
92 "mallinfo: arena=%d mmap=%d fordblks=%d keepcost=%d\n",
93 mi.arena >> 20, mi.hblkhd >> 20, mi.fordblks >> 20, mi.keepcost >> 20);
96 uptr GetRSS() {
97 uptr mem[7] = {};
98 __sanitizer::GetMemoryProfile(FillProfileCallback, mem, 7);
99 return mem[6];
103 void FlushShadowMemoryCallback(
104 const SuspendedThreadsList &suspended_threads_list,
105 void *argument) {
106 FlushUnneededShadowMemory(kLinuxShadowBeg, kLinuxShadowEnd - kLinuxShadowBeg);
109 void FlushShadowMemory() {
110 StopTheWorld(FlushShadowMemoryCallback, 0);
113 #ifndef TSAN_GO
114 static void ProtectRange(uptr beg, uptr end) {
115 CHECK_LE(beg, end);
116 if (beg == end)
117 return;
118 if (beg != (uptr)Mprotect(beg, end - beg)) {
119 Printf("FATAL: ThreadSanitizer can not protect [%zx,%zx]\n", beg, end);
120 Printf("FATAL: Make sure you are not using unlimited stack\n");
121 Die();
124 #endif
126 #ifndef TSAN_GO
127 // Mark shadow for .rodata sections with the special kShadowRodata marker.
128 // Accesses to .rodata can't race, so this saves time, memory and trace space.
129 static void MapRodata() {
130 // First create temp file.
131 const char *tmpdir = GetEnv("TMPDIR");
132 if (tmpdir == 0)
133 tmpdir = GetEnv("TEST_TMPDIR");
134 #ifdef P_tmpdir
135 if (tmpdir == 0)
136 tmpdir = P_tmpdir;
137 #endif
138 if (tmpdir == 0)
139 return;
140 char name[256];
141 internal_snprintf(name, sizeof(name), "%s/tsan.rodata.%d",
142 tmpdir, (int)internal_getpid());
143 uptr openrv = internal_open(name, O_RDWR | O_CREAT | O_EXCL, 0600);
144 if (internal_iserror(openrv))
145 return;
146 internal_unlink(name); // Unlink it now, so that we can reuse the buffer.
147 fd_t fd = openrv;
148 // Fill the file with kShadowRodata.
149 const uptr kMarkerSize = 512 * 1024 / sizeof(u64);
150 InternalScopedBuffer<u64> marker(kMarkerSize);
151 // volatile to prevent insertion of memset
152 for (volatile u64 *p = marker.data(); p < marker.data() + kMarkerSize; p++)
153 *p = kShadowRodata;
154 internal_write(fd, marker.data(), marker.size());
155 // Map the file into memory.
156 uptr page = internal_mmap(0, kPageSize, PROT_READ | PROT_WRITE,
157 MAP_PRIVATE | MAP_ANONYMOUS, fd, 0);
158 if (internal_iserror(page)) {
159 internal_close(fd);
160 return;
162 // Map the file into shadow of .rodata sections.
163 MemoryMappingLayout proc_maps(/*cache_enabled*/true);
164 uptr start, end, offset, prot;
165 // Reusing the buffer 'name'.
166 while (proc_maps.Next(&start, &end, &offset, name, ARRAY_SIZE(name), &prot)) {
167 if (name[0] != 0 && name[0] != '['
168 && (prot & MemoryMappingLayout::kProtectionRead)
169 && (prot & MemoryMappingLayout::kProtectionExecute)
170 && !(prot & MemoryMappingLayout::kProtectionWrite)
171 && IsAppMem(start)) {
172 // Assume it's .rodata
173 char *shadow_start = (char*)MemToShadow(start);
174 char *shadow_end = (char*)MemToShadow(end);
175 for (char *p = shadow_start; p < shadow_end; p += marker.size()) {
176 internal_mmap(p, Min<uptr>(marker.size(), shadow_end - p),
177 PROT_READ, MAP_PRIVATE | MAP_FIXED, fd, 0);
181 internal_close(fd);
184 void InitializeShadowMemory() {
185 uptr shadow = (uptr)MmapFixedNoReserve(kLinuxShadowBeg,
186 kLinuxShadowEnd - kLinuxShadowBeg);
187 if (shadow != kLinuxShadowBeg) {
188 Printf("FATAL: ThreadSanitizer can not mmap the shadow memory\n");
189 Printf("FATAL: Make sure to compile with -fPIE and "
190 "to link with -pie (%p, %p).\n", shadow, kLinuxShadowBeg);
191 Die();
193 const uptr kClosedLowBeg = 0x200000;
194 const uptr kClosedLowEnd = kLinuxShadowBeg - 1;
195 const uptr kClosedMidBeg = kLinuxShadowEnd + 1;
196 const uptr kClosedMidEnd = min(kLinuxAppMemBeg, kTraceMemBegin);
197 ProtectRange(kClosedLowBeg, kClosedLowEnd);
198 ProtectRange(kClosedMidBeg, kClosedMidEnd);
199 DPrintf("kClosedLow %zx-%zx (%zuGB)\n",
200 kClosedLowBeg, kClosedLowEnd, (kClosedLowEnd - kClosedLowBeg) >> 30);
201 DPrintf("kLinuxShadow %zx-%zx (%zuGB)\n",
202 kLinuxShadowBeg, kLinuxShadowEnd,
203 (kLinuxShadowEnd - kLinuxShadowBeg) >> 30);
204 DPrintf("kClosedMid %zx-%zx (%zuGB)\n",
205 kClosedMidBeg, kClosedMidEnd, (kClosedMidEnd - kClosedMidBeg) >> 30);
206 DPrintf("kLinuxAppMem %zx-%zx (%zuGB)\n",
207 kLinuxAppMemBeg, kLinuxAppMemEnd,
208 (kLinuxAppMemEnd - kLinuxAppMemBeg) >> 30);
209 DPrintf("stack %zx\n", (uptr)&shadow);
211 MapRodata();
213 #endif
215 static uptr g_data_start;
216 static uptr g_data_end;
218 #ifndef TSAN_GO
219 static void CheckPIE() {
220 // Ensure that the binary is indeed compiled with -pie.
221 MemoryMappingLayout proc_maps(true);
222 uptr start, end;
223 if (proc_maps.Next(&start, &end,
224 /*offset*/0, /*filename*/0, /*filename_size*/0,
225 /*protection*/0)) {
226 if ((u64)start < kLinuxAppMemBeg) {
227 Printf("FATAL: ThreadSanitizer can not mmap the shadow memory ("
228 "something is mapped at 0x%zx < 0x%zx)\n",
229 start, kLinuxAppMemBeg);
230 Printf("FATAL: Make sure to compile with -fPIE"
231 " and to link with -pie.\n");
232 Die();
237 static void InitDataSeg() {
238 MemoryMappingLayout proc_maps(true);
239 uptr start, end, offset;
240 char name[128];
241 bool prev_is_data = false;
242 while (proc_maps.Next(&start, &end, &offset, name, ARRAY_SIZE(name),
243 /*protection*/ 0)) {
244 DPrintf("%p-%p %p %s\n", start, end, offset, name);
245 bool is_data = offset != 0 && name[0] != 0;
246 // BSS may get merged with [heap] in /proc/self/maps. This is not very
247 // reliable.
248 bool is_bss = offset == 0 &&
249 (name[0] == 0 || internal_strcmp(name, "[heap]") == 0) && prev_is_data;
250 if (g_data_start == 0 && is_data)
251 g_data_start = start;
252 if (is_bss)
253 g_data_end = end;
254 prev_is_data = is_data;
256 DPrintf("guessed data_start=%p data_end=%p\n", g_data_start, g_data_end);
257 CHECK_LT(g_data_start, g_data_end);
258 CHECK_GE((uptr)&g_data_start, g_data_start);
259 CHECK_LT((uptr)&g_data_start, g_data_end);
262 #endif // #ifndef TSAN_GO
264 static rlim_t getlim(int res) {
265 rlimit rlim;
266 CHECK_EQ(0, getrlimit(res, &rlim));
267 return rlim.rlim_cur;
270 static void setlim(int res, rlim_t lim) {
271 // The following magic is to prevent clang from replacing it with memset.
272 volatile rlimit rlim;
273 rlim.rlim_cur = lim;
274 rlim.rlim_max = lim;
275 setrlimit(res, (rlimit*)&rlim);
278 const char *InitializePlatform() {
279 void *p = 0;
280 if (sizeof(p) == 8) {
281 // Disable core dumps, dumping of 16TB usually takes a bit long.
282 setlim(RLIMIT_CORE, 0);
285 // Go maps shadow memory lazily and works fine with limited address space.
286 // Unlimited stack is not a problem as well, because the executable
287 // is not compiled with -pie.
288 if (kCppMode) {
289 bool reexec = false;
290 // TSan doesn't play well with unlimited stack size (as stack
291 // overlaps with shadow memory). If we detect unlimited stack size,
292 // we re-exec the program with limited stack size as a best effort.
293 if (getlim(RLIMIT_STACK) == (rlim_t)-1) {
294 const uptr kMaxStackSize = 32 * 1024 * 1024;
295 VReport(1, "Program is run with unlimited stack size, which wouldn't "
296 "work with ThreadSanitizer.\n"
297 "Re-execing with stack size limited to %zd bytes.\n",
298 kMaxStackSize);
299 SetStackSizeLimitInBytes(kMaxStackSize);
300 reexec = true;
303 if (getlim(RLIMIT_AS) != (rlim_t)-1) {
304 Report("WARNING: Program is run with limited virtual address space,"
305 " which wouldn't work with ThreadSanitizer.\n");
306 Report("Re-execing with unlimited virtual address space.\n");
307 setlim(RLIMIT_AS, -1);
308 reexec = true;
310 if (reexec)
311 ReExec();
314 #ifndef TSAN_GO
315 CheckPIE();
316 InitTlsSize();
317 InitDataSeg();
318 #endif
319 return GetEnv(kTsanOptionsEnv);
322 bool IsGlobalVar(uptr addr) {
323 return g_data_start && addr >= g_data_start && addr < g_data_end;
326 #ifndef TSAN_GO
327 // Extract file descriptors passed to glibc internal __res_iclose function.
328 // This is required to properly "close" the fds, because we do not see internal
329 // closes within glibc. The code is a pure hack.
330 int ExtractResolvFDs(void *state, int *fds, int nfd) {
331 int cnt = 0;
332 __res_state *statp = (__res_state*)state;
333 for (int i = 0; i < MAXNS && cnt < nfd; i++) {
334 if (statp->_u._ext.nsaddrs[i] && statp->_u._ext.nssocks[i] != -1)
335 fds[cnt++] = statp->_u._ext.nssocks[i];
337 return cnt;
340 // Extract file descriptors passed via UNIX domain sockets.
341 // This is requried to properly handle "open" of these fds.
342 // see 'man recvmsg' and 'man 3 cmsg'.
343 int ExtractRecvmsgFDs(void *msgp, int *fds, int nfd) {
344 int res = 0;
345 msghdr *msg = (msghdr*)msgp;
346 struct cmsghdr *cmsg = CMSG_FIRSTHDR(msg);
347 for (; cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
348 if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS)
349 continue;
350 int n = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(fds[0]);
351 for (int i = 0; i < n; i++) {
352 fds[res++] = ((int*)CMSG_DATA(cmsg))[i];
353 if (res == nfd)
354 return res;
357 return res;
360 int call_pthread_cancel_with_cleanup(int(*fn)(void *c, void *m,
361 void *abstime), void *c, void *m, void *abstime,
362 void(*cleanup)(void *arg), void *arg) {
363 // pthread_cleanup_push/pop are hardcore macros mess.
364 // We can't intercept nor call them w/o including pthread.h.
365 int res;
366 pthread_cleanup_push(cleanup, arg);
367 res = fn(c, m, abstime);
368 pthread_cleanup_pop(0);
369 return res;
371 #endif
373 } // namespace __tsan
375 #endif // SANITIZER_LINUX