diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc b/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc --- a/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc +++ b/compiler-rt/lib/sanitizer_common/sanitizer_flags.inc @@ -191,6 +191,8 @@ "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, diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.cpp --- a/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stackdepot.cpp @@ -72,12 +72,25 @@ return stackStore.Allocated() + useCounts.MemoryUsage(); } +static void CompressStackStore() { + u64 start = MonotonicNanoTime(); + uptr diff = stackStore.Pack(static_cast( + common_flags()->compress_stack_depot)); + if (!diff) + return; + u64 finish = MonotonicNanoTime(); + uptr total_before = stackStore.Allocated() + diff; + VPrintf(1, "%s: StackDepot released %zu KiB out of %zu KiB in %llu ms\n", + SanitizerToolName, diff >> 10, total_before >> 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 --- /dev/null +++ b/compiler-rt/test/sanitizer_common/TestCases/compress_stack_depot.cpp @@ -0,0 +1,40 @@ +// 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 + +// FIXME: Fails for unknown reason. +// UNSUPPORTED: s390x + +#include + +__attribute__((noinline)) void a(unsigned v); +__attribute__((noinline)) void b(unsigned v); + +std::unique_ptr 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]+}}