[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