summaryrefslogtreecommitdiff
path: root/lib/dfsan
diff options
context:
space:
mode:
authorPeter Collingbourne <peter@pcc.me.uk>2014-08-19 01:47:33 +0000
committerPeter Collingbourne <peter@pcc.me.uk>2014-08-19 01:47:33 +0000
commit6b07b56c7c861640b1fc0215aad043dae2c11275 (patch)
treeed45e4d6db0d59574e39b66d086cd89f6a462fd8 /lib/dfsan
parentee354fb8b0da2f6d814c2944dec1cac22b45c175 (diff)
DFSan's set label function should avoid writing to the shadow memory when the write would not change the value in memory.
When writing a label to shadow memory, don't write if the value is already set to the value being written. This dramatically reduces real memory consumption in programs with sparse use of labels. Test Plan: It would be nice to test that unnecessary writes are skipped, but I do not see how a unit test could do this. Patch by Sam Kerner! Differential Revision: http://reviews.llvm.org/D4894 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@215961 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/dfsan')
-rw-r--r--lib/dfsan/dfsan.cc14
1 files changed, 13 insertions, 1 deletions
diff --git a/lib/dfsan/dfsan.cc b/lib/dfsan/dfsan.cc
index 11ab77e2e..a9673d5c5 100644
--- a/lib/dfsan/dfsan.cc
+++ b/lib/dfsan/dfsan.cc
@@ -169,8 +169,20 @@ dfsan_label dfsan_create_label(const char *desc, void *userdata) {
extern "C" SANITIZER_INTERFACE_ATTRIBUTE
void __dfsan_set_label(dfsan_label label, void *addr, uptr size) {
- for (dfsan_label *labelp = shadow_for(addr); size != 0; --size, ++labelp)
+ for (dfsan_label *labelp = shadow_for(addr); size != 0; --size, ++labelp) {
+ // Don't write the label if it is already the value we need it to be.
+ // In a program where most addresses are not labeled, it is common that
+ // a page of shadow memory is entirely zeroed. The Linux copy-on-write
+ // implementation will share all of the zeroed pages, making a copy of a
+ // page when any value is written. The un-sharing will happen even if
+ // the value written does not change the value in memory. Avoiding the
+ // write when both |label| and |*labelp| are zero dramatically reduces
+ // the amount of real memory used by large programs.
+ if (label == *labelp)
+ continue;
+
*labelp = label;
+ }
}
SANITIZER_INTERFACE_ATTRIBUTE