[lld] 5e0464e - [ELF] Support ELFCOMPRESS_ZSTD input

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 9 10:25:45 PDT 2022


Author: Fangrui Song
Date: 2022-09-09T10:25:37-07:00
New Revision: 5e0464e38bcb63186e5c5eaafe550e92143cab43

URL: https://github.com/llvm/llvm-project/commit/5e0464e38bcb63186e5c5eaafe550e92143cab43
DIFF: https://github.com/llvm/llvm-project/commit/5e0464e38bcb63186e5c5eaafe550e92143cab43.diff

LOG: [ELF] Support ELFCOMPRESS_ZSTD input

so that lld accepts relocatable object files produced by `clang -c -g -gz=zstd`.

We don't want to increase the size of InputSection, so do redundant but cheap
ch_type checks instead.

Differential Revision: https://reviews.llvm.org/D129406

Added: 
    lld/test/ELF/compress-debug-sections-zstd.s
    lld/test/ELF/compressed-input-err-zstd.s

Modified: 
    lld/ELF/InputSection.cpp
    lld/docs/ReleaseNotes.rst
    lld/test/CMakeLists.txt
    lld/test/ELF/gdb-index.s
    lld/test/lit.site.cfg.py.in

Removed: 
    


################################################################################
diff  --git a/lld/ELF/InputSection.cpp b/lld/ELF/InputSection.cpp
index b3ec3f7328413..8dff884a496d5 100644
--- a/lld/ELF/InputSection.cpp
+++ b/lld/ELF/InputSection.cpp
@@ -110,6 +110,18 @@ size_t InputSectionBase::getSize() const {
   return rawData.size() - bytesDropped;
 }
 
+template <class ELFT>
+static void decompressAux(const InputSectionBase &sec, uint8_t *out,
+                          size_t size) {
+  auto *hdr = reinterpret_cast<const typename ELFT::Chdr *>(sec.rawData.data());
+  auto compressed = sec.rawData.slice(sizeof(typename ELFT::Chdr));
+  if (Error e = hdr->ch_type == ELFCOMPRESS_ZLIB
+                    ? compression::zlib::uncompress(compressed, out, size)
+                    : compression::zstd::uncompress(compressed, out, size))
+    fatal(toString(&sec) +
+          ": decompress failed: " + llvm::toString(std::move(e)));
+}
+
 void InputSectionBase::decompress() const {
   size_t size = uncompressedSize;
   uint8_t *uncompressedBuf;
@@ -119,9 +131,7 @@ void InputSectionBase::decompress() const {
     uncompressedBuf = bAlloc().Allocate<uint8_t>(size);
   }
 
-  if (Error e = compression::zlib::uncompress(rawData, uncompressedBuf, size))
-    fatal(toString(this) +
-          ": decompress failed: " + llvm::toString(std::move(e)));
+  invokeELFT(decompressAux, *this, uncompressedBuf, size);
   rawData = makeArrayRef(uncompressedBuf, size);
   uncompressedSize = -1;
 }
