[lld] 09abee8 - [ELF] Support non-section Defined symbols at MergeInputSection end (#195801)
via llvm-commits
llvm-commits at lists.llvm.org
Tue May 5 10:11:47 PDT 2026
Author: Fangrui Song
Date: 2026-05-05T10:11:42-07:00
New Revision: 09abee845d2136630fc3f50524148daa55a740a8
URL: https://github.com/llvm/llvm-project/commit/09abee845d2136630fc3f50524148daa55a740a8
DIFF: https://github.com/llvm/llvm-project/commit/09abee845d2136630fc3f50524148daa55a740a8.diff
LOG: [ELF] Support non-section Defined symbols at MergeInputSection end (#195801)
Commit bb443359a8ad ("[ELF] Validate merge section offsets in getSymVA
and
match GNU ld") accepts offset == section_size for section-symbol
references
in getSymVA, and skips the out-of-bounds case in MarkLive.
This patch extends the support for non-section Defined symbols,
modifying the per-symbol pre-resolution added by commit 42cc45477727
("[ELF] Optimize binary search in getSectionPiece").
Fix #118148
Added:
Modified:
lld/ELF/SyntheticSections.cpp
lld/test/ELF/merge-piece-oob.s
Removed:
################################################################################
diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index 3c08c392ff214..805d0530f12ad 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -3813,14 +3813,17 @@ template <class ELFT> void elf::splitSections(Ctx &ctx) {
// For non-section Defined symbols in merge sections, pre-resolve the piece
// index to avoid potentially repeated binary search (MarkLive, RelocScan,
// includeInSymtab). Encode each non-section Defined symbol's value as
- // ((pieceIdx + 1) << mergeValueShift) | intraPieceOffset.
+ // ((pieceIdx + 1) << mergeValueShift) | intraPieceOffset. A one-past-end
+ // label is anchored on the last piece.
auto resolve = [](Defined *d) {
auto *ms = dyn_cast_or_null<MergeInputSection>(d->section);
if (!ms || d->isSection())
return;
- SectionPiece &piece = ms->getSectionPiece(d->value);
+ uint64_t v = d->value;
+ SectionPiece &piece = v >= ms->content().size() ? ms->pieces.back()
+ : ms->getSectionPiece(v);
uint32_t idx = &piece - ms->pieces.data();
- uint64_t off = d->value - piece.inputOff;
+ uint64_t off = v - piece.inputOff;
d->value = ((uint64_t)(idx + 1) << mergeValueShift) | off;
};
for (Symbol *sym : file->getLocalSymbols())
diff --git a/lld/test/ELF/merge-piece-oob.s b/lld/test/ELF/merge-piece-oob.s
index 829f45cbc75e7..8ce5cc46d6960 100644
--- a/lld/test/ELF/merge-piece-oob.s
+++ b/lld/test/ELF/merge-piece-oob.s
@@ -3,8 +3,11 @@
## Non-section symbols and offset <= section_size are accepted, matching GNU ld.
# RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64
-# RUN: not ld.lld --threads=1 %t.o -o /dev/null -shared 2>&1 | FileCheck %s -DPREFIX=error --implicit-check-not=error:
-# RUN: ld.lld --threads=1 %t.o -o /dev/null -shared --noinhibit-exec 2>&1 | FileCheck %s -DPREFIX=warning --implicit-check-not=warning:
+# RUN: llvm-mc %s -o %t.err.o -filetype=obj -triple=x86_64 --defsym=ERR=1
+
+## OOB section-symbol offsets diagnose (or warn).
+# RUN: not ld.lld --threads=1 %t.err.o -o /dev/null -shared 2>&1 | FileCheck %s -DPREFIX=error --implicit-check-not=error:
+# RUN: ld.lld --threads=1 %t.err.o -o /dev/null -shared --noinhibit-exec 2>&1 | FileCheck %s -DPREFIX=warning --implicit-check-not=warning:
## .foo is 8 bytes with entsize=8 (1 piece). .foo+8 (offset==size) is accepted.
# CHECK: [[PREFIX]]: {{.*}}:(.foo): offset 0x9 is outside the section
@@ -18,19 +21,31 @@
## Test that --gc-sections with an out-of-bounds offset doesn't crash.
## .data is discarded but .data.retain (SHF_GNU_RETAIN) is kept.
## The bad offset prevents the piece from being marked live, so .foo is discarded.
-# RUN: not ld.lld %t.o -o /dev/null --gc-sections 2>&1 | FileCheck %s --check-prefix=GC
+# RUN: not ld.lld %t.err.o -o /dev/null --gc-sections 2>&1 | FileCheck %s --check-prefix=GC
# GC: error: relocation refers to a discarded section: .foo
+# RUN: ld.lld -r %t.o -o %t.ro
+# RUN: llvm-readelf -s -r %t.ro | FileCheck %s --check-prefix=RELOC
+
+# RELOC: R_X86_64_64 {{.*}} str_end + 0
+# RELOC-NEXT: R_X86_64_64 {{.*}} fixed_end + 0
+
+# RELOC: 0000000000000004 {{.*}} str_end
+# RELOC: 0000000000000008 {{.*}} fixed_end
+
.globl _start
_start:
.data
.quad .foo + 8
+.quad .rodata.str1.1 + 4
+.quad str_end
+.quad fixed_end
+
+.ifdef ERR
.quad .foo + 9
.quad .foo + 0x100000000
.quad .foo - 1
-.quad .rodata.str1.1 + 3
-.quad .rodata.str1.1 + 4
.quad .rodata.str1.1 + 5
.quad a0 - 1
@@ -38,10 +53,15 @@ _start:
.section .data.retain,"awR"
.quad .foo - 2
+.endif
.section .foo,"aM", at progbits,8
a0:
.quad 0
+.globl fixed_end
+fixed_end:
.section .rodata.str1.1,"aMS", at progbits,1
.asciz "abc"
+.globl str_end
+str_end:
More information about the llvm-commits
mailing list