[LLD][ELF] Fix SHF_MERGE misalignment when spilled (#119289)
Section merging can increase section alignment after potential spill
sections are created. Since this operation is never performed on spill
sections, they can keep their earlier, smaller, alignment, which
produces a misalignment if a spill occurs.
This change propagates alignment increases forward after merging.
diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp
index 546dc58..a2da554 100644
--- a/lld/ELF/OutputSections.cpp
+++ b/lld/ELF/OutputSections.cpp
@@ -253,8 +253,20 @@
for (InputSection *s : isd->sections)
commitSection(s);
}
- for (auto *ms : mergeSections)
+ for (auto *ms : mergeSections) {
+ // Merging may have increased the alignment of a spillable section. Update
+ // the alignment of potential spill sections and their containing output
+ // sections.
+ if (auto it = script->potentialSpillLists.find(ms);
+ it != script->potentialSpillLists.end()) {
+ for (PotentialSpillSection *s = it->second.head; s; s = s->next) {
+ s->addralign = std::max(s->addralign, ms->addralign);
+ s->parent->addralign = std::max(s->parent->addralign, s->addralign);
+ }
+ }
+
ms->finalizeContents();
+ }
}
static void sortByOrder(MutableArrayRef<InputSection *> in,
diff --git a/lld/test/ELF/linkerscript/section-class.test b/lld/test/ELF/linkerscript/section-class.test
index 7fce13b..5c30b63 100644
--- a/lld/test/ELF/linkerscript/section-class.test
+++ b/lld/test/ELF/linkerscript/section-class.test
@@ -310,6 +310,7 @@
.byte 0x12, 0x34
.section .b,"aM",@progbits,1
+.p2align 3
.byte 0x12
# RUN: llvm-mc -n -filetype=obj -triple=x86_64 merge.s -o merge.o
@@ -317,10 +318,11 @@
#--- spill-merge.lds
## SHF_MERGE sections are spilled according to the class refs of the first
## merged input section (the one giving the resulting section its name).
+## Spills take into account increases in section alignment due to merging.
MEMORY {
a : ORIGIN = 0, LENGTH = 1
- b : ORIGIN = 1, LENGTH = 2
- c : ORIGIN = 3, LENGTH = 2
+ b : ORIGIN = 1, LENGTH = 16
+ c : ORIGIN = 17, LENGTH = 16
}
SECTIONS {
@@ -332,12 +334,14 @@
}
# RUN: ld.lld -T spill-merge.lds merge.o -o spill-merge
-# RUN: llvm-readelf -S spill-merge | FileCheck %s --check-prefix=SPILL-MERGE
+# RUN: llvm-readelf -S -x .second spill-merge | FileCheck %s --check-prefix=SPILL-MERGE
-# SPILL-MERGE: Name Type Address Off Size
+# SPILL-MERGE: Name Type Address Off Size
# SPILL-MERGE: .first PROGBITS 0000000000000000 000190 000000
-# SPILL-MERGE-NEXT: .second PROGBITS 0000000000000001 001001 000002
-# SPILL-MERGE-NEXT: .third PROGBITS 0000000000000003 001003 000000
+# SPILL-MERGE-NEXT: .second PROGBITS 0000000000000008 001008 000009
+# SPILL-MERGE-NEXT: .third PROGBITS 0000000000000018 001018 000000
+# SPILL-MERGE: Hex dump of section '.second':
+# SPILL-MERGE-NEXT: 0x00000008 12000000 00000000 34 .
#--- link-order.s
.section .a,"a",@progbits