ckissane created this revision.
ckissane added a reviewer: MaskRay.
Herald added subscribers: StephenFan, abrachet, hiraditya, mgorny, emaste.
Herald added a reviewer: jhenderson.
Herald added a project: All.
ckissane requested review of this revision.
Herald added projects: LLDB, LLVM.
Herald added subscribers: llvm-commits, lldb-commits.

fixes extra bytes that zlib is "ok" with but zstd detects and errors on when 
decompressing


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D133525

Files:
  lldb/test/CMakeLists.txt
  lldb/test/Shell/ObjectFile/ELF/compressed-sections-zstd.yaml
  lldb/test/Shell/lit.site.cfg.py.in
  llvm/include/llvm/Object/Decompressor.h
  llvm/include/llvm/Support/Compression.h
  llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
  llvm/lib/ObjCopy/ELF/ELFObject.cpp
  llvm/lib/ObjCopy/ELF/ELFObject.h
  llvm/lib/Object/Decompressor.cpp
  llvm/lib/Support/Compression.cpp

Index: llvm/lib/Support/Compression.cpp
===================================================================
--- llvm/lib/Support/Compression.cpp
+++ llvm/lib/Support/Compression.cpp
@@ -73,6 +73,22 @@
   return decompress(formatFor(T), Input, Output, UncompressedSize);
 }
 
+Error compression::decompress(compression::Format F, ArrayRef<uint8_t> 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<uint8_t> Input,
+                              uint8_t *Output, size_t &UncompressedSize) {
+  return decompress(formatFor(T), Input, Output, UncompressedSize);
+}
+
 #if LLVM_ENABLE_ZLIB
 
 static StringRef convertZlibCodeToString(int Code) {
Index: llvm/lib/Object/Decompressor.cpp
===================================================================
--- llvm/lib/Object/Decompressor.cpp
+++ 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> 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<uint8_t> 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);
 }
Index: llvm/lib/ObjCopy/ELF/ELFObject.h
===================================================================
--- llvm/lib/ObjCopy/ELF/ELFObject.h
+++ llvm/lib/ObjCopy/ELF/ELFObject.h
@@ -537,6 +537,7 @@
   MAKE_SEC_WRITER_FRIEND
 
   uint32_t ChType = 0;
+  bool Is64Bits;
   DebugCompressionType CompressionType;
   uint64_t DecompressedSize;
   uint64_t DecompressedAlign;
@@ -544,9 +545,10 @@
 
 public:
   CompressedSection(const SectionBase &Sec,
-                    DebugCompressionType CompressionType);
+                    DebugCompressionType CompressionType, bool Is64Bits);
   CompressedSection(ArrayRef<uint8_t> CompressedData, uint32_t ChType,
-                    uint64_t DecompressedSize, uint64_t DecompressedAlign);
+                    uint64_t DecompressedSize, uint64_t DecompressedAlign,
+                    bool Is64Bits);
 
   uint64_t getDecompressedSize() const { return DecompressedSize; }
   uint64_t getDecompressedAlign() const { return DecompressedAlign; }
Index: llvm/lib/ObjCopy/ELF/ELFObject.cpp
===================================================================
--- llvm/lib/ObjCopy/ELF/ELFObject.cpp
+++ llvm/lib/ObjCopy/ELF/ELFObject.cpp
@@ -527,26 +527,28 @@
 }
 
 CompressedSection::CompressedSection(const SectionBase &Sec,
-                                     DebugCompressionType CompressionType)
-    : SectionBase(Sec), CompressionType(CompressionType),
+                                     DebugCompressionType CompressionType,
+                                     bool Is64Bits)
+    : SectionBase(Sec), Is64Bits(Is64Bits), CompressionType(CompressionType),
       DecompressedSize(Sec.OriginalData.size()), DecompressedAlign(Sec.Align) {
   compression::compress(compression::Params(CompressionType), OriginalData,
                         CompressedData);
 
   Flags |= ELF::SHF_COMPRESSED;
   size_t ChdrSize =
-      std::max(std::max(sizeof(object::Elf_Chdr_Impl<object::ELF64LE>),
-                        sizeof(object::Elf_Chdr_Impl<object::ELF64BE>)),
-               std::max(sizeof(object::Elf_Chdr_Impl<object::ELF32LE>),
-                        sizeof(object::Elf_Chdr_Impl<object::ELF32BE>)));
+      Is64Bits ? std::max(sizeof(object::Elf_Chdr_Impl<object::ELF64LE>),
+                          sizeof(object::Elf_Chdr_Impl<object::ELF64BE>))
+               : std::max(sizeof(object::Elf_Chdr_Impl<object::ELF32LE>),
+                          sizeof(object::Elf_Chdr_Impl<object::ELF32BE>));
   Size = ChdrSize + CompressedData.size();
   Align = 8;
 }
 
 CompressedSection::CompressedSection(ArrayRef<uint8_t> CompressedData,
                                      uint32_t ChType, uint64_t DecompressedSize,
-                                     uint64_t DecompressedAlign)
-    : ChType(ChType), CompressionType(DebugCompressionType::None),
+                                     uint64_t DecompressedAlign, bool Is64Bits)
+    : ChType(ChType), Is64Bits(Is64Bits),
+      CompressionType(DebugCompressionType::None),
       DecompressedSize(DecompressedSize), DecompressedAlign(DecompressedAlign) {
   OriginalData = CompressedData;
 }
