[lld] [ELF] Add -z nosectionheader (PR #101286)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 30 21:53:39 PDT 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lld-elf
@llvm/pr-subscribers-lld
Author: Fangrui Song (MaskRay)
<details>
<summary>Changes</summary>
GNU ld since 2.41 supports this option, which is mildly useful. It omits
the section header table and non-ALLOC sections (including
.symtab/.strtab (--strip-all)).
This option is simple to implement and might be used by LLDB to test
program headers parsing without the section header table (#<!-- -->100900).
-z sectionheader, which is the default, is also added.
---
Full diff: https://github.com/llvm/llvm-project/pull/101286.diff
7 Files Affected:
- (modified) lld/ELF/Config.h (+1)
- (modified) lld/ELF/Driver.cpp (+7-1)
- (modified) lld/ELF/SyntheticSections.cpp (+4-2)
- (modified) lld/ELF/Writer.cpp (+9-2)
- (modified) lld/docs/ld.lld.1 (+3)
- (modified) lld/test/CMakeLists.txt (+1)
- (added) lld/test/ELF/zsectionheader.s (+36)
``````````diff
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index 6abd929d2343d..183dc88a93e2f 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -333,6 +333,7 @@ struct Config {
bool zPacPlt;
bool zRelro;
bool zRodynamic;
+ bool zSectionHeader;
bool zShstk;
bool zStartStopGC;
uint8_t zStartStopVisibility;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 7e0a5a1937c7f..a8c52e8c2b8e1 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -447,6 +447,8 @@ static void checkOptions() {
error("-r and --export-dynamic may not be used together");
if (config->debugNames)
error("-r and --debug-names may not be used together");
+ if (!config->zSectionHeader)
+ error("-r and -z nosectionheader may not be used together");
}
if (config->executeOnly) {
@@ -836,6 +838,8 @@ static ICFLevel getICF(opt::InputArgList &args) {
static StripPolicy getStrip(opt::InputArgList &args) {
if (args.hasArg(OPT_relocatable))
return StripPolicy::None;
+ if (!config->zSectionHeader)
+ return StripPolicy::All;
auto *arg = args.getLastArg(OPT_strip_all, OPT_strip_debug);
if (!arg)
@@ -1411,7 +1415,9 @@ static void readConfigs(opt::InputArgList &args) {
config->soName = args.getLastArgValue(OPT_soname);
config->sortSection = getSortSection(args);
config->splitStackAdjustSize = args::getInteger(args, OPT_split_stack_adjust_size, 16384);
- config->strip = getStrip(args);
+ config->zSectionHeader =
+ getZFlag(args, "sectionheader", "nosectionheader", true);
+ config->strip = getStrip(args); // needs zSectionHeader
config->sysroot = args.getLastArgValue(OPT_sysroot);
config->target1Rel = args.hasFlag(OPT_target1_rel, OPT_target1_abs, false);
config->target2 = getTarget2(args);
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index b767392c4456c..d0b1933121fa2 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -4665,7 +4665,8 @@ template <class ELFT> void elf::createSyntheticSections() {
auto add = [](SyntheticSection &sec) { ctx.inputSections.push_back(&sec); };
- in.shStrTab = std::make_unique<StringTableSection>(".shstrtab", false);
+ if (config->zSectionHeader)
+ in.shStrTab = std::make_unique<StringTableSection>(".shstrtab", false);
Out::programHeaders = make<OutputSection>("", 0, SHF_ALLOC);
Out::programHeaders->addralign = config->wordsize;
@@ -4917,7 +4918,8 @@ template <class ELFT> void elf::createSyntheticSections() {
add(*in.symTab);
if (in.symTabShndx)
add(*in.symTabShndx);
- add(*in.shStrTab);
+ if (in.shStrTab)
+ add(*in.shStrTab);
if (in.strTab)
add(*in.strTab);
}
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 5cffdb771a738..515ebb7453ad5 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -1875,13 +1875,16 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
sortSections();
// Create a list of OutputSections, assign sectionIndex, and populate
- // in.shStrTab.
+ // in.shStrTab. If -z nosectionheader is specified, drop non-ALLOC sections.
for (SectionCommand *cmd : script->sectionCommands)
if (auto *osd = dyn_cast<OutputDesc>(cmd)) {
OutputSection *osec = &osd->osec;
+ if (!in.shStrTab && !(osec->flags & SHF_ALLOC))
+ continue;
outputSections.push_back(osec);
osec->sectionIndex = outputSections.size();
- osec->shName = in.shStrTab->addString(osec->name);
+ if (in.shStrTab)
+ osec->shName = in.shStrTab->addString(osec->name);
}
// Prefer command line supplied address over other constraints.
@@ -2703,6 +2706,10 @@ template <class ELFT> void Writer<ELFT>::writeHeader() {
auto *eHdr = reinterpret_cast<Elf_Ehdr *>(Out::bufferStart);
eHdr->e_type = getELFType();
eHdr->e_entry = getEntryAddr();
+
+ // If -z nosectionheader is specified, omit the section header table.
+ if (!in.shStrTab)
+ return;
eHdr->e_shoff = sectionHeaderOff;
// Write the section header table.
diff --git a/lld/docs/ld.lld.1 b/lld/docs/ld.lld.1
index f9a00b7875038..b22cb36283771 100644
--- a/lld/docs/ld.lld.1
+++ b/lld/docs/ld.lld.1
@@ -857,6 +857,9 @@ The object will omit the
.Dv PT_GNU_RELRO
segment.
.Pp
+.It Cm nosectionheader
+Don't generate the section header table.
+.Pp
.It Cm notext
Allow relocations against read-only segments.
Sets the
diff --git a/lld/test/CMakeLists.txt b/lld/test/CMakeLists.txt
index 25d8f0a424926..5d4a2757c529b 100644
--- a/lld/test/CMakeLists.txt
+++ b/lld/test/CMakeLists.txt
@@ -64,6 +64,7 @@ if (NOT LLD_BUILT_STANDALONE)
llvm-profdata
llvm-readelf
llvm-readobj
+ llvm-strings
llvm-strip
llvm-symbolizer
not
diff --git a/lld/test/ELF/zsectionheader.s b/lld/test/ELF/zsectionheader.s
new file mode 100644
index 0000000000000..c1e654ac1082d
--- /dev/null
+++ b/lld/test/ELF/zsectionheader.s
@@ -0,0 +1,36 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
+# RUN: ld.lld -shared -z nosectionheader -z sectionheader %t.o -o %t.so 2>&1 | count 0
+# RUN: llvm-readelf -hS %t.so | FileCheck %s --check-prefixes=CHECK,SHDR
+
+# RUN: ld.lld -shared -z nosectionheader %t.o -o %t0.so
+# RUN: llvm-readelf -h --dyn-syms %t0.so | FileCheck %s --check-prefixes=CHECK,NOSHDR
+# RUN: llvm-strings %t0.so | FileCheck %s --check-prefixes=NOSHDR-STR
+
+# CHECK: Size of this header: 64 (bytes)
+# CHECK-NEXT: Size of program headers: 56 (bytes)
+# CHECK-NEXT: Number of program headers: 6
+# CHECK-NEXT: Size of section headers: 64 (bytes)
+# SHDR-NEXT: Number of section headers: 13
+# SHDR-NEXT: Section header string table index: 11
+# NOSHDR-NEXT: Number of section headers: 0
+# NOSHDR-NEXT: Section header string table index: 0
+
+# SHDR: Section Headers:
+# NOSHDR: Symbol table for image contains 2 entries:
+# NOSHDR: _start
+
+## _start occurs as a dynamic string table entry. There is no static string table
+## entry. `nonalloc` is not in the output.
+# NOSHDR-STR: _start
+# NOSHDR-STR-NOT: _start
+
+# RUN: not ld.lld -r -z nosectionheader %t.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR
+
+# ERR: error: -r and -z nosectionheader may not be used together
+
+.globl _start
+_start:
+
+.section nonalloc,""
+.asciz "_start"
``````````
</details>
https://github.com/llvm/llvm-project/pull/101286
More information about the llvm-commits
mailing list