@@ -212,6 +222,10 @@ template <typename ELFT> void InputSectionBase::parseCompressedHeader() {
     if (!compression::zlib::isAvailable())
       error(toString(this) + " is compressed with ELFCOMPRESS_ZLIB, but lld is "
                              "not built with zlib support");
+  } else if (hdr->ch_type == ELFCOMPRESS_ZSTD) {
+    if (!compression::zstd::isAvailable())
+      error(toString(this) + " is compressed with ELFCOMPRESS_ZSTD, but lld is "
+                             "not built with zstd support");
   } else {
     error(toString(this) + ": unsupported compression type (" +
           Twine(hdr->ch_type) + ")");
@@ -220,7 +234,6 @@ template <typename ELFT> void InputSectionBase::parseCompressedHeader() {
 
   uncompressedSize = hdr->ch_size;
   alignment = std::max<uint32_t>(hdr->ch_addralign, 1);
-  rawData = rawData.slice(sizeof(*hdr));
 }
 
 InputSection *InputSectionBase::getLinkOrderDep() const {
@@ -1219,8 +1232,12 @@ template <class ELFT> void InputSection::writeTo(uint8_t *buf) {
   // If this is a compressed section, uncompress section contents directly
   // to the buffer.
   if (uncompressedSize >= 0) {
+    auto *hdr = reinterpret_cast<const typename ELFT::Chdr *>(rawData.data());
+    auto compressed = rawData.slice(sizeof(typename ELFT::Chdr));
     size_t size = uncompressedSize;
-    if (Error e = compression::zlib::uncompress(rawData, buf, size))
+    if (Error e = hdr->ch_type == ELFCOMPRESS_ZLIB
+                      ? compression::zlib::uncompress(compressed, buf, size)
+                      : compression::zstd::uncompress(compressed, buf, size))
       fatal(toString(this) +
             ": decompress failed: " + llvm::toString(std::move(e)));
     uint8_t *bufEnd = buf + size;

diff  --git a/lld/docs/ReleaseNotes.rst b/lld/docs/ReleaseNotes.rst
index 325c8abd0bd80..af8b55578f810 100644
--- a/lld/docs/ReleaseNotes.rst
+++ b/lld/docs/ReleaseNotes.rst
@@ -26,6 +26,9 @@ Non-comprehensive list of changes in this release
 ELF Improvements
 ----------------
 
+* ``ELFCOMPRESS_ZSTD`` compressed input sections are now supported.
+  (`D129406 <https://reviews.llvm.org/D129406>`_)
+
 Breaking changes
 ----------------
 

diff  --git a/lld/test/CMakeLists.txt b/lld/test/CMakeLists.txt
index 85ac92e54b2fc..d290533ada5ad 100644
--- a/lld/test/CMakeLists.txt
+++ b/lld/test/CMakeLists.txt
@@ -1,6 +1,7 @@
 llvm_canonicalize_cmake_booleans(
   ENABLE_BACKTRACES
   LLVM_ENABLE_ZLIB
+  LLVM_ENABLE_ZSTD
   LLVM_ENABLE_LIBXML2
   LLD_DEFAULT_LD_LLD_IS_MINGW
   LLVM_HAVE_LIBXAR

diff  --git a/lld/test/ELF/compress-debug-sections-zstd.s b/lld/test/ELF/compress-debug-sections-zstd.s
new file mode 100644
index 0000000000000..59e4644c4e83e
--- /dev/null
+++ b/lld/test/ELF/compress-debug-sections-zstd.s
@@ -0,0 +1,26 @@
+# REQUIRES: x86, zstd
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64 --compress-debug-sections=zstd %s -o %t.o
+
+# RUN: ld.lld %t.o -o %t.so -shared
+# RUN: llvm-readelf -S -x .debug_str %t.so | FileCheck %s
+
+# CHECK:      .debug_str    PROGBITS [[#%x,]] [[#%x,]] [[#%x,]] 01 MS  0 0  1
+# CHECK:      Hex dump of section '.debug_str':
+# CHECK-NEXT: 0x00000000 756e7369 676e6564 20696e74 00636861 unsigned int.cha
+# CHECK-NEXT: 0x00000010 7200756e 7369676e 65642063 68617200 r.unsigned char.
+# CHECK-NEXT: 0x00000020 73686f72 7420756e 7369676e 65642069 short unsigned i
+# CHECK-NEXT: 0x00000030 6e74006c 6f6e6720 756e7369 676e6564 nt.long unsigned
+# CHECK-NEXT: 0x00000040 20696e74 00                          int.
+
+.section .debug_str,"MS", at progbits,1
+.LASF2:
+ .string "short unsigned int"
+.LASF3:
+ .string "unsigned int"
+.LASF0:
+ .string "long unsigned int"
+.LASF8:
+ .string "char"
+.LASF1:
+ .string "unsigned char"

diff  --git a/lld/test/ELF/compressed-input-err-zstd.s b/lld/test/ELF/compressed-input-err-zstd.s
new file mode 100644
index 0000000000000..31a88916f3c49
--- /dev/null
+++ b/lld/test/ELF/compressed-input-err-zstd.s
@@ -0,0 +1,18 @@
+# UNSUPPORTED: zstd
+# RUN: yaml2obj %s -o %t.o
+# RUN: not ld.lld %t.o -o /dev/null 2>&1 | FileCheck %s
+
+# CHECK: error: {{.*}}.o:(.debug_info) is compressed with ELFCOMPRESS_ZSTD, but lld is not built with zstd support
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_X86_64
+Sections:
+  - Type:         SHT_PROGBITS
+    Name:         .debug_info
+    Flags:        [ SHF_COMPRESSED ]
+    AddressAlign: 8
+    Content:      "020000000000000000000000000000000100000000000000789c030000000001"

diff  --git a/lld/test/ELF/gdb-index.s b/lld/test/ELF/gdb-index.s
index 7e72d470a118c..6d91a2e52acfb 100644
--- a/lld/test/ELF/gdb-index.s
+++ b/lld/test/ELF/gdb-index.s
@@ -22,6 +22,12 @@
 # RUN: llvm-dwarfdump -gdb-index %t | FileCheck %s --check-prefix=DWARF
 # RUN: llvm-readelf -S %t | FileCheck %s --check-prefix=SECTION
 
+# RUN: %if zstd %{ llvm-mc -compress-debug-sections=zlib -filetype=obj -triple=x86_64 %p/Inputs/gdb-index.s -o %t2.o %}
+# RUN: %if zstd %{ ld.lld --gdb-index %t1.o %t2.o -o %t %}
+# RUN: %if zstd %{ llvm-objdump -d %t | FileCheck %s --check-prefix=DISASM %}
+# RUN: %if zstd %{ llvm-dwarfdump --gdb-index %t | FileCheck %s --check-prefix=DWARF %}
+# RUN: %if zstd %{ llvm-readelf -S %t | FileCheck %s --check-prefix=SECTION %}
+
 # DISASM:       Disassembly of section .text:
 # DISASM-EMPTY:
 # DISASM:       <entrypoint>:

diff  --git a/lld/test/lit.site.cfg.py.in b/lld/test/lit.site.cfg.py.in
index 0523762cf6c95..e0998ab87d470 100644
--- a/lld/test/lit.site.cfg.py.in
+++ b/lld/test/lit.site.cfg.py.in
@@ -18,6 +18,7 @@ config.lld_tools_dir = lit_config.substitute("@CURRENT_TOOLS_DIR@")
 config.target_triple = "@LLVM_TARGET_TRIPLE@"
 config.python_executable = "@Python3_EXECUTABLE@"
 config.have_zlib = @LLVM_ENABLE_ZLIB@
+config.have_zstd = @LLVM_ENABLE_ZSTD@
 config.have_libxar = @LLVM_HAVE_LIBXAR@
 config.have_libxml2 = @LLVM_ENABLE_LIBXML2@
 config.sizeof_void_p = @CMAKE_SIZEOF_VOID_P@


        


More information about the llvm-commits mailing list