[lld] [lld][ELF] Fix crash when relocations proceed relocated section (PR #156354)

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 18 20:35:09 PDT 2025


https://github.com/MaskRay updated https://github.com/llvm/llvm-project/pull/156354

>From 3cc58a30bbdff74179b45bf0001943c200947186 Mon Sep 17 00:00:00 2001
From: koumeiyuan <koumeiyuan at huawei.com>
Date: Fri, 29 Aug 2025 09:07:10 +0000
Subject: [PATCH 1/3] [lld][ELF] Fix crash when relocations proceed relocated
 section

Fix the error generated during the linking process when the relocation section is placed before the relocated section and the relocated section is not defined in the linker script.
---
 lld/ELF/LinkerScript.cpp                      | 12 ++++--
 .../ELF/linkerscript/orphan-sections-init.s   | 37 +++++++++++++++++++
 2 files changed, 46 insertions(+), 3 deletions(-)
 create mode 100644 lld/test/ELF/linkerscript/orphan-sections-init.s

diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index 921128dae2bdb..4d66408a6510e 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -1037,10 +1037,16 @@ void LinkerScript::addOrphanSections() {
     if (ctx.arg.relocatable && (isec->flags & SHF_LINK_ORDER))
       continue;
 
-    if (auto *sec = dyn_cast<InputSection>(isec))
-      if (InputSectionBase *rel = sec->getRelocatedSection())
-        if (auto *relIS = dyn_cast_or_null<InputSectionBase>(rel->parent))
+    if (auto *sec = dyn_cast<InputSection>(isec)) {
+      if (InputSectionBase *relocated = sec->getRelocatedSection()) {
+        // Ensure creation of OutputSection for relocated section before
+        // relocation section
+        if (auto *relIS = dyn_cast_or_null<InputSectionBase>(relocated))
           add(relIS);
+        if (auto *relIS = dyn_cast_or_null<InputSectionBase>(relocated->parent))
+          add(relIS);
+      }
+    }
     add(isec);
     if (ctx.arg.relocatable)
       for (InputSectionBase *depSec : isec->dependentSections)
diff --git a/lld/test/ELF/linkerscript/orphan-sections-init.s b/lld/test/ELF/linkerscript/orphan-sections-init.s
new file mode 100644
index 0000000000000..fa70d29d41130
--- /dev/null
+++ b/lld/test/ELF/linkerscript/orphan-sections-init.s
@@ -0,0 +1,37 @@
+# REQUIRES: x86
+# RUN: rm -rf %t && mkdir -p %t
+# RUN: split-file %s %t && cd %t
+
+## Test that lld's orphan section placement can handle a relocatable link where
+## the relocation section is seen before the relocated section. 
+
+## Create a relocatable object with the relocations before the relocated section
+# RUN: llvm-mc -filetype=obj -triple=x86_64 foo.s -o foo.o
+# RUN: ld.lld -r  foo.o -T script.ld -o foo_mc.o
+
+## Rename the sections to make them orphans
+# RUN: llvm-objcopy \
+# RUN: --rename-section .text=.com.text \
+# RUN: --rename-section .rela.text=.rela.com.text \
+# RUN: foo_mc.o foo_mc.o
+
+# RUN: ld.lld -r foo_mc.o  -T script.ld -o foo_mc_after.o
+# RUN:  llvm-readelf -S foo_mc_after.o | FileCheck %s
+# CHECK:       .com.text         PROGBITS        0000000000000000 000040 000007 00  AX  0   0 16
+# CHECK-NEXT:  .rela.com.text    RELA            0000000000000000 000048 000018 18   I  4   1  8
+
+#--- foo.s
+  .text
+  .globl	foo
+  .p2align	4
+  .type	foo, at function
+foo:
+  mov $bar, %rax
+
+#--- script.ld
+SECTIONS
+{
+  .rela.text    0 : { *(.rela.text) }
+  .text         0 : { *(.text) }
+}
+

>From f1e714b8e04612f7c1ac25c2123e2075ea09dcbf Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Thu, 18 Sep 2025 09:38:52 -0700
Subject: [PATCH 2/3] Better fix for 156417

---
 lld/ELF/LinkerScript.cpp                      | 18 +++++------
 lld/test/ELF/linkerscript/orphan-relocation.s | 31 +++++++++++++++++++
 2 files changed, 39 insertions(+), 10 deletions(-)
 create mode 100644 lld/test/ELF/linkerscript/orphan-relocation.s

diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index 4d66408a6510e..218c9d3a86184 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -1021,10 +1021,6 @@ void LinkerScript::addOrphanSections() {
     }
   };
 
-  // For further --emit-reloc handling code we need target output section
-  // to be created before we create relocation output section, so we want
-  // to create target sections first. We do not want priority handling
-  // for synthetic sections because them are special.
   size_t n = 0;
   for (InputSectionBase *isec : ctx.inputSections) {
     // Process InputSection and MergeInputSection.
@@ -1039,12 +1035,14 @@ void LinkerScript::addOrphanSections() {
 
     if (auto *sec = dyn_cast<InputSection>(isec)) {
       if (InputSectionBase *relocated = sec->getRelocatedSection()) {
-        // Ensure creation of OutputSection for relocated section before
-        // relocation section
-        if (auto *relIS = dyn_cast_or_null<InputSectionBase>(relocated))
-          add(relIS);
-        if (auto *relIS = dyn_cast_or_null<InputSectionBase>(relocated->parent))
-          add(relIS);
+        // For --emit-relocs and -r, ensure the output section for .text.foo
+        // is created before the output section for .rela.text.foo.
+        add(relocated);
+        // EhInputSection sections are not added to ctx.inputSections. If we see
+        // .rela.eh_frame, ensure the output section for the synthetic
+        // EhFrameSection is created first.
+        if (auto *p = dyn_cast_or_null<InputSectionBase>(relocated->parent))
+          add(p);
       }
     }
     add(isec);
diff --git a/lld/test/ELF/linkerscript/orphan-relocation.s b/lld/test/ELF/linkerscript/orphan-relocation.s
new file mode 100644
index 0000000000000..adf5cac6c3e82
--- /dev/null
+++ b/lld/test/ELF/linkerscript/orphan-relocation.s
@@ -0,0 +1,31 @@
+# REQUIRES: x86
+## Test that orphan section placement can handle a relocatable link where
+## the relocation section is seen before the relocated section.
+
+# RUN: rm -rf %t && split-file %s %t && cd %t
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64 a.s -o a.o
+## In a.ro, .rela.text precedes its relocated section.
+# RUN: ld.lld -r a.o -T 1.lds -o a.ro
+# RUN: llvm-readelf -S a.ro | FileCheck %s
+# CHECK:       .rela.text    RELA
+# CHECK-NEXT:  .text         PROGBITS
+
+# RUN: llvm-objcopy --rename-section .text=.com.text --rename-section .rela.text=.rela.com.text a.ro a1.o
+
+## Regression test for #156354 , where we added an orphan RELA section before its relocated section.
+# RUN: ld.lld -r a1.o -o a1.ro
+# RUN: llvm-readelf -S a1.ro | FileCheck %s --check-prefix=CHECK1
+# CHECK1:       .com.text         PROGBITS
+# CHECK1-NEXT:  .rela.com.text    RELA
+
+#--- a.s
+.globl foo
+foo:
+  call foo
+
+#--- 1.lds
+SECTIONS {
+  .rela.text 0 : { *(.rela.text) }
+  .text      0 : { *(.text) }
+}

>From cc33e42f21d3ac8da653169c234aefbfa1326c8a Mon Sep 17 00:00:00 2001
From: Fangrui Song <i at maskray.me>
Date: Thu, 18 Sep 2025 20:34:53 -0700
Subject: [PATCH 3/3] delete old test

---
 .../ELF/linkerscript/orphan-sections-init.s   | 37 -------------------
 1 file changed, 37 deletions(-)
 delete mode 100644 lld/test/ELF/linkerscript/orphan-sections-init.s

diff --git a/lld/test/ELF/linkerscript/orphan-sections-init.s b/lld/test/ELF/linkerscript/orphan-sections-init.s
deleted file mode 100644
index fa70d29d41130..0000000000000
--- a/lld/test/ELF/linkerscript/orphan-sections-init.s
+++ /dev/null
@@ -1,37 +0,0 @@
-# REQUIRES: x86
-# RUN: rm -rf %t && mkdir -p %t
-# RUN: split-file %s %t && cd %t
-
-## Test that lld's orphan section placement can handle a relocatable link where
-## the relocation section is seen before the relocated section. 
-
-## Create a relocatable object with the relocations before the relocated section
-# RUN: llvm-mc -filetype=obj -triple=x86_64 foo.s -o foo.o
-# RUN: ld.lld -r  foo.o -T script.ld -o foo_mc.o
-
-## Rename the sections to make them orphans
-# RUN: llvm-objcopy \
-# RUN: --rename-section .text=.com.text \
-# RUN: --rename-section .rela.text=.rela.com.text \
-# RUN: foo_mc.o foo_mc.o
-
-# RUN: ld.lld -r foo_mc.o  -T script.ld -o foo_mc_after.o
-# RUN:  llvm-readelf -S foo_mc_after.o | FileCheck %s
-# CHECK:       .com.text         PROGBITS        0000000000000000 000040 000007 00  AX  0   0 16
-# CHECK-NEXT:  .rela.com.text    RELA            0000000000000000 000048 000018 18   I  4   1  8
-
-#--- foo.s
-  .text
-  .globl	foo
-  .p2align	4
-  .type	foo, at function
-foo:
-  mov $bar, %rax
-
-#--- script.ld
-SECTIONS
-{
-  .rela.text    0 : { *(.rela.text) }
-  .text         0 : { *(.text) }
-}
-



More information about the llvm-commits mailing list