[llvm] [llvm-objcopy] Add --compress-sections (PR #85036)
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Thu Mar 28 17:08:19 PDT 2024
https://github.com/MaskRay updated https://github.com/llvm/llvm-project/pull/85036
>From 795e3c3d94da0a664642d4580d87c82c02d5eca4 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Wed, 13 Mar 2024 00:29:36 -0700
Subject: [PATCH 1/2] =?UTF-8?q?[=F0=9D=98=80=F0=9D=97=BD=F0=9D=97=BF]=20ch?=
=?UTF-8?q?anges=20to=20main=20this=20commit=20is=20based=20on?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Created using spr 1.3.5-bogner
[skip ci]
---
llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp | 63 +++++++------------
llvm/lib/ObjCopy/ELF/ELFObject.h | 1 +
.../ELF/Inputs/compress-debug-sections.yaml | 4 ++
.../ELF/compress-debug-sections-zlib.test | 2 +
.../ELF/compress-debug-sections-zstd.test | 2 +
.../llvm-objcopy/ELF/decompress-sections.test | 36 +++++++++++
6 files changed, 68 insertions(+), 40 deletions(-)
create mode 100644 llvm/test/tools/llvm-objcopy/ELF/decompress-sections.test
diff --git a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
index f52bcb74938d15..e4d6e02f3aa60d 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
+++ b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
@@ -214,33 +214,32 @@ static Error dumpSectionToFile(StringRef SecName, StringRef Filename,
SecName.str().c_str());
}
-static bool isCompressable(const SectionBase &Sec) {
- return !(Sec.Flags & ELF::SHF_COMPRESSED) &&
- StringRef(Sec.Name).starts_with(".debug");
-}
-
-static Error replaceDebugSections(
- Object &Obj, function_ref<bool(const SectionBase &)> ShouldReplace,
- function_ref<Expected<SectionBase *>(const SectionBase *)> AddSection) {
+Error Object::compressOrDecompressSections(const CommonConfig &Config) {
// Build a list of the debug sections we are going to replace.
// We can't call `AddSection` while iterating over sections,
// because it would mutate the sections array.
- SmallVector<SectionBase *, 13> ToReplace;
- for (auto &Sec : Obj.sections())
- if (ShouldReplace(Sec))
- ToReplace.push_back(&Sec);
-
- // Build a mapping from original section to a new one.
- DenseMap<SectionBase *, SectionBase *> FromTo;
- for (SectionBase *S : ToReplace) {
- Expected<SectionBase *> NewSection = AddSection(S);
- if (!NewSection)
- return NewSection.takeError();
-
- FromTo[S] = *NewSection;
+ SmallVector<std::pair<SectionBase *, std::function<SectionBase *()>>, 0>
+ ToReplace;
+ for (SectionBase &Sec : sections()) {
+ if ((Sec.Flags & SHF_ALLOC) || !StringRef(Sec.Name).starts_with(".debug"))
+ continue;
+ if (auto *CS = dyn_cast<CompressedSection>(&Sec)) {
+ if (Config.DecompressDebugSections) {
+ ToReplace.emplace_back(
+ &Sec, [=] { return &addSection<DecompressedSection>(*CS); });
+ }
+ } else if (Config.CompressionType != DebugCompressionType::None) {
+ ToReplace.emplace_back(&Sec, [&, S = &Sec] {
+ return &addSection<CompressedSection>(
+ CompressedSection(*S, Config.CompressionType, Is64Bits));
+ });
+ }
}
- return Obj.replaceSections(FromTo);
+ DenseMap<SectionBase *, SectionBase *> FromTo;
+ for (auto [S, Func] : ToReplace)
+ FromTo[S] = Func();
+ return replaceSections(FromTo);
}
static bool isAArch64MappingSymbol(const Symbol &Sym) {
@@ -534,24 +533,8 @@ static Error replaceAndRemoveSections(const CommonConfig &Config,
if (Error E = Obj.removeSections(ELFConfig.AllowBrokenLinks, RemovePred))
return E;
- if (Config.CompressionType != DebugCompressionType::None) {
- if (Error Err = replaceDebugSections(
- Obj, isCompressable,
- [&Config, &Obj](const SectionBase *S) -> Expected<SectionBase *> {
- return &Obj.addSection<CompressedSection>(
- CompressedSection(*S, Config.CompressionType, Obj.Is64Bits));
- }))
- return Err;
- } else if (Config.DecompressDebugSections) {
- if (Error Err = replaceDebugSections(
- Obj,
- [](const SectionBase &S) { return isa<CompressedSection>(&S); },
- [&Obj](const SectionBase *S) {
- const CompressedSection *CS = cast<CompressedSection>(S);
- return &Obj.addSection<DecompressedSection>(*CS);
- }))
- return Err;
- }
+ if (Error E = Obj.compressOrDecompressSections(Config))
+ return E;
return Error::success();
}
diff --git a/llvm/lib/ObjCopy/ELF/ELFObject.h b/llvm/lib/ObjCopy/ELF/ELFObject.h
index 7a2e20d82d1150..f72c109b6009e8 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObject.h
+++ b/llvm/lib/ObjCopy/ELF/ELFObject.h
@@ -1210,6 +1210,7 @@ class Object {
Error removeSections(bool AllowBrokenLinks,
std::function<bool(const SectionBase &)> ToRemove);
+ Error compressOrDecompressSections(const CommonConfig &Config);
Error replaceSections(const DenseMap<SectionBase *, SectionBase *> &FromTo);
Error removeSymbols(function_ref<bool(const Symbol &)> ToRemove);
template <class T, class... Ts> T &addSection(Ts &&...Args) {
diff --git a/llvm/test/tools/llvm-objcopy/ELF/Inputs/compress-debug-sections.yaml b/llvm/test/tools/llvm-objcopy/ELF/Inputs/compress-debug-sections.yaml
index 67d8435fa486c1..e2dfee9163a2b8 100644
--- a/llvm/test/tools/llvm-objcopy/ELF/Inputs/compress-debug-sections.yaml
+++ b/llvm/test/tools/llvm-objcopy/ELF/Inputs/compress-debug-sections.yaml
@@ -43,6 +43,10 @@ Sections:
Type: SHT_PROGBITS
Flags: [ SHF_GROUP ]
Content: '00'
+ - Name: .debug_alloc
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC ]
+ Content: 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f
Symbols:
- Type: STT_SECTION
Section: .debug_foo
diff --git a/llvm/test/tools/llvm-objcopy/ELF/compress-debug-sections-zlib.test b/llvm/test/tools/llvm-objcopy/ELF/compress-debug-sections-zlib.test
index e1ebeed8d4fcb0..056ae84ce4915f 100644
--- a/llvm/test/tools/llvm-objcopy/ELF/compress-debug-sections-zlib.test
+++ b/llvm/test/tools/llvm-objcopy/ELF/compress-debug-sections-zlib.test
@@ -12,8 +12,10 @@
# CHECK: Name Type Address Off Size ES Flg Lk Inf Al
# COMPRESSED: .debug_foo PROGBITS 0000000000000000 000040 {{.*}} 00 C 0 0 8
# COMPRESSED-NEXT: .notdebug_foo PROGBITS 0000000000000000 {{.*}} 000008 00 0 0 0
+# COMPRESSED: .debug_alloc PROGBITS 0000000000000000 {{.*}} 000040 00 A 0 0 0
# UNCOMPRESSED: .debug_foo PROGBITS 0000000000000000 000040 000008 00 0 0 0
# UNCOMPRESSED-NEXT: .notdebug_foo PROGBITS 0000000000000000 {{.*}} 000008 00 0 0 0
+# UNCOMPRESSED: .debug_alloc PROGBITS 0000000000000000 {{.*}} 000040 00 A 0 0 0
## Relocations do not change.
# CHECK: Relocation section '.rela.debug_foo' at offset {{.*}} contains 2 entries:
diff --git a/llvm/test/tools/llvm-objcopy/ELF/compress-debug-sections-zstd.test b/llvm/test/tools/llvm-objcopy/ELF/compress-debug-sections-zstd.test
index d763131c4067de..dcf9c37abe5ead 100644
--- a/llvm/test/tools/llvm-objcopy/ELF/compress-debug-sections-zstd.test
+++ b/llvm/test/tools/llvm-objcopy/ELF/compress-debug-sections-zstd.test
@@ -12,8 +12,10 @@
# CHECK: Name Type Address Off Size ES Flg Lk Inf Al
# COMPRESSED: .debug_foo PROGBITS 0000000000000000 000040 {{.*}} 00 C 0 0 8
# COMPRESSED-NEXT: .notdebug_foo PROGBITS 0000000000000000 {{.*}} 000008 00 0 0 0
+# COMPRESSED: .debug_alloc PROGBITS 0000000000000000 {{.*}} 000040 00 A 0 0 0
# DECOMPRESSED: .debug_foo PROGBITS 0000000000000000 000040 000008 00 0 0 0
# DECOMPRESSED-NEXT: .notdebug_foo PROGBITS 0000000000000000 {{.*}} 000008 00 0 0 0
+# UNCOMPRESSED: .debug_alloc PROGBITS 0000000000000000 {{.*}} 000040 00 A 0 0 0
## Relocations do not change.
# CHECK: Relocation section '.rela.debug_foo' at offset {{.*}} contains 2 entries:
diff --git a/llvm/test/tools/llvm-objcopy/ELF/decompress-sections.test b/llvm/test/tools/llvm-objcopy/ELF/decompress-sections.test
new file mode 100644
index 00000000000000..4258ddbe66a3e5
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/ELF/decompress-sections.test
@@ -0,0 +1,36 @@
+# REQUIRES: zlib
+## Test decompression for different sections.
+
+# RUN: yaml2obj %s -o %t
+# RUN: llvm-objcopy --decompress-debug-sections %t %t.de
+# RUN: llvm-readelf -S %t.de | FileCheck %s
+
+# CHECK: Name Type Address Off Size ES Flg Lk Inf Al
+# CHECK: .debug_alloc PROGBITS 0000000000000000 [[#%x,]] [[#%x,]] 00 AC 0 0 0
+# CHECK-NEXT: .debug_nonalloc PROGBITS 0000000000000000 [[#%x,]] [[#%x,]] 00 0 0 1
+# CHECK-NEXT: .debugx PROGBITS 0000000000000000 [[#%x,]] [[#%x,]] 00 0 0 1
+# CHECK-NEXT: nodebug PROGBITS 0000000000000000 [[#%x,]] [[#%x,]] 00 C 0 0 0
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
+Sections:
+ - Name: .debug_alloc
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_COMPRESSED ]
+ Content: 010000000000000040000000000000000100000000000000789cd36280002d3269002f800151
+ - Name: .debug_nonalloc
+ Type: SHT_PROGBITS
+ Flags: [ SHF_COMPRESSED ]
+ Content: 010000000000000040000000000000000100000000000000789cd36280002d3269002f800151
+ - Name: .debugx
+ Type: SHT_PROGBITS
+ Flags: [ SHF_COMPRESSED ]
+ Content: 010000000000000040000000000000000100000000000000789cd36280002d3269002f800151
+ - Name: nodebug
+ Type: SHT_PROGBITS
+ Flags: [ SHF_COMPRESSED ]
+ Content: 010000000000000040000000000000000100000000000000789cd36280002d3269002f800151
>From c4aa3b08280f7ea7ec0b44edaebad1dad4022071 Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Thu, 28 Mar 2024 17:08:13 -0700
Subject: [PATCH 2/2] Update llvm/docs/CommandGuide/llvm-objcopy.rst
Co-authored-by: James Henderson <46713263+jh7370 at users.noreply.github.com>
---
llvm/docs/CommandGuide/llvm-objcopy.rst | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/llvm/docs/CommandGuide/llvm-objcopy.rst b/llvm/docs/CommandGuide/llvm-objcopy.rst
index 042ad77764e66d..57d6280d57c8bd 100644
--- a/llvm/docs/CommandGuide/llvm-objcopy.rst
+++ b/llvm/docs/CommandGuide/llvm-objcopy.rst
@@ -312,7 +312,7 @@ them.
.. option:: --compress-sections <section>=<format>
Compress or decompress sections matched by ``<section>`` using the specified
- format. Supported formatss are ``zlib`` and ``zstd``. Specify ``none`` for
+ format. Supported formats are ``zlib`` and ``zstd``. Specify ``none`` for
decompression. When a section is matched by multiple options, the last one
wins. A wildcard ``<section>`` starting with '!' is disallowed.
Sections within a segment cannot be (de)compressed.
More information about the llvm-commits
mailing list