108 lines · cpp
1// Regression test for2// https://code.google.com/p/chromium/issues/detail?id=4466923// where asan consumed too much RAM due to transparent hugetables.4//5// RUN: %clangxx_asan -g %s -o %t6// RUN: %env_asan_opts=no_huge_pages_for_shadow=1 %run %t 2>&1 | FileCheck %s7// RUN: %run %t 2>&1 | FileCheck %s8//9// Would be great to run the test with no_huge_pages_for_shadow=0, but10// the result will depend on the OS version and settings...11//12// REQUIRES: x86_64-target-arch, shadow-scale-313//14// WARNING: this test is very subtle and may nto work on some systems.15// If this is the case we'll need to futher improve it or disable it.16#include <assert.h>17#include <stdio.h>18#include <stdlib.h>19#include <string.h>20#include <sys/mman.h>21#include <sys/types.h>22#include <sys/stat.h>23#include <fcntl.h>24#include <unistd.h>25#include <errno.h>26#include <sanitizer/asan_interface.h>27 28char FileContents[1 << 16];29 30void FileToString(const char *path) {31 FileContents[0] = 0;32 int fd = open(path, 0);33 if (fd < 0) return;34 char *p = FileContents;35 ssize_t size = sizeof(FileContents) - 1;36 ssize_t res = 0;37 do {38 ssize_t got = read (fd, p, size);39 if (got == 0)40 break;41 else if (got > 0)42 {43 p += got;44 res += got;45 size -= got;46 }47 else if (errno != EINTR)48 break;49 } while (size > 0 && res < sizeof(FileContents));50 if (res >= 0)51 FileContents[res] = 0;52}53 54long ReadShadowRss() {55 const char *path = "/proc/self/smaps";56 FileToString(path);57 char *s = strstr(FileContents, "2008fff7000-10007fff8000");58 if (!s) return 0;59 60 s = strstr(s, "Rss:");61 if (!s) return 0;62 s = s + 4;63 return atol(s);64}65 66const int kAllocSize = 1 << 28; // 256Mb67const int kTwoMb = 1 << 21;68const int kAsanShadowGranularity = 8;69 70char *x;71 72__attribute__((no_sanitize_address)) void TouchNoAsan(size_t i) { x[i] = 0; }73 74int main() {75 long rss[5];76 rss[0] = ReadShadowRss();77 // use mmap directly to avoid asan touching the shadow.78 x = (char *)mmap(0, kAllocSize, PROT_READ | PROT_WRITE,79 MAP_PRIVATE | MAP_ANON, 0, 0);80 fprintf(stderr, "X: %p-%p\n", x, x + kAllocSize);81 rss[1] = ReadShadowRss();82 83 // Touch the allocated region, but not the shadow.84 for (size_t i = 0; i < kAllocSize; i += kTwoMb * kAsanShadowGranularity)85 TouchNoAsan(i);86 rss[2] = ReadShadowRss();87 88 // Touch the shadow just a bit, in 2Mb*Granularity steps.89 for (size_t i = 0; i < kAllocSize; i += kTwoMb * kAsanShadowGranularity)90 __asan_poison_memory_region(x + i, kAsanShadowGranularity);91 rss[3] = ReadShadowRss();92 93 // Touch all the shadow.94 __asan_poison_memory_region(x, kAllocSize);95 rss[4] = ReadShadowRss();96 97 // Print the differences.98 for (int i = 0; i < 4; i++) {99 assert(rss[i] > 0);100 assert(rss[i+1] >= rss[i]);101 long diff = rss[i+1] / rss[i];102 fprintf(stderr, "RSS CHANGE IS %d => %d: %s (%ld vs %ld)\n", i, i + 1,103 diff < 10 ? "SMALL" : "LARGE", rss[i], rss[i + 1]);104 }105}106// CHECK: RSS CHANGE IS 2 => 3: SMALL107// CHECK: RSS CHANGE IS 3 => 4: LARGE108