@@ -274,9 +274,10 @@ dfsan_label dfsan_create_label(const char *desc, void *userdata) {
274
274
return label;
275
275
}
276
276
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) {
280
281
// Don't write the label if it is already the value we need it to be.
281
282
// In a program where most addresses are not labeled, it is common that
282
283
// 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) {
292
293
}
293
294
}
294
295
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
+
295
328
SANITIZER_INTERFACE_ATTRIBUTE
296
329
void dfsan_set_label (dfsan_label label, void *addr, uptr size) {
297
330
__dfsan_set_label (label, addr, size);
0 commit comments