Skip to content

Commit cc07fbe

Browse files
Release pages to OS when setting 0 label
This is a follow up patch of https://reviews.llvm.org/D88755. When set 0 label for an address range, we can release pages within the corresponding shadow address range to OS, and set only addresses outside the pages to be 0. Reviewed-by: morehouse, eugenis Differential Revision: https://reviews.llvm.org/D89199
1 parent 2e58010 commit cc07fbe

File tree

2 files changed

+40
-16
lines changed

2 files changed

+40
-16
lines changed

compiler-rt/lib/dfsan/dfsan.cpp

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -274,9 +274,10 @@ dfsan_label dfsan_create_label(const char *desc, void *userdata) {
274274
return label;
275275
}
276276

277-
extern "C" SANITIZER_INTERFACE_ATTRIBUTE
278-
void __dfsan_set_label(dfsan_label label, void *addr, uptr size) {
279-
for (dfsan_label *labelp = shadow_for(addr); size != 0; --size, ++labelp) {
277+
static void WriteShadowIfDifferent(dfsan_label label, uptr shadow_addr,
278+
uptr size) {
279+
dfsan_label *labelp = (dfsan_label *)shadow_addr;
280+
for (; size != 0; --size, ++labelp) {
280281
// Don't write the label if it is already the value we need it to be.
281282
// In a program where most addresses are not labeled, it is common that
282283
// a page of shadow memory is entirely zeroed. The Linux copy-on-write
@@ -292,6 +293,38 @@ void __dfsan_set_label(dfsan_label label, void *addr, uptr size) {
292293
}
293294
}
294295

296+
extern "C" SANITIZER_INTERFACE_ATTRIBUTE void __dfsan_set_label(
297+
dfsan_label label, void *addr, uptr size) {
298+
const uptr beg_shadow_addr = (uptr)__dfsan::shadow_for(addr);
299+
300+
if (0 != label) {
301+
WriteShadowIfDifferent(label, beg_shadow_addr, size);
302+
return;
303+
}
304+
305+
// If label is 0, releases the pages within the shadow address range, and sets
306+
// the shadow addresses not on the pages to be 0.
307+
const void *end_addr = (void *)((uptr)addr + size);
308+
const uptr end_shadow_addr = (uptr)__dfsan::shadow_for(end_addr);
309+
const uptr page_size = GetPageSizeCached();
310+
const uptr beg_aligned = RoundUpTo(beg_shadow_addr, page_size);
311+
const uptr end_aligned = RoundDownTo(end_shadow_addr, page_size);
312+
313+
// dfsan_set_label can be called from the following cases
314+
// 1) mapped ranges by new/delete and malloc/free. This case has shadow memory
315+
// size > 100k, and happens less frequently.
316+
// 2) zero-filling internal data structures by utility libraries. This case
317+
// has shadow memory size < 32k, and happens more often.
318+
// Set kNumPagesThreshold to be 8 to avoid releasing small pages.
319+
const int kNumPagesThreshold = 8;
320+
if (beg_aligned + kNumPagesThreshold * page_size >= end_aligned)
321+
return WriteShadowIfDifferent(label, beg_shadow_addr, size);
322+
323+
WriteShadowIfDifferent(label, beg_shadow_addr, beg_aligned - beg_shadow_addr);
324+
ReleaseMemoryPagesToOS(beg_aligned, end_aligned);
325+
WriteShadowIfDifferent(label, end_aligned, end_shadow_addr - end_aligned);
326+
}
327+
295328
SANITIZER_INTERFACE_ATTRIBUTE
296329
void dfsan_set_label(dfsan_label label, void *addr, uptr size) {
297330
__dfsan_set_label(label, addr, size);

compiler-rt/lib/dfsan/dfsan_interceptors.cpp

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,6 @@ namespace {
2424

2525
bool interceptors_initialized;
2626

27-
void ReleaseShadowMemoryPagesToOS(void *addr, SIZE_T length) {
28-
uptr beg_shadow_addr = (uptr)__dfsan::shadow_for(addr);
29-
void *end_addr =
30-
(void *)((uptr)addr + RoundUpTo(length, GetPageSizeCached()));
31-
uptr end_shadow_addr = (uptr)__dfsan::shadow_for(end_addr);
32-
ReleaseMemoryPagesToOS(beg_shadow_addr, end_shadow_addr);
33-
}
34-
3527
} // namespace
3628

3729
INTERCEPTOR(void *, mmap, void *addr, SIZE_T length, int prot, int flags,
@@ -46,23 +38,22 @@ INTERCEPTOR(void *, mmap, void *addr, SIZE_T length, int prot, int flags,
4638
res = REAL(mmap)(addr, length, prot, flags, fd, offset);
4739

4840
if (res != (void *)-1)
49-
ReleaseShadowMemoryPagesToOS(res, length);
41+
dfsan_set_label(0, res, RoundUpTo(length, GetPageSizeCached()));
5042
return res;
5143
}
5244

5345
INTERCEPTOR(void *, mmap64, void *addr, SIZE_T length, int prot, int flags,
5446
int fd, OFF64_T offset) {
5547
void *res = REAL(mmap64)(addr, length, prot, flags, fd, offset);
5648
if (res != (void *)-1)
57-
ReleaseShadowMemoryPagesToOS(res, length);
49+
dfsan_set_label(0, res, RoundUpTo(length, GetPageSizeCached()));
5850
return res;
5951
}
6052

6153
INTERCEPTOR(int, munmap, void *addr, SIZE_T length) {
6254
int res = REAL(munmap)(addr, length);
63-
if (res != -1) {
64-
ReleaseShadowMemoryPagesToOS(addr, length);
65-
}
55+
if (res != -1)
56+
dfsan_set_label(0, addr, RoundUpTo(length, GetPageSizeCached()));
6657
return res;
6758
}
6859

0 commit comments

Comments
 (0)