From 0b140d0910d1762225fd10372d84ecca1a62305d Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Mon, 19 Sep 2022 11:41:16 -0700 Subject: [PATCH] [Object] Add zstd decompression support to Decompressor llvm::object::Decompressor is used by many DWARF consumers like llvm-dwarfdump, llvm-dwp, llvm-symbolizer. Add tests to them. The lldb test can be left to D133530. Reviewed By: dblaikie Differential Revision: https://reviews.llvm.org/D134116 --- llvm/include/llvm/Object/Decompressor.h | 7 ++--- llvm/include/llvm/Support/Compression.h | 2 ++ llvm/lib/Object/Decompressor.cpp | 35 +++++++++++++++---------- llvm/lib/Support/Compression.cpp | 11 ++++++++ llvm/test/DebugInfo/dwarfdump-zstd.test | 8 ++++++ llvm/test/DebugInfo/symbolize-zstd.test | 8 ++++++ llvm/test/tools/llvm-dwp/X86/compress-zstd.test | 9 +++++++ 7 files changed, 63 insertions(+), 17 deletions(-) create mode 100644 llvm/test/DebugInfo/dwarfdump-zstd.test create mode 100644 llvm/test/DebugInfo/symbolize-zstd.test create mode 100644 llvm/test/tools/llvm-dwp/X86/compress-zstd.test diff --git a/llvm/include/llvm/Object/Decompressor.h b/llvm/include/llvm/Object/Decompressor.h index 35f4ebe..d361b3f 100644 --- a/llvm/include/llvm/Object/Decompressor.h +++ b/llvm/include/llvm/Object/Decompressor.h @@ -11,6 +11,7 @@ #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/StringRef.h" +#include "llvm/Support/Compression.h" #include "llvm/Support/Error.h" namespace llvm { @@ -35,8 +36,7 @@ public: } /// Uncompress section data to raw buffer provided. - /// @param Buffer Destination buffer. - Error decompress(MutableArrayRef Buffer); + Error decompress(MutableArrayRef Output); /// Return memory buffer size required for decompression. uint64_t getDecompressedSize() { return DecompressedSize; } @@ -44,10 +44,11 @@ public: private: Decompressor(StringRef Data); - Error consumeCompressedZLibHeader(bool Is64Bit, bool IsLittleEndian); + Error consumeCompressedHeader(bool Is64Bit, bool IsLittleEndian); StringRef SectionData; uint64_t DecompressedSize; + DebugCompressionType CompressionType = DebugCompressionType::None; }; } // end namespace object diff --git a/llvm/include/llvm/Support/Compression.h b/llvm/include/llvm/Support/Compression.h index 66ad9f8..c3ba327 100644 --- a/llvm/include/llvm/Support/Compression.h +++ b/llvm/include/llvm/Support/Compression.h @@ -114,6 +114,8 @@ void compress(Params P, ArrayRef Input, SmallVectorImpl &Output); // Decompress Input. The uncompressed size must be available. +Error decompress(DebugCompressionType T, ArrayRef Input, + uint8_t *Output, size_t UncompressedSize); Error decompress(Format F, ArrayRef Input, SmallVectorImpl &Output, size_t UncompressedSize); Error decompress(DebugCompressionType T, ArrayRef Input, diff --git a/llvm/lib/Object/Decompressor.cpp b/llvm/lib/Object/Decompressor.cpp index 4793124..f38c0e6 100644 --- a/llvm/lib/Object/Decompressor.cpp +++ b/llvm/lib/Object/Decompressor.cpp @@ -19,11 +19,8 @@ using namespace object; Expected Decompressor::create(StringRef Name, StringRef Data, bool IsLE, bool Is64Bit) { - if (!compression::zlib::isAvailable()) - return createError("zlib is not available"); - Decompressor D(Data); - if (Error Err = D.consumeCompressedZLibHeader(Is64Bit, IsLE)) + if (Error Err = D.consumeCompressedHeader(Is64Bit, IsLE)) return std::move(Err); return D; } @@ -31,8 +28,7 @@ Expected Decompressor::create(StringRef Name, StringRef Data, Decompressor::Decompressor(StringRef Data) : SectionData(Data), DecompressedSize(0) {} -Error Decompressor::consumeCompressedZLibHeader(bool Is64Bit, - bool IsLittleEndian) { +Error Decompressor::consumeCompressedHeader(bool Is64Bit, bool IsLittleEndian) { using namespace ELF; uint64_t HdrSize = Is64Bit ? sizeof(Elf64_Chdr) : sizeof(Elf32_Chdr); if (SectionData.size() < HdrSize) @@ -40,10 +36,21 @@ Error Decompressor::consumeCompressedZLibHeader(bool Is64Bit, DataExtractor Extractor(SectionData, IsLittleEndian, 0); uint64_t Offset = 0; - if (Extractor.getUnsigned(&Offset, Is64Bit ? sizeof(Elf64_Word) - : sizeof(Elf32_Word)) != - ELFCOMPRESS_ZLIB) - return createError("unsupported compression type"); + auto ChType = Extractor.getUnsigned(&Offset, Is64Bit ? sizeof(Elf64_Word) + : sizeof(Elf32_Word)); + switch (ChType) { + case ELFCOMPRESS_ZLIB: + CompressionType = DebugCompressionType::Zlib; + break; + case ELFCOMPRESS_ZSTD: + CompressionType = DebugCompressionType::Zstd; + break; + default: + return createError("unsupported compression type (" + Twine(ChType) + ")"); + } + if (const char *Reason = llvm::compression::getReasonIfUnsupported( + compression::formatFor(CompressionType))) + return createError(Reason); // Skip Elf64_Chdr::ch_reserved field. if (Is64Bit) @@ -55,8 +62,8 @@ Error Decompressor::consumeCompressedZLibHeader(bool Is64Bit, return Error::success(); } -Error Decompressor::decompress(MutableArrayRef Buffer) { - size_t Size = Buffer.size(); - return compression::zlib::decompress(arrayRefFromStringRef(SectionData), - Buffer.data(), Size); +Error Decompressor::decompress(MutableArrayRef Output) { + return compression::decompress(CompressionType, + arrayRefFromStringRef(SectionData), + Output.data(), Output.size()); } diff --git a/llvm/lib/Support/Compression.cpp b/llvm/lib/Support/Compression.cpp index 529e617..8e57ba7 100644 --- a/llvm/lib/Support/Compression.cpp +++ b/llvm/lib/Support/Compression.cpp @@ -55,6 +55,17 @@ void compression::compress(Params P, ArrayRef Input, } } +Error compression::decompress(DebugCompressionType T, ArrayRef Input, + uint8_t *Output, size_t UncompressedSize) { + switch (formatFor(T)) { + case compression::Format::Zlib: + return zlib::decompress(Input, Output, UncompressedSize); + case compression::Format::Zstd: + return zstd::decompress(Input, Output, UncompressedSize); + } + llvm_unreachable(""); +} + Error compression::decompress(compression::Format F, ArrayRef Input, SmallVectorImpl &Output, size_t UncompressedSize) { diff --git a/llvm/test/DebugInfo/dwarfdump-zstd.test b/llvm/test/DebugInfo/dwarfdump-zstd.test new file mode 100644 index 0000000..2cf7a47 --- /dev/null +++ b/llvm/test/DebugInfo/dwarfdump-zstd.test @@ -0,0 +1,8 @@ +; REQUIRES: zstd +;; llvm-dwarfdump supports zstd compressed debug sections. + +; RUN: llvm-objcopy --compress-debug-sections=zstd %S/Inputs/dwarfdump-test.elf-x86-64 %t +; RUN: llvm-dwarfdump %t | FileCheck %s + +; CHECK: .debug_info contents +; CHECK: DW_AT_name ("dwarfdump-test.cc") diff --git a/llvm/test/DebugInfo/symbolize-zstd.test b/llvm/test/DebugInfo/symbolize-zstd.test new file mode 100644 index 0000000..ae60374 --- /dev/null +++ b/llvm/test/DebugInfo/symbolize-zstd.test @@ -0,0 +1,8 @@ +# REQUIRES: zstd +## llvm-symbolizer supports zstd compressed debug sections. + +# RUN: llvm-objcopy --compress-debug-sections=zstd %S/Inputs/dwarfdump-test.elf-x86-64 %t +# RUN: llvm-symbolizer --obj=%t 0x40113f | FileCheck %s + +# CHECK: main +# CHECK-NEXT: /tmp/dbginfo{{[/\\]}}dwarfdump-test.cc:16 diff --git a/llvm/test/tools/llvm-dwp/X86/compress-zstd.test b/llvm/test/tools/llvm-dwp/X86/compress-zstd.test new file mode 100644 index 0000000..c63d0d1 --- /dev/null +++ b/llvm/test/tools/llvm-dwp/X86/compress-zstd.test @@ -0,0 +1,9 @@ +# REQUIRES: zstd +## llvm-dwp supports zstd compressed debug sections. + +# RUN: llvm-objcopy --compress-debug-sections=zstd %p/../Inputs/simple/notypes/a.dwo %t.o +# RUN: llvm-dwp %t.o -o %t.dwp + +# CHECK: .debug_info.dwo contents: +# CHECK: DW_TAG_compile_unit +# CHECK: DW_AT_name {{.*}} "a.cpp" -- 2.7.4