1// DFSAN_OPTIONS=no_huge_pages_for_shadow=false RUN: %clang_dfsan %s -o %t && setarch `uname -m` -R %run %t
2// DFSAN_OPTIONS=no_huge_pages_for_shadow=true RUN: %clang_dfsan %s -o %t && setarch `uname -m` -R %run %t
3// DFSAN_OPTIONS=no_huge_pages_for_shadow=false RUN: %clang_dfsan %s -DORIGIN_TRACKING -mllvm -dfsan-fast-16-labels -mllvm -dfsan-track-origins=1 -o %t && setarch `uname -m` -R %run %t
4// DFSAN_OPTIONS=no_huge_pages_for_shadow=true RUN: %clang_dfsan %s -DORIGIN_TRACKING -mllvm -dfsan-fast-16-labels -mllvm -dfsan-track-origins=1 -o %t && setarch `uname -m` -R %run %t
5//
6// REQUIRES: x86_64-target-arch
7
8#include <assert.h>
9#include <sanitizer/dfsan_interface.h>
10#include <stdbool.h>
11#include <stdio.h>
12#include <string.h>
13#include <sys/mman.h>
14#include <unistd.h>
15
16size_t get_rss_kb() {
17 size_t ret = 0;
18 pid_t pid = getpid();
19
20 char fname[256];
21 sprintf(fname, "/proc/%ld/task/%ld/smaps", (long)pid, (long)pid);
22 FILE *f = fopen(fname, "r");
23 assert(f);
24
25 char buf[256];
26 while (fgets(buf, sizeof(buf), f) != NULL) {
27 int64_t rss;
28 if (sscanf(buf, "Rss: %ld kB", &rss) == 1)
29 ret += rss;
30 }
31 assert(feof(f));
32 fclose(f);
33
34 return ret;
35}
36
37int main(int argc, char **argv) {
38 const size_t map_size = 100 << 20;
39 size_t before = get_rss_kb();
40
41 // mmap and touch all addresses. The overhead is 1x.
42 char *p = mmap(NULL, map_size, PROT_READ | PROT_WRITE,
43 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
44 memset(p, 0xff, map_size);
45 size_t after_mmap = get_rss_kb();
46
47 // store labels to all addresses. The overhead is 2x.
48 const dfsan_label label = dfsan_create_label("l", 0);
49 char val = 0xff;
50 dfsan_set_label(label, &val, sizeof(val));
51 memset(p, val, map_size);
52 size_t after_mmap_and_set_label = get_rss_kb();
53
54 // fixed-mmap the same address. OS recyles pages and reinitializes data at the
55 // address. This should be the same to calling munmap.
56 p = mmap(p, map_size, PROT_READ | PROT_WRITE,
57 MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
58 size_t after_fixed_mmap = get_rss_kb();
59
60 // store labels to all addresses.
61 memset(p, val, map_size);
62 size_t after_mmap_and_set_label2 = get_rss_kb();
63
64 // munmap the addresses.
65 munmap(p, map_size);
66 size_t after_munmap = get_rss_kb();
67
68 fprintf(
69 stderr,
70 "RSS at start: %zu, after mmap: %zu, after mmap+set label: %zu, after "
71 "fixed map: %zu, after another mmap+set label: %zu, after munmap: %zu\n",
72 before, after_mmap, after_mmap_and_set_label, after_fixed_mmap,
73 after_mmap_and_set_label2, after_munmap);
74
75 const size_t mmap_cost_kb = map_size >> 10;
76 const size_t mmap_shadow_cost_kb = sizeof(dfsan_label) * mmap_cost_kb;
77#ifdef ORIGIN_TRACKING
78 const size_t mmap_origin_cost_kb = mmap_cost_kb;
79#else
80 const size_t mmap_origin_cost_kb = 0;
81#endif
82 assert(after_mmap >= before + mmap_cost_kb);
83 assert(after_mmap_and_set_label >=
84 after_mmap + mmap_shadow_cost_kb + mmap_origin_cost_kb);
85 assert(after_mmap_and_set_label2 >=
86 before + mmap_cost_kb + mmap_shadow_cost_kb + mmap_origin_cost_kb);
87
88 // RSS may not change memory amount after munmap to the same level as the
89 // start of the program. The assert checks the memory up to a delta.
90 const size_t delta = 5000;
91 assert(after_fixed_mmap <= before + delta);
92 assert(after_munmap <= before + delta);
93
94 return 0;
95}
96