[lld] [LLD][ELF] Fix SHF_MERGE misalignment when spilled (PR #119289)

via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 9 15:40:52 PST 2024


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-lld-elf

Author: Daniel Thornburgh (mysterymath)

<details>
<summary>Changes</summary>

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.

---
Full diff: https://github.com/llvm/llvm-project/pull/119289.diff


2 Files Affected:

- (modified) lld/ELF/OutputSections.cpp (+16-1) 
- (modified) lld/test/ELF/linkerscript/section-class.test (+6-4) 


``````````diff
diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp
index 546dc58b4bc843..5e77eeb1ed5988 100644
--- a/lld/ELF/OutputSections.cpp
+++ b/lld/ELF/OutputSections.cpp
@@ -249,12 +249,27 @@ void OutputSection::finalizeInputSections() {
     // catch misuses.
     isd->sectionBases.clear();
 
+
     // Some input sections may be removed from the list after ICF.
     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 (!script->potentialSpillLists.empty()) {
+      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 7fce13bfe3e025..ae1a5026ef0490 100644
--- a/lld/test/ELF/linkerscript/section-class.test
+++ b/lld/test/ELF/linkerscript/section-class.test
@@ -310,6 +310,7 @@ SECTIONS {
 .byte 0x12, 0x34
 
 .section .b,"aM", at progbits,1
+.p2align 1
 .byte 0x12
 
 # RUN: llvm-mc -n -filetype=obj -triple=x86_64 merge.s -o merge.o
@@ -317,10 +318,11 @@ SECTIONS {
 #--- 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 = 4
+  c : ORIGIN = 5, LENGTH = 4
 }
 
 SECTIONS {
@@ -336,8 +338,8 @@ SECTIONS {
 
 # 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 0000000000000002 001002 000003
+# SPILL-MERGE-NEXT: .third  PROGBITS 0000000000000006 001006 000000
 
 #--- link-order.s
 .section .a,"a", at progbits

``````````

</details>


https://github.com/llvm/llvm-project/pull/119289


More information about the llvm-commits mailing list