@@ -1724,8 +1726,9 @@
     if (!(Shdr.sh_flags & ELF::SHF_COMPRESSED))
       return Obj.addSection<Section>(*Data);
     auto *Chdr = reinterpret_cast<const Elf_Chdr_Impl<ELFT> *>(Data->data());
-    return Obj.addSection<CompressedSection>(CompressedSection(
-        *Data, Chdr->ch_type, Chdr->ch_size, Chdr->ch_addralign));
+    return Obj.addSection<CompressedSection>(
+        CompressedSection(*Data, Chdr->ch_type, Chdr->ch_size,
+                          Chdr->ch_addralign, ELFT::Is64Bits));
   }
   }
 }
Index: llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
===================================================================
--- llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
+++ llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
@@ -505,12 +505,18 @@
   if (Error E = Obj.removeSections(ELFConfig.AllowBrokenLinks, RemovePred))
     return E;
 
+  const ElfType OutputElfType =
+      getOutputElfType(Config.OutputArch.value_or(MachineInfo()));
+  const bool Is64Bit =
+      OutputElfType == ELFT_ELF64LE || OutputElfType == ELFT_ELF64BE;
   if (Config.CompressionType != DebugCompressionType::None) {
+
     if (Error Err = replaceDebugSections(
             Obj, isCompressable,
-            [&Config, &Obj](const SectionBase *S) -> Expected<SectionBase *> {
+            [&Config, &Obj,
+             Is64Bit](const SectionBase *S) -> Expected<SectionBase *> {
               return &Obj.addSection<CompressedSection>(
-                  CompressedSection(*S, Config.CompressionType));
+                  CompressedSection(*S, Config.CompressionType, Is64Bit));
             }))
       return Err;
   } else if (Config.DecompressDebugSections) {
Index: llvm/include/llvm/Support/Compression.h
===================================================================
--- llvm/include/llvm/Support/Compression.h
+++ llvm/include/llvm/Support/Compression.h
@@ -121,6 +121,11 @@
 Error decompress(DebugCompressionType T, ArrayRef<uint8_t> Input,
                  SmallVectorImpl<uint8_t> &Output, size_t UncompressedSize);
 
+Error decompress(Format F, ArrayRef<uint8_t> Input, uint8_t *Output,
+                 size_t &UncompressedSize);
+Error decompress(DebugCompressionType T, ArrayRef<uint8_t> Input,
+                 uint8_t *Output, size_t &UncompressedSize);
+
 } // End of namespace compression
 
 } // End of namespace llvm
Index: llvm/include/llvm/Object/Decompressor.h
===================================================================
--- llvm/include/llvm/Object/Decompressor.h
+++ 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
Index: lldb/test/Shell/lit.site.cfg.py.in
===================================================================
--- lldb/test/Shell/lit.site.cfg.py.in
+++ 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
Index: lldb/test/Shell/ObjectFile/ELF/compressed-sections-zstd.yaml
===================================================================
--- /dev/null
+++ lldb/test/Shell/ObjectFile/ELF/compressed-sections-zstd.yaml
@@ -0,0 +1,23 @@
+# 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
+
+# CHECK: Name: .hello_elf
+# CHECK-NEXT: Type: regular
+# CHECK: VM address: 0
+# CHECK-NEXT: VM size: 0
+# CHECK-NEXT: File size: 28
+# CHECK-NEXT: Data: (
+# CHECK-NEXT: 20304050 60708090
+# CHECK-NEXT: )
Index: lldb/test/CMakeLists.txt
===================================================================
--- lldb/test/CMakeLists.txt
+++ 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
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to