diff --git a/lldb/test/CMakeLists.txt b/lldb/test/CMakeLists.txt --- a/lldb/test/CMakeLists.txt +++ b/lldb/test/CMakeLists.txt @@ -165,6 +165,7 @@ LLDB_ENABLE_LUA LLDB_ENABLE_LZMA LLVM_ENABLE_ZLIB + LLVM_ENABLE_ZSTD LLVM_ENABLE_SHARED_LIBS LLDB_HAS_LIBCXX LLDB_USE_SYSTEM_DEBUGSERVER diff --git a/lldb/test/Shell/ObjectFile/ELF/compressed-sections-zstd.yaml b/lldb/test/Shell/ObjectFile/ELF/compressed-sections-zstd.yaml new file mode 100644 --- /dev/null +++ b/lldb/test/Shell/ObjectFile/ELF/compressed-sections-zstd.yaml @@ -0,0 +1,45 @@ +# REQUIRES: zstd +# RUN: yaml2obj %s -o %t +# RUN: lldb-test object-file --contents %t | FileCheck %s +--- !ELF +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_386 +Sections: + - Name: .hello_elf + Type: SHT_PROGBITS + Flags: [ SHF_COMPRESSED ] + Content: 02000000080000000100000028B52FFD20084100002030405060708090 + - Name: .bogus + Type: SHT_PROGBITS + Flags: [ SHF_COMPRESSED ] + Content: deadbeefbaadf00d +## The legacy .zdebug format is not supported. + - Name: .zdebug_info + Type: SHT_PROGBITS + Content: 5A4C49420000000000000008789c5330700848286898000009c802c1 + +# CHECK: Name: .hello_elf +# CHECK-NEXT: Type: regular +# CHECK: VM address: 0 +# CHECK-NEXT: VM size: 0 +# CHECK-NEXT: File size: 29 +# CHECK-NEXT: Data: ( +# CHECK-NEXT: 20304050 60708090 +# CHECK-NEXT: ) + +# CHECK: Name: .bogus +# CHECK-NEXT: Type: regular +# CHECK: VM address: 0 +# CHECK-NEXT: VM size: 0 +# CHECK-NEXT: File size: 8 +# CHECK-NEXT: Data: () + +# CHECK: Name: .zdebug_info +# CHECK: regular +# CHECK: File size: 28 +# CHECK: Data: ( +# CHECK-NEXT: 5A4C4942 00000000 00000008 789C5330 70084828 68980000 09C802C1 +# CHECK-NEXT: ) diff --git a/lldb/test/Shell/lit.site.cfg.py.in b/lldb/test/Shell/lit.site.cfg.py.in --- a/lldb/test/Shell/lit.site.cfg.py.in +++ b/lldb/test/Shell/lit.site.cfg.py.in @@ -16,6 +16,7 @@ config.target_triple = "@LLVM_TARGET_TRIPLE@" config.python_executable = "@Python3_EXECUTABLE@" config.have_zlib = @LLVM_ENABLE_ZLIB@ +config.have_zstd = @LLVM_ENABLE_ZSTD@ config.lldb_enable_lzma = @LLDB_ENABLE_LZMA@ config.host_triple = "@LLVM_HOST_TRIPLE@" config.lldb_bitness = 64 if @LLDB_IS_64_BITS@ else 32 diff --git a/llvm/include/llvm/Object/Decompressor.h b/llvm/include/llvm/Object/Decompressor.h --- 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 { @@ -44,10 +45,11 @@ private: Decompressor(StringRef Data); - Error consumeCompressedZLibHeader(bool Is64Bit, bool IsLittleEndian); + Error consumeCompressedSectionHeader(bool Is64Bit, bool IsLittleEndian); StringRef SectionData; uint64_t DecompressedSize; + llvm::DebugCompressionType CompressionType = llvm::DebugCompressionType::None; }; } // end namespace object diff --git a/llvm/include/llvm/Support/Compression.h b/llvm/include/llvm/Support/Compression.h --- a/llvm/include/llvm/Support/Compression.h +++ b/llvm/include/llvm/Support/Compression.h @@ -121,6 +121,11 @@ Error decompress(DebugCompressionType T, ArrayRef Input, SmallVectorImpl &Output, size_t UncompressedSize); +Error decompress(Format F, ArrayRef Input, uint8_t *Output, + size_t &UncompressedSize); +Error decompress(DebugCompressionType T, ArrayRef Input, + uint8_t *Output, size_t &UncompressedSize); + } // End of namespace compression } // End of namespace llvm diff --git a/llvm/lib/Object/Decompressor.cpp b/llvm/lib/Object/Decompressor.cpp --- a/llvm/lib/Object/Decompressor.cpp +++ b/llvm/lib/Object/Decompressor.cpp @@ -14,16 +14,15 @@ #include "llvm/Support/Endian.h" using namespace llvm; +using namespace llvm::compression; using namespace llvm::support::endian; 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.consumeCompressedSectionHeader(Is64Bit, IsLE)) return std::move(Err); return D; } @@ -31,8 +30,8 @@ Decompressor::Decompressor(StringRef Data) : SectionData(Data), DecompressedSize(0) {} -Error Decompressor::consumeCompressedZLibHeader(bool Is64Bit, - bool IsLittleEndian) { +Error Decompressor::consumeCompressedSectionHeader(bool Is64Bit, + bool IsLittleEndian) { using namespace ELF; uint64_t HdrSize = Is64Bit ? sizeof(Elf64_Chdr) : sizeof(Elf32_Chdr); if (SectionData.size() < HdrSize) @@ -40,10 +39,25 @@ DataExtractor Extractor(SectionData, IsLittleEndian, 0); uint64_t Offset = 0; - if (Extractor.getUnsigned(&Offset, Is64Bit ? sizeof(Elf64_Word) - : sizeof(Elf32_Word)) != - ELFCOMPRESS_ZLIB) + uint64_t ELFCompressionSchemeId = Extractor.getUnsigned( + &Offset, Is64Bit ? sizeof(Elf64_Word) : sizeof(Elf32_Word)); + + if (ELFCompressionSchemeId == ELFCOMPRESS_ZLIB) + CompressionType = llvm::DebugCompressionType::Z; + if (ELFCompressionSchemeId == ELFCOMPRESS_ZSTD) + CompressionType = llvm::DebugCompressionType::Zstd; + + if (CompressionType == llvm::DebugCompressionType::None) return createError("unsupported compression type"); + if (llvm::compression::getReasonIfUnsupported( + compression::formatFor(CompressionType)) != nullptr) { + switch (compression::formatFor(CompressionType)) { + case llvm::compression::Format::Zstd: + return createError("zstd is not available"); + default: + return createError("zlib is not available"); + } + } // Skip Elf64_Chdr::ch_reserved field. if (Is64Bit) @@ -57,6 +71,7 @@ Error Decompressor::decompress(MutableArrayRef Buffer) { size_t Size = Buffer.size(); - return compression::zlib::uncompress(arrayRefFromStringRef(SectionData), - Buffer.data(), Size); + return compression::decompress(compression::formatFor(CompressionType), + arrayRefFromStringRef(SectionData), + Buffer.data(), Size); } diff --git a/llvm/lib/Support/Compression.cpp b/llvm/lib/Support/Compression.cpp --- a/llvm/lib/Support/Compression.cpp +++ b/llvm/lib/Support/Compression.cpp @@ -73,6 +73,22 @@ return decompress(formatFor(T), Input, Output, UncompressedSize); } +Error compression::decompress(compression::Format F, ArrayRef Input, + uint8_t *Output, size_t &UncompressedSize) { + switch (F) { + case compression::Format::Zlib: + return zlib::uncompress(Input, Output, UncompressedSize); + case compression::Format::Zstd: + return zstd::uncompress(Input, Output, UncompressedSize); + } + llvm_unreachable(""); +} + +Error compression::decompress(DebugCompressionType T, ArrayRef Input, + uint8_t *Output, size_t &UncompressedSize) { + return decompress(formatFor(T), Input, Output, UncompressedSize); +} + #if LLVM_ENABLE_ZLIB static StringRef convertZlibCodeToString(int Code) {