[lld] cfa9769 - [ELF] Retain uncompressed if compressed content is larger
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Wed May 22 15:55:26 PDT 2024
Author: Fangrui Song
Date: 2024-05-22T15:55:21-07:00
New Revision: cfa97699f76761f25c4c4b686a503466c427afce
URL: https://github.com/llvm/llvm-project/commit/cfa97699f76761f25c4c4b686a503466c427afce
DIFF: https://github.com/llvm/llvm-project/commit/cfa97699f76761f25c4c4b686a503466c427afce.diff
LOG: [ELF] Retain uncompressed if compressed content is larger
--compress-debug-sections in GNU ld, gas, and LLVM integrated assembler
retain the uncompressed content if the compressed content is larger.
This patch also updates the manpage (-O2 does not enable zlib level 6)
and fixes a crash of --compress-sections when the uncompressed section
is empty.
Added:
Modified:
lld/ELF/Options.td
lld/ELF/OutputSections.cpp
lld/docs/ld.lld.1
lld/test/ELF/compress-debug-sections-zstd.s
lld/test/ELF/compress-sections.s
Removed:
################################################################################
diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td
index 883a6079bf507..ff61a566f52f7 100644
--- a/lld/ELF/Options.td
+++ b/lld/ELF/Options.td
@@ -69,6 +69,7 @@ defm compress_debug_sections:
defm compress_sections: EEq<"compress-sections",
"Compress output sections that match the glob and do not have the SHF_ALLOC flag. "
+ "The sections remain uncompressed if compressed content would be larger. "
"The compression level is <level> (if specified) or a default speed-focused level">,
MetaVarName<"<section-glob>={none,zlib,zstd}[:level]">;
diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp
index fcb4c4387aa97..60de10061c53d 100644
--- a/lld/ELF/OutputSections.cpp
+++ b/lld/ELF/OutputSections.cpp
@@ -344,9 +344,10 @@ template <class ELFT> void OutputSection::maybeCompress() {
(void)sizeof(Elf_Chdr);
DebugCompressionType ctype = DebugCompressionType::None;
+ size_t compressedSize = sizeof(Elf_Chdr);
unsigned level = 0; // default compression level
if (!(flags & SHF_ALLOC) && config->compressDebugSections &&
- name.starts_with(".debug_") && size)
+ name.starts_with(".debug_"))
ctype = *config->compressDebugSections;
for (auto &[glob, t, l] : config->compressSections)
if (glob.match(name))
@@ -360,7 +361,6 @@ template <class ELFT> void OutputSection::maybeCompress() {
}
llvm::TimeTraceScope timeScope("Compress sections");
- compressed.uncompressedSize = size;
auto buf = std::make_unique<uint8_t[]>(size);
// Write uncompressed data to a temporary zero-initialized buffer.
{
@@ -378,7 +378,6 @@ template <class ELFT> void OutputSection::maybeCompress() {
[[maybe_unused]] constexpr size_t shardSize = 1 << 20;
auto shardsIn = split(ArrayRef<uint8_t>(buf.get(), size), shardSize);
const size_t numShards = shardsIn.size();
- compressed.numShards = numShards;
auto shardsOut = std::make_unique<SmallVector<uint8_t, 0>[]>(numShards);
#if LLVM_ENABLE_ZSTD
@@ -409,9 +408,8 @@ template <class ELFT> void OutputSection::maybeCompress() {
shardsOut[i] = std::move(out);
});
compressed.type = ELFCOMPRESS_ZSTD;
- size = sizeof(Elf_Chdr);
for (size_t i = 0; i != numShards; ++i)
- size += shardsOut[i].size();
+ compressedSize += shardsOut[i].size();
}
#endif
@@ -434,18 +432,23 @@ template <class ELFT> void OutputSection::maybeCompress() {
// Update section size and combine Alder-32 checksums.
uint32_t checksum = 1; // Initial Adler-32 value
- size = sizeof(Elf_Chdr) + 2; // Elf_Chdir and zlib header
+ compressedSize += 2; // Elf_Chdir and zlib header
for (size_t i = 0; i != numShards; ++i) {
- size += shardsOut[i].size();
+ compressedSize += shardsOut[i].size();
checksum = adler32_combine(checksum, shardsAdler[i], shardsIn[i].size());
}
- size += 4; // checksum
+ compressedSize += 4; // checksum
compressed.type = ELFCOMPRESS_ZLIB;
compressed.checksum = checksum;
}
#endif
+ if (compressedSize >= size)
+ return;
+ compressed.uncompressedSize = size;
compressed.shards = std::move(shardsOut);
+ compressed.numShards = numShards;
+ size = compressedSize;
flags |= SHF_COMPRESSED;
}
diff --git a/lld/docs/ld.lld.1 b/lld/docs/ld.lld.1
index 0df13f07f560d..da3b926d02a28 100644
--- a/lld/docs/ld.lld.1
+++ b/lld/docs/ld.lld.1
@@ -148,6 +148,7 @@ Alias for
.Fl -color-diagnostics Ns = Ns Cm auto .
.It Fl -compress-debug-sections Ns = Ns Ar value
Compress DWARF debug sections.
+The sections remain uncompressed if compressed content would be larger.
.Cm value
may be
.Pp
@@ -163,6 +164,7 @@ Use the default compression level in zstd.
.Pp
.It Fl -compress-sections Ns = Ns Ar section-glob={none,zlib,zstd}[:level]
Compress output sections that match the glob and do not have the SHF_ALLOC flag.
+The matched sections remain uncompressed if compressed content would be larger.
The compression level is
.Cm level
(if specified) or a default speed-focused level.
@@ -420,9 +422,7 @@ Disable string merging.
.It Cm 1
Enable string merging.
.It Cm 2
-Enable string tail merging. If
-.Fl -compress-debug-sections
-is given, compress debug sections at compression level 6 instead of 1.
+Enable string tail merging.
.El
.Pp
.Fl O Ns Cm 1
diff --git a/lld/test/ELF/compress-debug-sections-zstd.s b/lld/test/ELF/compress-debug-sections-zstd.s
index 61ae15b15cd7b..d9f29af999741 100644
--- a/lld/test/ELF/compress-debug-sections-zstd.s
+++ b/lld/test/ELF/compress-debug-sections-zstd.s
@@ -21,7 +21,7 @@
# OUTPUT-SEC: .debug_str PROGBITS [[#%x,]] [[#%x,]] [[#%x,]] 01 MSC 0 0 1
# OUTPUT-SEC-NEXT: .debug_frame PROGBITS [[#%x,]] [[#%x,]] 000000 00 0 0 1
-# OUTPUT-SEC-NEXT: .debug_loc PROGBITS [[#%x,]] [[#%x,]] [[#%x,]] 00 C 0 0 1
+# OUTPUT-SEC-NEXT: .debug_loc PROGBITS [[#%x,]] [[#%x,]] 000010 00 0 0 1
.section .debug_str,"MS", at progbits,1
.LASF2:
diff --git a/lld/test/ELF/compress-sections.s b/lld/test/ELF/compress-sections.s
index e61dc22ccd205..aaad31476044e 100644
--- a/lld/test/ELF/compress-sections.s
+++ b/lld/test/ELF/compress-sections.s
@@ -25,8 +25,8 @@
# CHECK2-NEXT: foo1 PROGBITS [[#%x,FOO1:]] [[#%x,]] [[#%x,]] 00 A 0 0 8
# CHECK2-NEXT: .text PROGBITS [[#%x,TEXT:]] [[#%x,]] [[#%x,]] 00 AX 0 0 4
# CHECK2: nonalloc0 PROGBITS 0000000000000000 [[#%x,]] [[#%x,]] 00 C 0 0 1
-# CHECK2-NEXT: nonalloc1 PROGBITS 0000000000000000 [[#%x,]] [[#%x,]] 00 0 0 8
-# CHECK2-NEXT: smallc0 PROGBITS 0000000000000000 [[#%x,]] [[#%x,]] 00 C 0 0 1
+# CHECK2-NEXT: nonalloc1 PROGBITS 0000000000000000 [[#%x,]] 000088 00 0 0 8
+# CHECK2-NEXT: smallc0 PROGBITS 0000000000000000 [[#%x,]] 00000c 00 0 0 1
# CHECK2-NEXT: .debug_str PROGBITS 0000000000000000 [[#%x,]] [[#%x,]] 01 MSC 0 0 1
# CHECK2: 0000000000000090 0 NOTYPE LOCAL DEFAULT [[#]] (nonalloc0) sym0
More information about the llvm-commits
mailing list