[lld] [ELF] Reject SHF_LINK_ORDER on a non-regular section (PR #219816)

Matt Turner via llvm-commits llvm-commits at lists.llvm.org
Sun Sep 6 18:54:37 PDT 2026


https://github.com/mattst88 updated https://github.com/llvm/llvm-project/pull/219816

>From cbd5f813a6edef27b243132505d9de274306ded8 Mon Sep 17 00:00:00 2001
From: Matt Turner <mattst88 at gmail.com>
Date: Sun, 30 Aug 2026 11:15:10 -0400
Subject: [PATCH] [ELF] Reject SHF_LINK_ORDER on a non-regular section

initializeSections() unconditionally casts a linked-to section to
InputSection, but SHT_STRTAB, mergeable, and .eh_frame sections are not
InputSections, so the cast is invalid for them. Diagnose these cases
instead of asserting.

A follow-up PR will handle discarding an SHF_LINK_ORDER section whose
linked-to section is already discarded.

Assisted-by: Claude Code
---
 lld/ELF/InputFiles.cpp                 | 10 +++++-
 lld/test/ELF/linkorder-nonregular.test | 46 ++++++++++++++++++++++++++
 2 files changed, 55 insertions(+), 1 deletion(-)
 create mode 100644 lld/test/ELF/linkorder-nonregular.test

diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp
index 23649d6200719..4c4b211ab64fc 100644
--- a/lld/ELF/InputFiles.cpp
+++ b/lld/ELF/InputFiles.cpp
@@ -951,9 +951,17 @@ void ObjFile<ELFT>::initializeSections(bool ignoreComdats,
       continue;
     }
 
+    // dependentSections can only hold InputSections.
+    StringRef name = check(obj.getSectionName(sec, shstrtab));
+    auto *isec = dyn_cast_or_null<InputSection>(this->sections[i]);
+    if (!isec || (sec.sh_flags & SHF_MERGE) || name == ".eh_frame") {
+      ErrAlways(ctx) << this << ":(" << name
+                     << "): unsupported section for SHF_LINK_ORDER";
+      continue;
+    }
+
     // A SHF_LINK_ORDER section is discarded if its linked-to section is
     // discarded.
-    InputSection *isec = cast<InputSection>(this->sections[i]);
     linkSec->dependentSections.push_back(isec);
     if (!isa<InputSection>(linkSec))
       ErrAlways(ctx)
diff --git a/lld/test/ELF/linkorder-nonregular.test b/lld/test/ELF/linkorder-nonregular.test
new file mode 100644
index 0000000000000..c2736626c89d3
--- /dev/null
+++ b/lld/test/ELF/linkorder-nonregular.test
@@ -0,0 +1,46 @@
+# REQUIRES: x86
+## dependentSections holds plain InputSections. An SHT_STRTAB section has no
+## InputSectionBase at all, a mergeable one has a MergeInputSection and
+## .eh_frame has an EhInputSection, so none of the three can record the
+## SHF_LINK_ORDER dependency. All three used to assert in cast<InputSection>.
+
+# RUN: yaml2obj %s -o %t.o
+# RUN: not ld.lld %t.o -o /dev/null -e 0 2>&1 | FileCheck %s -DFILE=%t.o
+
+# CHECK-DAG: error: [[FILE]]:(lo_strtab): unsupported section for SHF_LINK_ORDER
+# CHECK-DAG: error: [[FILE]]:(lo_merge): unsupported section for SHF_LINK_ORDER
+# CHECK-DAG: error: [[FILE]]:(.eh_frame): unsupported section for SHF_LINK_ORDER
+
+## The diagnostic must not depend on whether this link happens to build a
+## MergeInputSection or an EhInputSection: -O0 does not merge, and -r keeps
+## .eh_frame a plain InputSection.
+# RUN: not ld.lld %t.o -o /dev/null -e 0 -O0 2>&1 | FileCheck %s -DFILE=%t.o
+# RUN: not ld.lld -r %t.o -o /dev/null 2>&1 | FileCheck %s -DFILE=%t.o
+
+--- !ELF
+FileHeader:
+  Class:   ELFCLASS64
+  Data:    ELFDATA2LSB
+  Type:    ET_REL
+  Machine: EM_X86_64
+Sections:
+  - Name:    .text
+    Type:    SHT_PROGBITS
+    Flags:   [ SHF_ALLOC, SHF_EXECINSTR ]
+    Size:    1
+  - Name:    lo_strtab
+    Type:    SHT_STRTAB
+    Flags:   [ SHF_ALLOC, SHF_LINK_ORDER ]
+    Link:    .text
+    Size:    8
+  - Name:    lo_merge
+    Type:    SHT_PROGBITS
+    Flags:   [ SHF_ALLOC, SHF_MERGE, SHF_LINK_ORDER ]
+    Link:    .text
+    EntSize: 4
+    Size:    8
+  - Name:    .eh_frame
+    Type:    SHT_PROGBITS
+    Flags:   [ SHF_ALLOC, SHF_LINK_ORDER ]
+    Link:    .text
+    Size:    0



More information about the llvm-commits mailing list