Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / compiler-rt / test / dfsan / release_shadow_space.c
blob9492f2ad7728ccf5889e50ae2bedc34143affe03
1 // https://github.com/llvm/llvm-project/issues/60678
2 // XFAIL: glibc-2.37
4 // DFSAN_OPTIONS=no_huge_pages_for_shadow=false RUN: %clang_dfsan %s -o %t && %run %t
5 // DFSAN_OPTIONS=no_huge_pages_for_shadow=true RUN: %clang_dfsan %s -o %t && %run %t
6 // DFSAN_OPTIONS=no_huge_pages_for_shadow=false RUN: %clang_dfsan %s -DORIGIN_TRACKING -mllvm -dfsan-track-origins=1 -o %t && %run %t
7 // DFSAN_OPTIONS=no_huge_pages_for_shadow=true RUN: %clang_dfsan %s -DORIGIN_TRACKING -mllvm -dfsan-track-origins=1 -o %t && %run %t
9 #include <assert.h>
10 #include <sanitizer/dfsan_interface.h>
11 #include <stdbool.h>
12 #include <stdio.h>
13 #include <string.h>
14 #include <sys/mman.h>
15 #include <unistd.h>
17 size_t get_rss_kb() {
18 size_t ret = 0;
19 pid_t pid = getpid();
21 char fname[256];
22 sprintf(fname, "/proc/%ld/task/%ld/smaps", (long)pid, (long)pid);
23 FILE *f = fopen(fname, "r");
24 assert(f);
26 char buf[256];
27 while (fgets(buf, sizeof(buf), f) != NULL) {
28 int64_t rss;
29 if (sscanf(buf, "Rss: %ld kB", &rss) == 1)
30 ret += rss;
32 assert(feof(f));
33 fclose(f);
35 return ret;
38 int main(int argc, char **argv) {
39 const size_t map_size = 100 << 20;
40 size_t before = get_rss_kb();
42 // mmap and touch all addresses. The overhead is 1x.
43 char *p = mmap(NULL, map_size, PROT_READ | PROT_WRITE,
44 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
45 memset(p, 0xff, map_size);
46 size_t after_mmap = get_rss_kb();
48 // store labels to all addresses. The overhead is 2x.
49 const dfsan_label label = 8;
50 char val = 0xff;
51 dfsan_set_label(label, &val, sizeof(val));
52 memset(p, val, map_size);
53 size_t after_mmap_and_set_label = get_rss_kb();
55 // fixed-mmap the same address. OS recyles pages and reinitializes data at the
56 // address. This should be the same to calling munmap.
57 p = mmap(p, map_size, PROT_READ | PROT_WRITE,
58 MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
59 size_t after_fixed_mmap = get_rss_kb();
61 // store labels to all addresses.
62 memset(p, val, map_size);
63 size_t after_mmap_and_set_label2 = get_rss_kb();
65 // munmap the addresses.
66 munmap(p, map_size);
67 size_t after_munmap = get_rss_kb();
69 fprintf(
70 stderr,
71 "RSS at start: %zu, after mmap: %zu, after mmap+set label: %zu, after "
72 "fixed map: %zu, after another mmap+set label: %zu, after munmap: %zu\n",
73 before, after_mmap, after_mmap_and_set_label, after_fixed_mmap,
74 after_mmap_and_set_label2, after_munmap);
76 const size_t mmap_cost_kb = map_size >> 10;
77 // Shadow space (1:1 with application memory)
78 const size_t mmap_shadow_cost_kb = sizeof(dfsan_label) * mmap_cost_kb;
79 #ifdef ORIGIN_TRACKING
80 // Origin space (1:1 with application memory)
81 const size_t mmap_origin_cost_kb = mmap_cost_kb;
82 #else
83 const size_t mmap_origin_cost_kb = 0;
84 #endif
85 assert(after_mmap >= before + mmap_cost_kb);
86 assert(after_mmap_and_set_label >=
87 after_mmap + mmap_shadow_cost_kb + mmap_origin_cost_kb);
88 assert(after_mmap_and_set_label2 >=
89 before + mmap_cost_kb + mmap_shadow_cost_kb + mmap_origin_cost_kb);
91 #ifdef ORIGIN_TRACKING
92 // This value is chosen based on observed difference.
93 const size_t mmap_origin_chain_kb = 4000;
94 #else
95 const size_t mmap_origin_chain_kb = 0;
96 #endif
98 // RSS may not change memory amount after munmap to the same level as the
99 // start of the program. The assert checks the memory up to a delta.
100 const size_t delta = 5000;
101 // Origin chains are not freed, even when the origin space which refers to
102 // them is freed, so mmap_origin_chain_kb is added to account for this.
103 assert(after_fixed_mmap <= before + delta + mmap_origin_chain_kb);
104 assert(after_munmap <= before + delta + mmap_origin_chain_kb);
106 return 0;