diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stack_store.h b/compiler-rt/lib/sanitizer_common/sanitizer_stack_store.h --- a/compiler-rt/lib/sanitizer_common/sanitizer_stack_store.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stack_store.h @@ -26,6 +26,7 @@ enum class Compression : u8 { None = 0, Delta, + LZW, }; constexpr StackStore() = default; diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_stack_store.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_stack_store.cpp --- a/compiler-rt/lib/sanitizer_common/sanitizer_stack_store.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_stack_store.cpp @@ -12,6 +12,8 @@ #include "sanitizer_common.h" #include "sanitizer_internal_defs.h" #include "sanitizer_leb128.h" +#include "sanitizer_lzw.h" +#include "sanitizer_placement_new.h" #include "sanitizer_stacktrace.h" namespace __sanitizer { @@ -211,6 +213,22 @@ }; } // namespace +static u8 *CompressLzw(const uptr *from, const uptr *from_end, u8 *to, + u8 *to_end) { + SLeb128Encoder encoder(to, to_end); + encoder = LzwEncode(from, from_end, encoder); + return encoder.base(); +} + +static uptr *UncompressLzw(const u8 *from, const u8 *from_end, uptr *to, + uptr *to_end) { + SLeb128Decoder decoder(from, from_end); + SLeb128Decoder end(from_end, from_end); + to = LzwDecode(decoder, end, to); + CHECK_EQ(to, to_end); + return to; +} + uptr *StackStore::BlockInfo::GetOrUnpack() { SpinMutexLock l(&mtx_); switch (state) { @@ -240,6 +258,10 @@ unpacked_end = UncompressDelta(header->data, ptr + header->size, unpacked, unpacked + kBlockSizeFrames); break; + case Compression::LZW: + unpacked_end = UncompressLzw(header->data, ptr + header->size, unpacked, + unpacked + kBlockSizeFrames); + break; default: UNREACHABLE("Unexpected type"); break; @@ -283,6 +305,10 @@ packed_end = CompressDelta(ptr, ptr + kBlockSizeFrames, header->data, alloc_end); break; + case Compression::LZW: + packed_end = + CompressLzw(ptr, ptr + kBlockSizeFrames, header->data, alloc_end); + break; default: UNREACHABLE("Unexpected type"); break; diff --git a/compiler-rt/lib/sanitizer_common/tests/sanitizer_stack_store_test.cpp b/compiler-rt/lib/sanitizer_common/tests/sanitizer_stack_store_test.cpp --- a/compiler-rt/lib/sanitizer_common/tests/sanitizer_stack_store_test.cpp +++ b/compiler-rt/lib/sanitizer_common/tests/sanitizer_stack_store_test.cpp @@ -137,6 +137,8 @@ ::testing::ValuesIn({ StackStorePackTest::ParamType(StackStore::Compression::Delta, FIRST_32_SECOND_64(2, 6)), + StackStorePackTest::ParamType(StackStore::Compression::LZW, + FIRST_32_SECOND_64(60, 130)), })); TEST_P(StackStorePackTest, PackUnpack) { diff --git a/compiler-rt/test/sanitizer_common/TestCases/compress_stack_depot.cpp b/compiler-rt/test/sanitizer_common/TestCases/compress_stack_depot.cpp --- a/compiler-rt/test/sanitizer_common/TestCases/compress_stack_depot.cpp +++ b/compiler-rt/test/sanitizer_common/TestCases/compress_stack_depot.cpp @@ -1,6 +1,7 @@ // 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 +// RUN: %env_tool_opts="compress_stack_depot=-2:malloc_context_size=128:verbosity=1" %run %t 2>&1 | FileCheck %s --check-prefixes=COMPRESS // Ubsan does not store stacks. // UNSUPPORTED: ubsan