[lld] [lld][ELF] Merge .ltext.* input sections into .ltext output section (PR #190305)
Farid Zakaria via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 2 22:12:20 PDT 2026
https://github.com/fzakaria updated https://github.com/llvm/llvm-project/pull/190305
>From d49ef89f65375fd9d5c9e2e9c04acb399a0ee1bf Mon Sep 17 00:00:00 2001
From: Farid Zakaria <fmzakari at fb.com>
Date: Thu, 2 Apr 2026 22:11:45 -0700
Subject: [PATCH] [lld][ELF] Merge .ltext.* input sections into .ltext output
section
The default output section name rules in getOutputSectionName() already
merge .ldata.*, .lrodata.*, and .lbss.* into their respective output
sections, but .ltext.* was missing. This caused mcmodel=large builds
with -ffunction-sections to produce a separate output section for every
function instead of combining them into .ltext.
Add .ltext handling mirroring .text, including -z keep-text-section-prefix
support so that .ltext.hot, .ltext.unlikely, etc. are preserved when
that flag is set.
Co-authored-by: Grigory Pastukhov <gpastukhov at meta.com>
---
lld/ELF/LinkerScript.cpp | 8 ++++++++
lld/test/ELF/x86-64-section-layout.s | 27 ++++++++++++++++++++++++++-
2 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp
index 76f04a27b9997..d76ee6b5aa55f 100644
--- a/lld/ELF/LinkerScript.cpp
+++ b/lld/ELF/LinkerScript.cpp
@@ -102,6 +102,14 @@ StringRef LinkerScript::getOutputSectionName(const InputSectionBase *s) const {
return v;
return ".text";
}
+ if (isSectionPrefix(".ltext", s->name)) {
+ if (ctx.arg.zKeepTextSectionPrefix)
+ for (StringRef v : {".ltext.hot", ".ltext.unknown", ".ltext.unlikely",
+ ".ltext.startup", ".ltext.exit", ".ltext.split"})
+ if (isSectionPrefix(v.substr(6), s->name.substr(6)))
+ return v;
+ return ".ltext";
+ }
for (StringRef v : {".data.rel.ro", ".data", ".rodata",
".bss.rel.ro", ".bss", ".ldata",
diff --git a/lld/test/ELF/x86-64-section-layout.s b/lld/test/ELF/x86-64-section-layout.s
index 1432271b885a8..81cc16d566239 100644
--- a/lld/test/ELF/x86-64-section-layout.s
+++ b/lld/test/ELF/x86-64-section-layout.s
@@ -22,6 +22,10 @@
# RUN: ld.lld c.o -o c
# RUN: llvm-readelf -S -l c | FileCheck %s --check-prefix=CHECK4
+# RUN: llvm-mc -filetype=obj -triple=x86_64 d.s -o d.o
+# RUN: ld.lld d.o -z keep-text-section-prefix -o d
+# RUN: llvm-readelf -S d | FileCheck %s --check-prefix=CHECK5
+
# CHECK: Name Type Address Off Size ES Flg Lk Inf Al
# CHECK-NEXT: NULL 0000000000000000 000000 000000 00 0 0 0
# CHECK-NEXT: .note NOTE 0000000000200300 000300 000001 00 A 0 0 1
@@ -132,6 +136,13 @@
# CHECK4-NEXT: .ltext_w PROGBITS
# CHECK4-NEXT: .comment PROGBITS
+## .ltext.hot and .ltext.unlikely are kept separate with -z keep-text-section-prefix.
+# CHECK5: .ltext.hot PROGBITS
+# CHECK5-NEXT: .ltext.unlikely PROGBITS
+# CHECK5-NEXT: .ltext PROGBITS
+# CHECK5: .text.hot PROGBITS
+# CHECK5-NEXT: .text.unlikely PROGBITS
+
#--- a.s
.globl _start, _etext, _edata, _end
_start:
@@ -173,12 +184,17 @@ SECTIONS {
}
#--- c.s
-## Test .ltext layout
+## Test .ltext layout. .ltext.1 should be merged into .ltext.
.section .ltext,"axl", at progbits
.globl f
f:
ret
+.section .ltext.1,"axl", at progbits
+.globl f1
+f1:
+ ret
+
.section .ltext_w,"awxl", at progbits
.globl g
g:
@@ -196,3 +212,12 @@ h:
.section .lrodata,"al"; .space 1
.section .ldata,"awl"; .space 1
.section .lbss,"awl", at nobits; .space 1
+
+#--- d.s
+## Test -z keep-text-section-prefix with .ltext
+.section .ltext.hot.f1,"axl", at progbits; ret
+.section .ltext.unlikely.f2,"axl", at progbits; ret
+.section .ltext.f3,"axl", at progbits; ret
+.section .text.hot.f4,"ax", at progbits; ret
+.section .text.unlikely.f5,"ax", at progbits; ret
+.section .text.f6,"ax", at progbits; ret
More information about the llvm-commits
mailing list