1 //===-- tsan_platform_linux.cc --------------------------------------------===//
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
6 //===----------------------------------------------------------------------===//
8 // This file is a part of ThreadSanitizer (TSan), a race detector.
10 // Linux- and FreeBSD-specific code.
11 //===----------------------------------------------------------------------===//
14 #include "sanitizer_common/sanitizer_platform.h"
15 #if SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD
17 #include "sanitizer_common/sanitizer_common.h"
18 #include "sanitizer_common/sanitizer_libc.h"
19 #include "sanitizer_common/sanitizer_linux.h"
20 #include "sanitizer_common/sanitizer_platform_limits_netbsd.h"
21 #include "sanitizer_common/sanitizer_platform_limits_posix.h"
22 #include "sanitizer_common/sanitizer_posix.h"
23 #include "sanitizer_common/sanitizer_procmaps.h"
24 #include "sanitizer_common/sanitizer_stoptheworld.h"
25 #include "sanitizer_common/sanitizer_stackdepot.h"
26 #include "tsan_platform.h"
28 #include "tsan_flags.h"
39 #include <sys/personality.h>
42 #include <sys/syscall.h>
43 #include <sys/socket.h>
45 #include <sys/types.h>
46 #include <sys/resource.h>
52 #define __need_res_state
65 extern "C" void *__libc_stack_end
;
66 void *__libc_stack_end
= 0;
69 #if SANITIZER_LINUX && defined(__aarch64__)
70 void InitializeGuardPtr() __attribute__((visibility("hidden")));
75 #ifdef TSAN_RUNTIME_VMA
76 // Runtime detected VMA size.
92 void FillProfileCallback(uptr p
, uptr rss
, bool file
,
93 uptr
*mem
, uptr stats_size
) {
95 if (p
>= ShadowBeg() && p
< ShadowEnd())
96 mem
[MemShadow
] += rss
;
97 else if (p
>= MetaShadowBeg() && p
< MetaShadowEnd())
100 else if (p
>= HeapMemBeg() && p
< HeapMemEnd())
102 else if (p
>= LoAppMemBeg() && p
< LoAppMemEnd())
103 mem
[file
? MemFile
: MemMmap
] += rss
;
104 else if (p
>= HiAppMemBeg() && p
< HiAppMemEnd())
105 mem
[file
? MemFile
: MemMmap
] += rss
;
107 else if (p
>= AppMemBeg() && p
< AppMemEnd())
108 mem
[file
? MemFile
: MemMmap
] += rss
;
110 else if (p
>= TraceMemBeg() && p
< TraceMemEnd())
111 mem
[MemTrace
] += rss
;
113 mem
[MemOther
] += rss
;
116 void WriteMemoryProfile(char *buf
, uptr buf_size
, uptr nthread
, uptr nlive
) {
118 internal_memset(mem
, 0, sizeof(mem
[0]) * MemCount
);
119 __sanitizer::GetMemoryProfile(FillProfileCallback
, mem
, 7);
120 StackDepotStats
*stacks
= StackDepotGetStats();
121 internal_snprintf(buf
, buf_size
,
122 "RSS %zd MB: shadow:%zd meta:%zd file:%zd mmap:%zd"
123 " trace:%zd heap:%zd other:%zd stacks=%zd[%zd] nthr=%zd/%zd\n",
124 mem
[MemTotal
] >> 20, mem
[MemShadow
] >> 20, mem
[MemMeta
] >> 20,
125 mem
[MemFile
] >> 20, mem
[MemMmap
] >> 20, mem
[MemTrace
] >> 20,
126 mem
[MemHeap
] >> 20, mem
[MemOther
] >> 20,
127 stacks
->allocated
>> 20, stacks
->n_uniq_ids
,
132 void FlushShadowMemoryCallback(
133 const SuspendedThreadsList
&suspended_threads_list
,
135 ReleaseMemoryPagesToOS(ShadowBeg(), ShadowEnd());
139 void FlushShadowMemory() {
141 StopTheWorld(FlushShadowMemoryCallback
, 0);
146 // Mark shadow for .rodata sections with the special kShadowRodata marker.
147 // Accesses to .rodata can't race, so this saves time, memory and trace space.
148 static void MapRodata() {
149 // First create temp file.
150 const char *tmpdir
= GetEnv("TMPDIR");
152 tmpdir
= GetEnv("TEST_TMPDIR");
160 internal_snprintf(name
, sizeof(name
), "%s/tsan.rodata.%d",
161 tmpdir
, (int)internal_getpid());
162 uptr openrv
= internal_open(name
, O_RDWR
| O_CREAT
| O_EXCL
, 0600);
163 if (internal_iserror(openrv
))
165 internal_unlink(name
); // Unlink it now, so that we can reuse the buffer.
167 // Fill the file with kShadowRodata.
168 const uptr kMarkerSize
= 512 * 1024 / sizeof(u64
);
169 InternalMmapVector
<u64
> marker(kMarkerSize
);
170 // volatile to prevent insertion of memset
171 for (volatile u64
*p
= marker
.data(); p
< marker
.data() + kMarkerSize
; p
++)
173 internal_write(fd
, marker
.data(), marker
.size() * sizeof(u64
));
174 // Map the file into memory.
175 uptr page
= internal_mmap(0, GetPageSizeCached(), PROT_READ
| PROT_WRITE
,
176 MAP_PRIVATE
| MAP_ANONYMOUS
, fd
, 0);
177 if (internal_iserror(page
)) {
181 // Map the file into shadow of .rodata sections.
182 MemoryMappingLayout
proc_maps(/*cache_enabled*/true);
183 // Reusing the buffer 'name'.
184 MemoryMappedSegment
segment(name
, ARRAY_SIZE(name
));
185 while (proc_maps
.Next(&segment
)) {
186 if (segment
.filename
[0] != 0 && segment
.filename
[0] != '[' &&
187 segment
.IsReadable() && segment
.IsExecutable() &&
188 !segment
.IsWritable() && IsAppMem(segment
.start
)) {
189 // Assume it's .rodata
190 char *shadow_start
= (char *)MemToShadow(segment
.start
);
191 char *shadow_end
= (char *)MemToShadow(segment
.end
);
192 for (char *p
= shadow_start
; p
< shadow_end
;
193 p
+= marker
.size() * sizeof(u64
)) {
194 internal_mmap(p
, Min
<uptr
>(marker
.size() * sizeof(u64
), shadow_end
- p
),
195 PROT_READ
, MAP_PRIVATE
| MAP_FIXED
, fd
, 0);
202 void InitializeShadowMemoryPlatform() {
206 #endif // #if !SANITIZER_GO
208 void InitializePlatformEarly() {
209 #ifdef TSAN_RUNTIME_VMA
211 (MostSignificantSetBitIndex(GET_CURRENT_FRAME()) + 1);
212 #if defined(__aarch64__)
214 if (vmaSize
!= 39 && vmaSize
!= 42 && vmaSize
!= 48) {
215 Printf("FATAL: ThreadSanitizer: unsupported VMA range\n");
216 Printf("FATAL: Found %zd - Supported 39, 42 and 48\n", vmaSize
);
221 Printf("FATAL: ThreadSanitizer: unsupported VMA range\n");
222 Printf("FATAL: Found %zd - Supported 48\n", vmaSize
);
226 #elif defined(__powerpc64__)
228 if (vmaSize
!= 44 && vmaSize
!= 46 && vmaSize
!= 47) {
229 Printf("FATAL: ThreadSanitizer: unsupported VMA range\n");
230 Printf("FATAL: Found %zd - Supported 44, 46, and 47\n", vmaSize
);
234 if (vmaSize
!= 46 && vmaSize
!= 47) {
235 Printf("FATAL: ThreadSanitizer: unsupported VMA range\n");
236 Printf("FATAL: Found %zd - Supported 46, and 47\n", vmaSize
);
244 void InitializePlatform() {
245 DisableCoreDumperIfNecessary();
247 // Go maps shadow memory lazily and works fine with limited address space.
248 // Unlimited stack is not a problem as well, because the executable
249 // is not compiled with -pie.
252 // TSan doesn't play well with unlimited stack size (as stack
253 // overlaps with shadow memory). If we detect unlimited stack size,
254 // we re-exec the program with limited stack size as a best effort.
255 if (StackSizeIsUnlimited()) {
256 const uptr kMaxStackSize
= 32 * 1024 * 1024;
257 VReport(1, "Program is run with unlimited stack size, which wouldn't "
258 "work with ThreadSanitizer.\n"
259 "Re-execing with stack size limited to %zd bytes.\n",
261 SetStackSizeLimitInBytes(kMaxStackSize
);
265 if (!AddressSpaceIsUnlimited()) {
266 Report("WARNING: Program is run with limited virtual address space,"
267 " which wouldn't work with ThreadSanitizer.\n");
268 Report("Re-execing with unlimited virtual address space.\n");
269 SetAddressSpaceUnlimited();
272 #if SANITIZER_LINUX && defined(__aarch64__)
273 // After patch "arm64: mm: support ARCH_MMAP_RND_BITS." is introduced in
274 // linux kernel, the random gap between stack and mapped area is increased
275 // from 128M to 36G on 39-bit aarch64. As it is almost impossible to cover
276 // this big range, we should disable randomized virtual space on aarch64.
277 int old_personality
= personality(0xffffffff);
278 if (old_personality
!= -1 && (old_personality
& ADDR_NO_RANDOMIZE
) == 0) {
279 VReport(1, "WARNING: Program is run with randomized virtual address "
280 "space, which wouldn't work with ThreadSanitizer.\n"
281 "Re-execing with fixed virtual address space.\n");
282 CHECK_NE(personality(old_personality
| ADDR_NO_RANDOMIZE
), -1);
285 // Initialize the guard pointer used in {sig}{set,long}jump.
286 InitializeGuardPtr();
299 // Extract file descriptors passed to glibc internal __res_iclose function.
300 // This is required to properly "close" the fds, because we do not see internal
301 // closes within glibc. The code is a pure hack.
302 int ExtractResolvFDs(void *state
, int *fds
, int nfd
) {
303 #if SANITIZER_LINUX && !SANITIZER_ANDROID
305 struct __res_state
*statp
= (struct __res_state
*)state
;
306 for (int i
= 0; i
< MAXNS
&& cnt
< nfd
; i
++) {
307 if (statp
->_u
._ext
.nsaddrs
[i
] && statp
->_u
._ext
.nssocks
[i
] != -1)
308 fds
[cnt
++] = statp
->_u
._ext
.nssocks
[i
];
316 // Extract file descriptors passed via UNIX domain sockets.
317 // This is requried to properly handle "open" of these fds.
318 // see 'man recvmsg' and 'man 3 cmsg'.
319 int ExtractRecvmsgFDs(void *msgp
, int *fds
, int nfd
) {
321 msghdr
*msg
= (msghdr
*)msgp
;
322 struct cmsghdr
*cmsg
= CMSG_FIRSTHDR(msg
);
323 for (; cmsg
; cmsg
= CMSG_NXTHDR(msg
, cmsg
)) {
324 if (cmsg
->cmsg_level
!= SOL_SOCKET
|| cmsg
->cmsg_type
!= SCM_RIGHTS
)
326 int n
= (cmsg
->cmsg_len
- CMSG_LEN(0)) / sizeof(fds
[0]);
327 for (int i
= 0; i
< n
; i
++) {
328 fds
[res
++] = ((int*)CMSG_DATA(cmsg
))[i
];
336 void ImitateTlsWrite(ThreadState
*thr
, uptr tls_addr
, uptr tls_size
) {
337 // Check that the thr object is in tls;
338 const uptr thr_beg
= (uptr
)thr
;
339 const uptr thr_end
= (uptr
)thr
+ sizeof(*thr
);
340 CHECK_GE(thr_beg
, tls_addr
);
341 CHECK_LE(thr_beg
, tls_addr
+ tls_size
);
342 CHECK_GE(thr_end
, tls_addr
);
343 CHECK_LE(thr_end
, tls_addr
+ tls_size
);
344 // Since the thr object is huge, skip it.
345 MemoryRangeImitateWrite(thr
, /*pc=*/2, tls_addr
, thr_beg
- tls_addr
);
346 MemoryRangeImitateWrite(thr
, /*pc=*/2, thr_end
,
347 tls_addr
+ tls_size
- thr_end
);
350 // Note: this function runs with async signals enabled,
351 // so it must not touch any tsan state.
352 int call_pthread_cancel_with_cleanup(int(*fn
)(void *c
, void *m
,
353 void *abstime
), void *c
, void *m
, void *abstime
,
354 void(*cleanup
)(void *arg
), void *arg
) {
355 // pthread_cleanup_push/pop are hardcore macros mess.
356 // We can't intercept nor call them w/o including pthread.h.
358 pthread_cleanup_push(cleanup
, arg
);
359 res
= fn(c
, m
, abstime
);
360 pthread_cleanup_pop(0);
366 void ReplaceSystemMalloc() { }
370 #if SANITIZER_ANDROID
371 // On Android, one thread can call intercepted functions after
372 // DestroyThreadState(), so add a fake thread state for "dead" threads.
373 static ThreadState
*dead_thread_state
= nullptr;
375 ThreadState
*cur_thread() {
376 ThreadState
* thr
= reinterpret_cast<ThreadState
*>(*get_android_tls_ptr());
377 if (thr
== nullptr) {
378 __sanitizer_sigset_t emptyset
;
379 internal_sigfillset(&emptyset
);
380 __sanitizer_sigset_t oldset
;
381 CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK
, &emptyset
, &oldset
));
382 thr
= reinterpret_cast<ThreadState
*>(*get_android_tls_ptr());
383 if (thr
== nullptr) {
384 thr
= reinterpret_cast<ThreadState
*>(MmapOrDie(sizeof(ThreadState
),
386 *get_android_tls_ptr() = reinterpret_cast<uptr
>(thr
);
387 if (dead_thread_state
== nullptr) {
388 dead_thread_state
= reinterpret_cast<ThreadState
*>(
389 MmapOrDie(sizeof(ThreadState
), "ThreadState"));
390 dead_thread_state
->fast_state
.SetIgnoreBit();
391 dead_thread_state
->ignore_interceptors
= 1;
392 dead_thread_state
->is_dead
= true;
393 *const_cast<int*>(&dead_thread_state
->tid
) = -1;
394 CHECK_EQ(0, internal_mprotect(dead_thread_state
, sizeof(ThreadState
),
398 CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK
, &oldset
, nullptr));
403 void cur_thread_finalize() {
404 __sanitizer_sigset_t emptyset
;
405 internal_sigfillset(&emptyset
);
406 __sanitizer_sigset_t oldset
;
407 CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK
, &emptyset
, &oldset
));
408 ThreadState
* thr
= reinterpret_cast<ThreadState
*>(*get_android_tls_ptr());
409 if (thr
!= dead_thread_state
) {
410 *get_android_tls_ptr() = reinterpret_cast<uptr
>(dead_thread_state
);
411 UnmapOrDie(thr
, sizeof(ThreadState
));
413 CHECK_EQ(0, internal_sigprocmask(SIG_SETMASK
, &oldset
, nullptr));
415 #endif // SANITIZER_ANDROID
416 #endif // if !SANITIZER_GO
418 } // namespace __tsan
420 #endif // SANITIZER_LINUX || SANITIZER_FREEBSD || SANITIZER_NETBSD