[sanitizer] Add compress_stack_depot flag
authorVitaly Buka <vitalybuka@google.com>
Wed, 24 Nov 2021 00:31:26 +0000 (16:31 -0800)
committerVitaly Buka <vitalybuka@google.com>
Wed, 1 Dec 2021 03:08:58 +0000 (19:08 -0800)
Depends on D114494.

Reviewed By: morehouse

Differential Revision: https://reviews.llvm.org/D114495

compiler-rt/lib/sanitizer_common/sanitizer_flags.inc
compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.cpp
compiler-rt/test/sanitizer_common/TestCases/compress_stack_depot.cpp [new file with mode: 0644]

index 95da82b..8295537 100644 (file)
@@ -191,6 +191,8 @@ COMMON_FLAG(const char *, stack_trace_format, "DEFAULT",
             "Format string used to render stack frames. "
             "See sanitizer_stacktrace_printer.h for the format description. "
             "Use DEFAULT to get default format.")
+COMMON_FLAG(int, compress_stack_depot, 0,
+            "Compress stack depot to save memory.")
 COMMON_FLAG(bool, no_huge_pages_for_shadow, true,
             "If true, the shadow is not allowed to use huge pages. ")
 COMMON_FLAG(bool, strict_string_checks, false,
index 527221b..6c281e4 100644 (file)
@@ -72,12 +72,25 @@ uptr StackDepotNode::allocated() {
   return stackStore.Allocated() + useCounts.MemoryUsage();
 }
 
+static void CompressStackStore() {
+  u64 start = MonotonicNanoTime();
+  uptr diff = stackStore.Pack(static_cast<StackStore::Compression>(
+      common_flags()->compress_stack_depot));
+  if (!diff)
+    return;
+  u64 finish = MonotonicNanoTime();
+  uptr total = stackStore.Allocated();
+  VPrintf(1, "%s: StackDepot released %zu KiB out of %zu KiB in %llu ms\n",
+          SanitizerToolName, diff >> 10, total >> 10,
+          (finish - start) / 1000000);
+}
+
 void StackDepotNode::store(u32 id, const args_type &args, hash_type hash) {
   stack_hash = hash;
   uptr pack = 0;
   store_id = stackStore.Store(args, &pack);
-  if (pack)
-    stackStore.Pack(StackStore::Compression::None);
+  if (pack && common_flags()->compress_stack_depot)
+    CompressStackStore();
 }
 
 StackDepotNode::args_type StackDepotNode::load(u32 id) const {
diff --git a/compiler-rt/test/sanitizer_common/TestCases/compress_stack_depot.cpp b/compiler-rt/test/sanitizer_common/TestCases/compress_stack_depot.cpp
new file mode 100644 (file)
index 0000000..6df3b2c
--- /dev/null
@@ -0,0 +1,37 @@
+// RUN: %clangxx %s -fsanitize-memory-track-origins=1 -o %t
+// RUN: %env_tool_opts="compress_stack_depot=0:malloc_context_size=128:verbosity=1" %run %t 2>&1 | FileCheck %s --implicit-check-not="StackDepot released"
+// RUN: %env_tool_opts="compress_stack_depot=1:malloc_context_size=128:verbosity=1" %run %t 2>&1 | FileCheck %s --check-prefixes=COMPRESS
+
+// Ubsan does not store stacks.
+// UNSUPPORTED: ubsan
+
+#include <memory>
+
+__attribute__((noinline)) void a(unsigned v);
+__attribute__((noinline)) void b(unsigned v);
+
+std::unique_ptr<int[]> p;
+
+__attribute__((noinline)) void a(unsigned v) {
+  int x;
+  v >>= 1;
+  if (!v) {
+    p.reset(new int[100]);
+    p[1] = x;
+    return;
+  }
+  if (v & 1)
+    b(v);
+  else
+    a(v);
+}
+
+__attribute__((noinline)) void b(unsigned v) { return a(v); }
+
+int main(int argc, char *argv[]) {
+  for (unsigned i = 0; i < 100000; ++i)
+    a(i + (i << 16));
+  return 0;
+}
+
+// COMPRESS: StackDepot released {{[0-9]+}}