Skip to content

Commit 4bf9b56

Browse files
committed
[TSan] Fix madvise(MADV_NOHUGEPAGE) for meta shadow memory
Summary: Move madvise(MADV_NOHUGEPAGE) for the meta shadow memory after the meta shadow memory is mapped (currently it silently fails with ENOMEM). Add a diagnostic message to detect similar problems in the future. Reviewers: dvyukov Subscribers: kubamracek, delcypher, #sanitizers, llvm-commits Differential Revision: https://reviews.llvm.org/D48097 llvm-svn: 334624
1 parent 9fd634d commit 4bf9b56

File tree

4 files changed

+40
-18
lines changed

4 files changed

+40
-18
lines changed

compiler-rt/lib/sanitizer_common/sanitizer_common.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,8 @@ void ReleaseMemoryPagesToOS(uptr beg, uptr end);
120120
void IncreaseTotalMmap(uptr size);
121121
void DecreaseTotalMmap(uptr size);
122122
uptr GetRSS();
123-
void NoHugePagesInRegion(uptr addr, uptr length);
124-
void DontDumpShadowMemory(uptr addr, uptr length);
123+
bool NoHugePagesInRegion(uptr addr, uptr length);
124+
bool DontDumpShadowMemory(uptr addr, uptr length);
125125
// Check if the built VMA size matches the runtime one.
126126
void CheckVMASize();
127127
void RunMallocHooks(const void *ptr, uptr size);

compiler-rt/lib/sanitizer_common/sanitizer_posix_libcdep.cc

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -69,16 +69,20 @@ void ReleaseMemoryPagesToOS(uptr beg, uptr end) {
6969
SANITIZER_MADVISE_DONTNEED);
7070
}
7171

72-
void NoHugePagesInRegion(uptr addr, uptr size) {
72+
bool NoHugePagesInRegion(uptr addr, uptr size) {
7373
#ifdef MADV_NOHUGEPAGE // May not be defined on old systems.
74-
madvise((void *)addr, size, MADV_NOHUGEPAGE);
74+
return madvise((void *)addr, size, MADV_NOHUGEPAGE) == 0;
75+
#else
76+
return true;
7577
#endif // MADV_NOHUGEPAGE
7678
}
7779

78-
void DontDumpShadowMemory(uptr addr, uptr length) {
80+
bool DontDumpShadowMemory(uptr addr, uptr length) {
7981
#ifdef MADV_DONTDUMP
80-
madvise((void *)addr, length, MADV_DONTDUMP);
81-
#endif
82+
return madvise((void *)addr, length, MADV_DONTDUMP) == 0;
83+
#else
84+
return true;
85+
#endif // MADV_DONTDUMP
8286
}
8387

8488
static rlim_t getlim(int res) {

compiler-rt/lib/sanitizer_common/sanitizer_win.cc

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -311,13 +311,15 @@ void ReleaseMemoryPagesToOS(uptr beg, uptr end) {
311311
// FIXME: add madvise-analog when we move to 64-bits.
312312
}
313313

314-
void NoHugePagesInRegion(uptr addr, uptr size) {
314+
bool NoHugePagesInRegion(uptr addr, uptr size) {
315315
// FIXME: probably similar to ReleaseMemoryToOS.
316+
return true;
316317
}
317318

318-
void DontDumpShadowMemory(uptr addr, uptr length) {
319+
bool DontDumpShadowMemory(uptr addr, uptr length) {
319320
// This is almost useless on 32-bits.
320321
// FIXME: add madvise-analog when we move to 64-bits.
322+
return true;
321323
}
322324

323325
uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding,

compiler-rt/lib/tsan/rtl/tsan_platform_posix.cc

Lines changed: 25 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,27 @@
2323

2424
namespace __tsan {
2525

26+
static const char kShadowMemoryMappingWarning[] =
27+
"FATAL: %s can not madvise shadow region [%zx, %zx] with %s\n";
28+
29+
static void NoHugePagesInShadow(uptr addr, uptr size) {
30+
if (common_flags()->no_huge_pages_for_shadow)
31+
if (!NoHugePagesInRegion(addr, size)) {
32+
Printf(kShadowMemoryMappingWarning, SanitizerToolName, addr, addr + size,
33+
"MADV_NOHUGEPAGE");
34+
Die();
35+
}
36+
}
37+
38+
static void DontDumpShadow(uptr addr, uptr size) {
39+
if (common_flags()->use_madv_dontdump)
40+
if (!DontDumpShadowMemory(addr, size)) {
41+
Printf(kShadowMemoryMappingWarning, SanitizerToolName, addr, addr + size,
42+
"MADV_DONTDUMP");
43+
Die();
44+
}
45+
}
46+
2647
#if !SANITIZER_GO
2748
void InitializeShadowMemory() {
2849
// Map memory shadow.
@@ -74,14 +95,9 @@ void InitializeShadowMemory() {
7495
DCHECK(0);
7596
}
7697
#endif
77-
NoHugePagesInRegion(MemToShadow(kMadviseRangeBeg),
98+
NoHugePagesInShadow(MemToShadow(kMadviseRangeBeg),
7899
kMadviseRangeSize * kShadowMultiplier);
79-
// Meta shadow is compressing and we don't flush it,
80-
// so it makes sense to mark it as NOHUGEPAGE to not over-allocate memory.
81-
// On one program it reduces memory consumption from 5GB to 2.5GB.
82-
NoHugePagesInRegion(MetaShadowBeg(), MetaShadowEnd() - MetaShadowBeg());
83-
if (common_flags()->use_madv_dontdump)
84-
DontDumpShadowMemory(ShadowBeg(), ShadowEnd() - ShadowBeg());
100+
DontDumpShadow(ShadowBeg(), ShadowEnd() - ShadowBeg());
85101
DPrintf("memory shadow: %zx-%zx (%zuGB)\n",
86102
ShadowBeg(), ShadowEnd(),
87103
(ShadowEnd() - ShadowBeg()) >> 30);
@@ -96,8 +112,8 @@ void InitializeShadowMemory() {
96112
"to link with -pie (%p, %p).\n", meta, MetaShadowBeg());
97113
Die();
98114
}
99-
if (common_flags()->use_madv_dontdump)
100-
DontDumpShadowMemory(meta, meta_size);
115+
NoHugePagesInShadow(meta, meta_size);
116+
DontDumpShadow(meta, meta_size);
101117
DPrintf("meta shadow: %zx-%zx (%zuGB)\n",
102118
meta, meta + meta_size, meta_size >> 30);
103119

0 commit comments

Comments
 (0)