1 // Regression test for 2 // https://code.google.com/p/chromium/issues/detail?id=446692 3 // where asan consumed too much RAM due to transparent hugetables. 4 // 5 // RUN: %clangxx_asan -g %s -o %t 6 // RUN: %env_asan_opts=no_huge_pages_for_shadow=1 %run %t 2>&1 | FileCheck %s 7 // RUN: %run %t 2>&1 | FileCheck %s 8 // 9 // Would be great to run the test with no_huge_pages_for_shadow=0, but 10 // the result will depend on the OS version and settings... 11 // 12 // REQUIRES: x86_64-supported-target, asan-64-bits 13 // 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 28 char FileContents[1 << 16]; 29 30 void 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 54 long 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 66 const int kAllocSize = 1 << 28; // 256Mb 67 const int kTwoMb = 1 << 21; 68 const int kAsanShadowGranularity = 8; 69 70 char *x; 71 72 __attribute__((no_sanitize_address)) void TouchNoAsan(size_t i) { x[i] = 0; } 73 74 int 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: SMALL 107 // CHECK: RSS CHANGE IS 3 => 4: LARGE 108