-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[ELF] Allow KEEP within OVERLAY #130661
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[ELF] Allow KEEP within OVERLAY #130661
Conversation
When attempting to add KEEP within an OVERLAY description, which the Linux kernel would like to do for ARCH=arm to avoid dropping the .vectors sections with '--gc-sections' [1], ld.lld errors with: ld.lld: error: ./arch/arm/kernel/vmlinux.lds:37: section pattern is expected >>> __vectors_lma = .; OVERLAY 0xffff0000 : AT(__vectors_lma) { .vectors { KEEP(*(.vectors)) } ... >>> ^ readOverlaySectionDescription() does not handle all input section description keywords, despite GNU ld's documentation stating that "The section definitions within the OVERLAY construct are identical to those within the general SECTIONS construct, except that no addresses and no memory regions may be defined for sections within an OVERLAY." Reuse the existing parsing in readInputSectionDescription(), which handles KEEP, allowing the Linux kernel's use case to work properly. [1]: https://lore.kernel.org/[email protected]/
@llvm/pr-subscribers-lld-elf Author: Nathan Chancellor (nathanchance) ChangesWhen attempting to add KEEP within an OVERLAY description, which the ld.lld: error: ./arch/arm/kernel/vmlinux.lds:37: section pattern is expected readOverlaySectionDescription() does not handle all input section Reuse the existing parsing in readInputSectionDescription(), which [1]: https://lore.kernel.org/20250221125520.14035-1-ceggers@arri.de/ Full diff: https://github.com/llvm/llvm-project/pull/130661.diff 2 Files Affected:
diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index 671a5ec4deccb..4c52bfda7a70e 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -988,20 +988,8 @@ OutputDesc *ScriptParser::readOverlaySectionDescription() {
ctx.script->createOutputSection(readName(), getCurrentLocation());
osd->osec.inOverlay = true;
expect("{");
- while (auto tok = till("}")) {
- uint64_t withFlags = 0;
- uint64_t withoutFlags = 0;
- if (tok == "INPUT_SECTION_FLAGS") {
- std::tie(withFlags, withoutFlags) = readInputSectionFlags();
- tok = till("");
- }
- if (tok == "CLASS")
- osd->osec.commands.push_back(make<InputSectionDescription>(
- StringRef{}, withFlags, withoutFlags, readSectionClassName()));
- else
- osd->osec.commands.push_back(
- readInputSectionRules(tok, withFlags, withoutFlags));
- }
+ while (auto tok = till("}"))
+ osd->osec.commands.push_back(readInputSectionDescription(tok));
osd->osec.phdrs = readOutputSectionPhdrs();
return osd;
}
diff --git a/lld/test/ELF/linkerscript/overlay-keep.test b/lld/test/ELF/linkerscript/overlay-keep.test
new file mode 100644
index 0000000000000..1b163523eead5
--- /dev/null
+++ b/lld/test/ELF/linkerscript/overlay-keep.test
@@ -0,0 +1,51 @@
+# REQUIRES: x86
+# RUN: rm -rf %t && split-file %s %t && cd %t
+# RUN: llvm-mc -filetype=obj -triple=x86_64 a.s -o a.o
+# RUN: ld.lld a.o --gc-sections --script nokeep.t -o a
+# RUN: llvm-objdump --section-headers a | FileCheck --check-prefix=NOKEEP %s
+# RUN: ld.lld a.o --gc-sections --script keep.t -o a
+# RUN: llvm-objdump --section-headers a | FileCheck --check-prefix=KEEP %s
+
+# NOKEEP: Sections:
+# NOKEEP-NEXT: Idx Name Size
+# NOKEEP-NEXT: 0 00000000
+# NOKEEP-NEXT: 1 .text 00000004
+# NOKEEP-NEXT: 2 .keep1 00000000
+
+# KEEP: Sections:
+# KEEP-NEXT: Idx Name Size
+# KEEP-NEXT: 0 00000000
+# KEEP-NEXT: 1 .text 00000004
+# KEEP-NEXT: 2 .keep1 00000004
+# KEEP-NEXT: 3 .keep2 00000004
+
+#--- a.s
+.global _start
+_start:
+ .long 1
+
+.section .keep1, "a"
+keep1:
+ .long 2
+
+.section .keep2, "a"
+keep2:
+ .long 3
+
+#--- nokeep.t
+SECTIONS {
+ .text : { *(.text) }
+ OVERLAY 0x1000 : AT ( 0x4000 ) {
+ .keep1 { *(.keep1) }
+ .keep2 { *(.keep2) }
+ }
+}
+
+#--- keep.t
+SECTIONS {
+ .text : { *(.text) }
+ OVERLAY 0x1000 : AT ( 0x4000 ) {
+ .keep1 { KEEP(*(.keep1)) }
+ .keep2 { KEEP(*(.keep2)) }
+ }
+}
|
@llvm/pr-subscribers-lld Author: Nathan Chancellor (nathanchance) ChangesWhen attempting to add KEEP within an OVERLAY description, which the ld.lld: error: ./arch/arm/kernel/vmlinux.lds:37: section pattern is expected readOverlaySectionDescription() does not handle all input section Reuse the existing parsing in readInputSectionDescription(), which [1]: https://lore.kernel.org/20250221125520.14035-1-ceggers@arri.de/ Full diff: https://github.com/llvm/llvm-project/pull/130661.diff 2 Files Affected:
diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp
index 671a5ec4deccb..4c52bfda7a70e 100644
--- a/lld/ELF/ScriptParser.cpp
+++ b/lld/ELF/ScriptParser.cpp
@@ -988,20 +988,8 @@ OutputDesc *ScriptParser::readOverlaySectionDescription() {
ctx.script->createOutputSection(readName(), getCurrentLocation());
osd->osec.inOverlay = true;
expect("{");
- while (auto tok = till("}")) {
- uint64_t withFlags = 0;
- uint64_t withoutFlags = 0;
- if (tok == "INPUT_SECTION_FLAGS") {
- std::tie(withFlags, withoutFlags) = readInputSectionFlags();
- tok = till("");
- }
- if (tok == "CLASS")
- osd->osec.commands.push_back(make<InputSectionDescription>(
- StringRef{}, withFlags, withoutFlags, readSectionClassName()));
- else
- osd->osec.commands.push_back(
- readInputSectionRules(tok, withFlags, withoutFlags));
- }
+ while (auto tok = till("}"))
+ osd->osec.commands.push_back(readInputSectionDescription(tok));
osd->osec.phdrs = readOutputSectionPhdrs();
return osd;
}
diff --git a/lld/test/ELF/linkerscript/overlay-keep.test b/lld/test/ELF/linkerscript/overlay-keep.test
new file mode 100644
index 0000000000000..1b163523eead5
--- /dev/null
+++ b/lld/test/ELF/linkerscript/overlay-keep.test
@@ -0,0 +1,51 @@
+# REQUIRES: x86
+# RUN: rm -rf %t && split-file %s %t && cd %t
+# RUN: llvm-mc -filetype=obj -triple=x86_64 a.s -o a.o
+# RUN: ld.lld a.o --gc-sections --script nokeep.t -o a
+# RUN: llvm-objdump --section-headers a | FileCheck --check-prefix=NOKEEP %s
+# RUN: ld.lld a.o --gc-sections --script keep.t -o a
+# RUN: llvm-objdump --section-headers a | FileCheck --check-prefix=KEEP %s
+
+# NOKEEP: Sections:
+# NOKEEP-NEXT: Idx Name Size
+# NOKEEP-NEXT: 0 00000000
+# NOKEEP-NEXT: 1 .text 00000004
+# NOKEEP-NEXT: 2 .keep1 00000000
+
+# KEEP: Sections:
+# KEEP-NEXT: Idx Name Size
+# KEEP-NEXT: 0 00000000
+# KEEP-NEXT: 1 .text 00000004
+# KEEP-NEXT: 2 .keep1 00000004
+# KEEP-NEXT: 3 .keep2 00000004
+
+#--- a.s
+.global _start
+_start:
+ .long 1
+
+.section .keep1, "a"
+keep1:
+ .long 2
+
+.section .keep2, "a"
+keep2:
+ .long 3
+
+#--- nokeep.t
+SECTIONS {
+ .text : { *(.text) }
+ OVERLAY 0x1000 : AT ( 0x4000 ) {
+ .keep1 { *(.keep1) }
+ .keep2 { *(.keep2) }
+ }
+}
+
+#--- keep.t
+SECTIONS {
+ .text : { *(.text) }
+ OVERLAY 0x1000 : AT ( 0x4000 ) {
+ .keep1 { KEEP(*(.keep1)) }
+ .keep2 { KEEP(*(.keep2)) }
+ }
+}
|
Should there be tests that we don't support the things that GNU says are disallowed in overlays? |
I think that |
When attempting to add
KEEP
within anOVERLAY
description, which the Linux kernel would like to do forARCH=arm
to avoid dropping the.vectors
sections with--gc-sections
(patch),ld.lld
errors with:readOverlaySectionDescription()
does not handle all input section description keywords, despite GNU ld's documentation stating thatReuse the existing parsing in
readInputSectionDescription()
, which handlesKEEP
, allowing the Linux kernel's use case to work properly.