[llvm-branch-commits] [lld] release/22.x: [lld][ELF] Fix crash when relaxation pass encounters synthetic sections (PR #186725)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Sun Mar 15 19:21:29 PDT 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-lld-elf

Author: None (llvmbot)

<details>
<summary>Changes</summary>

Backport 655d5e7f690c37aad1da453ed5e3f354d5781d68

Requested by: @<!-- -->wangleiat

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


4 Files Affected:

- (modified) lld/ELF/Arch/LoongArch.cpp (+4-1) 
- (modified) lld/ELF/Arch/RISCV.cpp (+8-1) 
- (added) lld/test/ELF/loongarch-relax-synthetic-in-text.s (+31) 
- (added) lld/test/ELF/riscv-relax-synthetic-in-text.s (+33) 


``````````diff
diff --git a/lld/ELF/Arch/LoongArch.cpp b/lld/ELF/Arch/LoongArch.cpp
index 9682b4722ac1e..7e6f14a7cc8f4 100644
--- a/lld/ELF/Arch/LoongArch.cpp
+++ b/lld/ELF/Arch/LoongArch.cpp
@@ -1579,7 +1579,8 @@ bool LoongArch::relaxOnce(int pass) const {
     if (!(osec->flags & SHF_EXECINSTR))
       continue;
     for (InputSection *sec : getInputSections(*osec, storage))
-      changed |= relax(ctx, *sec);
+      if (sec->relaxAux)
+        changed |= relax(ctx, *sec);
   }
   return changed;
 }
@@ -1591,6 +1592,8 @@ void LoongArch::finalizeRelax(int passes) const {
     if (!(osec->flags & SHF_EXECINSTR))
       continue;
     for (InputSection *sec : getInputSections(*osec, storage)) {
+      if (!sec->relaxAux)
+        continue;
       RelaxAux &aux = *sec->relaxAux;
       if (!aux.relocDeltas)
         continue;
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index bdb728bc19e7b..4c2bca27e1047 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -706,6 +706,8 @@ void elf::initSymbolAnchors(Ctx &ctx) {
     if (!(osec->flags & SHF_EXECINSTR))
       continue;
     for (InputSection *sec : getInputSections(*osec, storage)) {
+      if (isa<SyntheticSection>(sec))
+        continue;
       sec->relaxAux = make<RelaxAux>();
       if (sec->relocs().size()) {
         sec->relaxAux->relocDeltas =
@@ -750,6 +752,8 @@ void elf::initSymbolAnchors(Ctx &ctx) {
     if (!(osec->flags & SHF_EXECINSTR))
       continue;
     for (InputSection *sec : getInputSections(*osec, storage)) {
+      if (!sec->relaxAux)
+        continue;
       llvm::sort(sec->relaxAux->anchors, [](auto &a, auto &b) {
         return std::make_pair(a.offset, a.end) <
                std::make_pair(b.offset, b.end);
@@ -980,7 +984,8 @@ bool RISCV::relaxOnce(int pass) const {
     if (!(osec->flags & SHF_EXECINSTR))
       continue;
     for (InputSection *sec : getInputSections(*osec, storage))
-      changed |= relax(ctx, pass, *sec);
+      if (sec->relaxAux)
+        changed |= relax(ctx, pass, *sec);
   }
   return changed;
 }
@@ -1104,6 +1109,8 @@ void RISCV::finalizeRelax(int passes) const {
     if (!(osec->flags & SHF_EXECINSTR))
       continue;
     for (InputSection *sec : getInputSections(*osec, storage)) {
+      if (!sec->relaxAux)
+        continue;
       RelaxAux &aux = *sec->relaxAux;
       if (!aux.relocDeltas)
         continue;
diff --git a/lld/test/ELF/loongarch-relax-synthetic-in-text.s b/lld/test/ELF/loongarch-relax-synthetic-in-text.s
new file mode 100644
index 0000000000000..67c355e5a7595
--- /dev/null
+++ b/lld/test/ELF/loongarch-relax-synthetic-in-text.s
@@ -0,0 +1,31 @@
+# REQUIRES: loongarch
+# RUN: rm -rf %t && split-file %s %t
+# RUN: llvm-mc --filetype=obj -triple=loongarch64 -mattr=+relax %t/a.s -o %t/a.o
+
+## Do not crash when we encounter a synthetic section (like .got) that has
+## been placed inside an executable output section via a linker script.
+## Synthetic sections do not have relaxAux data structures initialized.
+
+# RUN: ld.lld -T %t/a.ld %t/a.o -o %t/a.out
+# RUN: llvm-objdump -s %t/a.out | FileCheck %s
+
+# CHECK:      Contents of section .text:
+# CHECK-NEXT: 0400001a 8440c002 10000000 00000000
+
+#--- a.s
+.global _start
+_start:
+  pcalau12i $a0, %got_pc_hi20(sym)
+  ld.d $a0, $a0, %got_pc_lo12(sym)
+
+.data
+sym:
+  .word 0
+
+#--- a.ld
+SECTIONS {
+  .text : {
+    *(.text)
+    *(.got)
+  }
+}
diff --git a/lld/test/ELF/riscv-relax-synthetic-in-text.s b/lld/test/ELF/riscv-relax-synthetic-in-text.s
new file mode 100644
index 0000000000000..d892da3fdd3a4
--- /dev/null
+++ b/lld/test/ELF/riscv-relax-synthetic-in-text.s
@@ -0,0 +1,33 @@
+# REQUIRES: riscv
+# RUN: rm -rf %t && split-file %s %t
+# RUN: llvm-mc --filetype=obj -triple=riscv64 -mattr=+relax %t/a.s -o %t/a.o
+
+## Do not crash when we encounter a synthetic section (like .got) that has
+## been placed inside an executable output section via a linker script.
+## Synthetic sections do not have relaxAux data structures initialized.
+
+# RUN: ld.lld -T %t/a.ld %t/a.o -o %t/a.out
+# RUN: llvm-objdump -s %t/a.out | FileCheck %s
+
+# CHECK:      Contents of section .text:
+# CHECK-NEXT: 17050000 03350501 00000000 00000000
+# CHECK-NEXT: 18000000 00000000
+
+#--- a.s
+.global _start
+_start:
+1:
+  auipc a0, %got_pcrel_hi(sym)
+  ld a0, %pcrel_lo(1b)(a0)
+
+.data
+sym:
+  .word 0
+
+#--- a.ld
+SECTIONS {
+  .text : {
+    *(.text)
+    *(.got)
+  }
+}

``````````

</details>


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


More information about the llvm-branch-commits mailing list