[compiler-rt] 81b1d3d - [sanitizers][Windows] Implement __sanitizer_purge_allocator for Win64

Matthew G McGovern via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 12 09:51:37 PST 2021


Author: Matthew G McGovern
Date: 2021-02-12T09:49:04-08:00
New Revision: 81b1d3da094c54ffd75e05c8d4683792edf17f4c

URL: https://github.com/llvm/llvm-project/commit/81b1d3da094c54ffd75e05c8d4683792edf17f4c
DIFF: https://github.com/llvm/llvm-project/commit/81b1d3da094c54ffd75e05c8d4683792edf17f4c.diff

LOG: [sanitizers][Windows] Implement __sanitizer_purge_allocator for Win64

    Windows' memory unmapping has to be explicit, there is no madvise.
Similarly, re-mapping memory has to be explicit as well. This patch
implements a basic method for remapping memory which was previously
returned to the OS on Windows.

Patch by Matthew G. McGovern and Jordyn Puryear

Added: 
    compiler-rt/test/asan/TestCases/Windows/sanitizer_purge.cpp

Modified: 
    compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h
    compiler-rt/lib/sanitizer_common/sanitizer_win.cpp

Removed: 
    


################################################################################
diff  --git a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h
index 0a18b0c58ef7..21b0366d83ca 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_allocator_primary64.h
@@ -144,6 +144,17 @@ class SizeClassAllocator64 {
     CompactPtrT *free_array = GetFreeArray(region_beg);
 
     BlockingMutexLock l(&region->mutex);
+#if SANITIZER_WINDOWS
+    /* On Windows unmapping of memory during __sanitizer_purge_allocator is
+    explicit and immediate, so unmapped regions must be explicitly mapped back
+    in when they are accessed again. */
+    if (region->rtoi.last_released_bytes > 0) {
+      MmapFixedOrDie(region_beg, region->mapped_user,
+                                      "SizeClassAllocator: region data");
+      region->rtoi.n_freed_at_last_release = 0;
+      region->rtoi.last_released_bytes = 0;
+    }
+#endif
     if (UNLIKELY(region->num_freed_chunks < n_chunks)) {
       if (UNLIKELY(!PopulateFreeArray(stat, class_id, region,
                                       n_chunks - region->num_freed_chunks)))

diff  --git a/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp
index 1b591f1bdcbb..99ecfd040c6a 100644
--- a/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp
+++ b/compiler-rt/lib/sanitizer_common/sanitizer_win.cpp
@@ -334,8 +334,12 @@ bool MprotectNoAccess(uptr addr, uptr size) {
 }
 
 void ReleaseMemoryPagesToOS(uptr beg, uptr end) {
-  // This is almost useless on 32-bits.
-  // FIXME: add madvise-analog when we move to 64-bits.
+  uptr beg_aligned = RoundDownTo(beg, GetPageSizeCached()),
+       end_aligned = RoundDownTo(end, GetPageSizeCached());
+  CHECK(beg < end);                // make sure the region is sane
+  if (beg_aligned == end_aligned)  // make sure we're freeing at least 1 page;
+    return;
+  UnmapOrDie((void *)beg, end_aligned - beg_aligned);
 }
 
 void SetShadowRegionHugePageMode(uptr addr, uptr size) {

diff  --git a/compiler-rt/test/asan/TestCases/Windows/sanitizer_purge.cpp b/compiler-rt/test/asan/TestCases/Windows/sanitizer_purge.cpp
new file mode 100644
index 000000000000..e3c7bfeaa5d4
--- /dev/null
+++ b/compiler-rt/test/asan/TestCases/Windows/sanitizer_purge.cpp
@@ -0,0 +1,31 @@
+#include <Windows.h>
+#include <stdio.h>
+#include <sanitizer/allocator_interface.h>
+#include <psapi.h>
+
+// RUN: %clang_cl_asan -Od %s -Fe%t 
+// RUN: %t
+// REQUIRES: asan-64-bits
+
+size_t GetRSS() {
+  PROCESS_MEMORY_COUNTERS counters;
+  if (!GetProcessMemoryInfo(GetCurrentProcess(), &counters, sizeof(counters)))
+    return 0;
+  return counters.WorkingSetSize;
+}
+
+int main(){
+    for (int i = 0; i < 1000; i++) {
+        void* a = malloc(1000);
+        free(a);
+    }
+    size_t rss_pre  = GetRSS();
+    __sanitizer_purge_allocator();
+    size_t rss_post = GetRSS();
+
+    if (rss_pre <= rss_post){
+        return -1;
+    }
+
+    return 0;
+}
\ No newline at end of file


        


More information about the llvm-commits mailing list