brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.0 KiB · 0f0e1a9 Raw
114 lines · c
1// DFSAN_OPTIONS=no_huge_pages_for_shadow=false RUN: %clang_dfsan %s -o %t && %run %t2// DFSAN_OPTIONS=no_huge_pages_for_shadow=true RUN: %clang_dfsan %s -o %t && %run %t3// DFSAN_OPTIONS=no_huge_pages_for_shadow=false RUN: %clang_dfsan %s -DORIGIN_TRACKING -mllvm -dfsan-track-origins=1 -o %t && %run %t4// DFSAN_OPTIONS=no_huge_pages_for_shadow=true RUN: %clang_dfsan %s -DORIGIN_TRACKING -mllvm -dfsan-track-origins=1 -o %t && %run %t5 6#include <assert.h>7#include <sanitizer/dfsan_interface.h>8#include <stdbool.h>9#include <stdio.h>10#include <string.h>11#include <sys/mman.h>12#include <unistd.h>13 14size_t get_rss_kb() {15  size_t ret = 0;16  pid_t pid = getpid();17 18  char fname[256];19  sprintf(fname, "/proc/%ld/task/%ld/smaps", (long)pid, (long)pid);20  FILE *f = fopen(fname, "r");21  assert(f);22 23  char buf[256];24  while (fgets(buf, sizeof(buf), f) != NULL) {25    int64_t rss;26    // DFSan's sscanf is broken and doesn't check for ordinary characters in27    // the format string, hence we use strstr as a secondary check28    // (https://github.com/llvm/llvm-project/issues/94769).29    if ((sscanf(buf, "Rss: %ld kB", &rss) == 1) &&30        (strstr(buf, "Rss: ") != NULL))31      ret += rss;32  }33  assert(feof(f));34  fclose(f);35 36  return ret;37}38 39int main(int argc, char **argv) {40  const size_t map_size = 100 << 20;41  size_t before = get_rss_kb();42 43  // mmap and touch all addresses. The overhead is 1x.44  char *p = mmap(NULL, map_size, PROT_READ | PROT_WRITE,45                 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);46  memset(p, 0xff, map_size);47  size_t after_mmap = get_rss_kb();48 49  // store labels to all addresses. The overhead is 2x.50  const dfsan_label label = 8;51  char val = 0xff;52  dfsan_set_label(label, &val, sizeof(val));53  memset(p, val, map_size);54  size_t after_mmap_and_set_label = get_rss_kb();55 56  // fixed-mmap the same address. OS recyles pages and reinitializes data at the57  // address. This should be the same to calling munmap.58  p = mmap(p, map_size, PROT_READ | PROT_WRITE,59           MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);60  size_t after_fixed_mmap = get_rss_kb();61 62  // store labels to all addresses.63  memset(p, val, map_size);64  size_t after_mmap_and_set_label2 = get_rss_kb();65 66  // munmap the addresses.67  munmap(p, map_size);68  size_t after_munmap = get_rss_kb();69 70  fprintf(71      stderr,72      "RSS at start: %zu, after mmap: %zu, after mmap+set label: %zu, after "73      "fixed map: %zu, after another mmap+set label: %zu, after munmap: %zu\n",74      before, after_mmap, after_mmap_and_set_label, after_fixed_mmap,75      after_mmap_and_set_label2, after_munmap);76 77  // This is orders of magnitude larger than we expect (typically < 10,000KB).78  // It is a quick check to ensure that the RSS calculation function isn't79  // egregriously wrong.80  assert(before < 1000000);81 82  const size_t mmap_cost_kb = map_size >> 10;83  // Shadow space (1:1 with application memory)84  const size_t mmap_shadow_cost_kb = sizeof(dfsan_label) * mmap_cost_kb;85#ifdef ORIGIN_TRACKING86  // Origin space (1:1 with application memory)87  const size_t mmap_origin_cost_kb = mmap_cost_kb;88#else89  const size_t mmap_origin_cost_kb = 0;90#endif91  assert(after_mmap >= before + mmap_cost_kb);92  assert(after_mmap_and_set_label >=93         after_mmap + mmap_shadow_cost_kb + mmap_origin_cost_kb);94  assert(after_mmap_and_set_label2 >=95         before + mmap_cost_kb + mmap_shadow_cost_kb + mmap_origin_cost_kb);96 97#ifdef ORIGIN_TRACKING98  // This value is chosen based on observed difference.99  const size_t mmap_origin_chain_kb = 4000;100#else101  const size_t mmap_origin_chain_kb = 0;102#endif103 104  // RSS may not change memory amount after munmap to the same level as the105  // start of the program. The assert checks the memory up to a delta.106  const size_t delta = 5000;107  // Origin chains are not freed, even when the origin space which refers to108  // them is freed, so mmap_origin_chain_kb is added to account for this.109  assert(after_fixed_mmap <= before + delta + mmap_origin_chain_kb);110  assert(after_munmap <= before + delta + mmap_origin_chain_kb);111 112  return 0;113}114