[llvm-branch-commits] [lld] PR for llvm/llvm-project#80390 (PR #80391)
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Feb 1 21:27:29 PST 2024
https://github.com/llvmbot created https://github.com/llvm/llvm-project/pull/80391
resolves llvm/llvm-project#80390
>From 1ddb69d220733c545cba77c59b3a27a9ee95767c Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Thu, 1 Feb 2024 21:20:27 -0800
Subject: [PATCH] [ELF] Fix compareSections assertion failure when OutputDescs
in sectionCommands are non-contiguous
In a `--defsym y0=0 -T a.lds` link where a.lds contains only INSERT
commands, the `script->sectionCommands` layout may be:
```
orphan sections
SymbolAssignment due to --defsym
sections created by INSERT commands
```
The `OutputDesc` objects are not contiguous in sortInputSections, and
`compareSections` will be called with a SymbolAssignment argument,
leading to an assertion failure.
(cherry picked from commit dee8786f70a3d62b639113343fa36ef55bdbad63)
---
lld/ELF/Writer.cpp | 12 ++++++------
lld/test/ELF/linkerscript/insert-before.test | 11 ++++++++---
2 files changed, 14 insertions(+), 9 deletions(-)
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 6f66f3615fa4a..501c10f358497 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -1518,12 +1518,12 @@ template <class ELFT> void Writer<ELFT>::sortSections() {
if (auto *osd = dyn_cast<OutputDesc>(cmd))
osd->osec.sortRank = getSectionRank(osd->osec);
if (!script->hasSectionsCommand) {
- // We know that all the OutputSections are contiguous in this case.
- auto isSection = [](SectionCommand *cmd) { return isa<OutputDesc>(cmd); };
- std::stable_sort(
- llvm::find_if(script->sectionCommands, isSection),
- llvm::find_if(llvm::reverse(script->sectionCommands), isSection).base(),
- compareSections);
+ // OutputDescs are mostly contiguous, but may be interleaved with
+ // SymbolAssignments in the presence of INSERT commands.
+ auto mid = std::stable_partition(
+ script->sectionCommands.begin(), script->sectionCommands.end(),
+ [](SectionCommand *cmd) { return isa<OutputDesc>(cmd); });
+ std::stable_sort(script->sectionCommands.begin(), mid, compareSections);
}
// Process INSERT commands and update output section attributes. From this
diff --git a/lld/test/ELF/linkerscript/insert-before.test b/lld/test/ELF/linkerscript/insert-before.test
index e6ed413639827..a72834988007c 100644
--- a/lld/test/ELF/linkerscript/insert-before.test
+++ b/lld/test/ELF/linkerscript/insert-before.test
@@ -24,8 +24,9 @@
## without making more layout changes. Address/offset assignments are different
## with a main linker script.
-# RUN: ld.lld --script %s %t1.o -o %t2
-# RUN: llvm-readelf -S -l %t2 | FileCheck --check-prefix=CHECK2 %s
+## Test non-contiguous OutputDescs in script->sectionCommands.
+# RUN: ld.lld --defsym y0=1 %s --defsym y1=1 %t1.o -o %t2
+# RUN: llvm-readelf -S -l -sX %t2 | FileCheck --check-prefix=CHECK2 %s
# CHECK2: Name Type Address Off Size ES Flg
# CHECK2-NEXT: NULL
# CHECK2-NEXT: .foo.text PROGBITS 000000000020{{.*}} [[#%x,]] 000008 00 AX
@@ -40,9 +41,13 @@
# CHECK2-NEXT: LOAD {{.*}} RW 0x1000
# CHECK2-NEXT: GNU_STACK {{.*}} RW 0
+# CHECK2: NOTYPE GLOBAL DEFAULT ABS y0
+# CHECK2: NOTYPE GLOBAL DEFAULT [[#]] (.foo.text) x0
+# CHECK2: NOTYPE GLOBAL DEFAULT ABS y1
+
SECTIONS { .byte : { BYTE(0) } } INSERT BEFORE .data;
SECTIONS { .foo.data : { *(.foo.data) } } INSERT BEFORE .data;
## The input section .foo.text is an orphan. It will be placed in .foo.text
-SECTIONS { .foo.text : {} } INSERT BEFORE .text;
+SECTIONS { .foo.text : { x0 = .; } } INSERT BEFORE .text;
More information about the llvm-branch-commits
mailing list