1 //===-- tsan_platform_posix.cpp -------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file is a part of ThreadSanitizer (TSan), a race detector.
11 // POSIX-specific code.
12 //===----------------------------------------------------------------------===//
14 #include "sanitizer_common/sanitizer_platform.h"
19 # include "sanitizer_common/sanitizer_common.h"
20 # include "sanitizer_common/sanitizer_errno.h"
21 # include "sanitizer_common/sanitizer_libc.h"
22 # include "sanitizer_common/sanitizer_procmaps.h"
23 # include "tsan_platform.h"
24 # include "tsan_rtl.h"
28 static const char kShadowMemoryMappingWarning
[] =
29 "FATAL: %s can not madvise shadow region [%zx, %zx] with %s (errno: %d)\n";
30 static const char kShadowMemoryMappingHint
[] =
31 "HINT: if %s is not supported in your environment, you may set "
32 "TSAN_OPTIONS=%s=0\n";
35 static void DontDumpShadow(uptr addr
, uptr size
) {
36 if (common_flags()->use_madv_dontdump
)
37 if (!DontDumpShadowMemory(addr
, size
)) {
38 Printf(kShadowMemoryMappingWarning
, SanitizerToolName
, addr
, addr
+ size
,
39 "MADV_DONTDUMP", errno
);
40 Printf(kShadowMemoryMappingHint
, "MADV_DONTDUMP", "use_madv_dontdump");
45 void InitializeShadowMemory() {
47 if (!MmapFixedSuperNoReserve(ShadowBeg(), ShadowEnd() - ShadowBeg(),
49 Printf("FATAL: ThreadSanitizer can not mmap the shadow memory\n");
50 Printf("FATAL: Make sure to compile with -fPIE and to link with -pie.\n");
53 // This memory range is used for thread stacks and large user mmaps.
54 // Frequently a thread uses only a small part of stack and similarly
55 // a program uses a small part of large mmap. On some programs
56 // we see 20% memory usage reduction without huge pages for this range.
57 DontDumpShadow(ShadowBeg(), ShadowEnd() - ShadowBeg());
58 DPrintf("memory shadow: %zx-%zx (%zuGB)\n",
59 ShadowBeg(), ShadowEnd(),
60 (ShadowEnd() - ShadowBeg()) >> 30);
63 const uptr meta
= MetaShadowBeg();
64 const uptr meta_size
= MetaShadowEnd() - meta
;
65 if (!MmapFixedSuperNoReserve(meta
, meta_size
, "meta shadow")) {
66 Printf("FATAL: ThreadSanitizer can not mmap the shadow memory\n");
67 Printf("FATAL: Make sure to compile with -fPIE and to link with -pie.\n");
70 DontDumpShadow(meta
, meta_size
);
71 DPrintf("meta shadow: %zx-%zx (%zuGB)\n",
72 meta
, meta
+ meta_size
, meta_size
>> 30);
74 InitializeShadowMemoryPlatform();
76 on_initialize
= reinterpret_cast<void (*)(void)>(
77 dlsym(RTLD_DEFAULT
, "__tsan_on_initialize"));
79 reinterpret_cast<int (*)(int)>(dlsym(RTLD_DEFAULT
, "__tsan_on_finalize"));
82 static bool TryProtectRange(uptr beg
, uptr end
) {
86 return beg
== (uptr
)MmapFixedNoAccess(beg
, end
- beg
);
89 static void ProtectRange(uptr beg
, uptr end
) {
90 if (!TryProtectRange(beg
, end
)) {
91 Printf("FATAL: ThreadSanitizer can not protect [%zx,%zx]\n", beg
, end
);
92 Printf("FATAL: Make sure you are not using unlimited stack\n");
97 void CheckAndProtect() {
98 // Ensure that the binary is indeed compiled with -pie.
99 MemoryMappingLayout
proc_maps(true);
100 MemoryMappedSegment segment
;
101 while (proc_maps
.Next(&segment
)) {
102 if (IsAppMem(segment
.start
)) continue;
103 if (segment
.start
>= HeapMemEnd() && segment
.start
< HeapEnd()) continue;
104 if (segment
.protection
== 0) // Zero page or mprotected.
106 if (segment
.start
>= VdsoBeg()) // vdso
108 Printf("FATAL: ThreadSanitizer: unexpected memory mapping 0x%zx-0x%zx\n",
109 segment
.start
, segment
.end
);
113 # if SANITIZER_IOS && !SANITIZER_IOSSIM
114 ProtectRange(HeapMemEnd(), ShadowBeg());
115 ProtectRange(ShadowEnd(), MetaShadowBeg());
116 ProtectRange(MetaShadowEnd(), HiAppMemBeg());
118 ProtectRange(LoAppMemEnd(), ShadowBeg());
119 ProtectRange(ShadowEnd(), MetaShadowBeg());
120 if (MidAppMemBeg()) {
121 ProtectRange(MetaShadowEnd(), MidAppMemBeg());
122 ProtectRange(MidAppMemEnd(), HeapMemBeg());
124 ProtectRange(MetaShadowEnd(), HeapMemBeg());
126 ProtectRange(HeapEnd(), HiAppMemBeg());
129 # if defined(__s390x__)
130 // Protect the rest of the address space.
131 const uptr user_addr_max_l4
= 0x0020000000000000ull
;
132 const uptr user_addr_max_l5
= 0xfffffffffffff000ull
;
133 // All the maintained s390x kernels support at least 4-level page tables.
134 ProtectRange(HiAppMemEnd(), user_addr_max_l4
);
135 // Older s390x kernels may not support 5-level page tables.
136 TryProtectRange(user_addr_max_l4
, user_addr_max_l5
);
141 } // namespace __tsan
143 #endif // SANITIZER_POSIX