[llvm] 0b140d0 - [Object] Add zstd decompression support to Decompressor

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Mon Sep 19 11:41:24 PDT 2022


Author: Fangrui Song
Date: 2022-09-19T11:41:16-07:00
New Revision: 0b140d0910d1762225fd10372d84ecca1a62305d

URL: https://github.com/llvm/llvm-project/commit/0b140d0910d1762225fd10372d84ecca1a62305d
DIFF: https://github.com/llvm/llvm-project/commit/0b140d0910d1762225fd10372d84ecca1a62305d.diff

LOG: [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

Added: 
    llvm/test/DebugInfo/dwarfdump-zstd.test
    llvm/test/DebugInfo/symbolize-zstd.test
    llvm/test/tools/llvm-dwp/X86/compress-zstd.test

Modified: 
    llvm/include/llvm/Object/Decompressor.h
    llvm/include/llvm/Support/Compression.h
    llvm/lib/Object/Decompressor.cpp
    llvm/lib/Support/Compression.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Object/Decompressor.h b/llvm/include/llvm/Object/Decompressor.h
index 35f4ebe2e5d61..d361b3fba81da 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 @@ class Decompressor {
   }
 
   /// Uncompress section data to raw buffer provided.
-  /// @param Buffer      Destination buffer.
-  Error decompress(MutableArrayRef<uint8_t> Buffer);
+  Error decompress(MutableArrayRef<uint8_t> Output);
 
   /// Return memory buffer size required for decompression.
   uint64_t getDecompressedSize() { return DecompressedSize; }
@@ -44,10 +44,11 @@ class Decompressor {
 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 66ad9f8f275fd..c3ba3274d6ed8 100644
--- a/llvm/include/llvm/Support/Compression.h
+++ b/llvm/include/llvm/Support/Compression.h
@@ -114,6 +114,8 @@ void compress(Params P, ArrayRef<uint8_t> Input,
               SmallVectorImpl<uint8_t> &Output);
 
 // Decompress Input. The uncompressed size must be available.
+Error decompress(DebugCompressionType T, ArrayRef<uint8_t> Input,
+                 uint8_t *Output, size_t UncompressedSize);
 Error decompress(Format F, ArrayRef<uint8_t> Input,
                  SmallVectorImpl<uint8_t> &Output, size_t UncompressedSize);
 Error decompress(DebugCompressionType T, ArrayRef<uint8_t> Input,

diff  --git a/llvm/lib/Object/Decompressor.cpp b/llvm/lib/Object/Decompressor.cpp
index 4793124d6f1b4..f38c0e69e850b 100644
--- a/llvm/lib/Object/Decompressor.cpp
+++ b/llvm/lib/Object/Decompressor.cpp
@@ -19,11 +19,8 @@ using namespace object;
 
 Expected<Decompressor> 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> 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<uint8_t> Buffer) {
-  size_t Size = Buffer.size();
-  return compression::zlib::decompress(arrayRefFromStringRef(SectionData),
-                                       Buffer.data(), Size);
+Error Decompressor::decompress(MutableArrayRef<uint8_t> 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 529e617190dd8..8e57ba798f520 100644
--- a/llvm/lib/Support/Compression.cpp
+++ b/llvm/lib/Support/Compression.cpp
@@ -55,6 +55,17 @@ void compression::compress(Params P, ArrayRef<uint8_t> Input,
   }
 }
 
+Error compression::decompress(DebugCompressionType T, ArrayRef<uint8_t> 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<uint8_t> Input,
                               SmallVectorImpl<uint8_t> &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 0000000000000..2cf7a47ab5c26
--- /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 0000000000000..ae60374feb7b2
--- /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 0000000000000..c63d0d1c90f41
--- /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"


        


More information about the llvm-commits mailing list