[lld] [lld/ELF][x86-64] Place large executable sections at the edges of binary (PR #70358)
Arthur Eubanks via llvm-commits
llvm-commits at lists.llvm.org
Thu Jun 12 11:20:23 PDT 2025
https://github.com/aeubanks updated https://github.com/llvm/llvm-project/pull/70358
>From 0389a497ed22ea0af316a7be77f235331ea6dd75 Mon Sep 17 00:00:00 2001
From: Arthur Eubanks <aeubanks at google.com>
Date: Thu, 29 May 2025 00:09:19 +0000
Subject: [PATCH 1/2] [lld/ELF] Place large executable sections at beginning or
end
---
lld/ELF/Writer.cpp | 26 +++++++++++++-----
lld/test/ELF/x86-64-section-layout.s | 40 ++++++++++++++++++++++++++++
2 files changed, 59 insertions(+), 7 deletions(-)
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index ec1f87a47479a..19f6b2877a537 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -653,15 +653,17 @@ enum RankFlags {
RF_NOT_ADDR_SET = 1 << 27,
RF_NOT_ALLOC = 1 << 26,
RF_PARTITION = 1 << 18, // Partition number (8 bits)
+ RF_LARGE_EXEC_WRITE = 1 << 16,
RF_LARGE_ALT = 1 << 15,
RF_WRITE = 1 << 14,
RF_EXEC_WRITE = 1 << 13,
RF_EXEC = 1 << 12,
RF_RODATA = 1 << 11,
- RF_LARGE = 1 << 10,
- RF_NOT_RELRO = 1 << 9,
- RF_NOT_TLS = 1 << 8,
- RF_BSS = 1 << 7,
+ RF_LARGE_EXEC = 1 << 10,
+ RF_LARGE = 1 << 9,
+ RF_NOT_RELRO = 1 << 8,
+ RF_NOT_TLS = 1 << 7,
+ RF_BSS = 1 << 6,
};
unsigned elf::getSectionRank(Ctx &ctx, OutputSection &osec) {
@@ -691,6 +693,7 @@ unsigned elf::getSectionRank(Ctx &ctx, OutputSection &osec) {
// places.
bool isExec = osec.flags & SHF_EXECINSTR;
bool isWrite = osec.flags & SHF_WRITE;
+ bool isLarge = osec.flags & SHF_X86_64_LARGE && ctx.arg.emachine == EM_X86_64;
if (!isWrite && !isExec) {
// Among PROGBITS sections, place .lrodata further from .text.
@@ -698,7 +701,7 @@ unsigned elf::getSectionRank(Ctx &ctx, OutputSection &osec) {
// layout has one extra PT_LOAD, but alleviates relocation overflow
// pressure for absolute relocations referencing small data from -fno-pic
// relocatable files.
- if (osec.flags & SHF_X86_64_LARGE && ctx.arg.emachine == EM_X86_64)
+ if (isLarge)
rank |= ctx.arg.zLrodataAfterBss ? RF_LARGE_ALT : 0;
else
rank |= ctx.arg.zLrodataAfterBss ? 0 : RF_LARGE;
@@ -722,7 +725,16 @@ unsigned elf::getSectionRank(Ctx &ctx, OutputSection &osec) {
else
rank |= RF_RODATA;
} else if (isExec) {
- rank |= isWrite ? RF_EXEC_WRITE : RF_EXEC;
+ // Place readonly .ltext before .lrodata and writable .ltext after .lbss to
+ // keep writable and readonly segments separate.
+ if (isLarge) {
+ if (isWrite)
+ rank |= RF_LARGE_EXEC_WRITE;
+ else
+ rank |= RF_LARGE_EXEC;
+ } else {
+ rank |= isWrite ? RF_EXEC_WRITE : RF_EXEC;
+ }
} else {
rank |= RF_WRITE;
// The TLS initialization block needs to be a single contiguous block. Place
@@ -737,7 +749,7 @@ unsigned elf::getSectionRank(Ctx &ctx, OutputSection &osec) {
// alleviates relocation overflow pressure.
// For -z lrodata-after-bss, place .lbss/.lrodata/.ldata after .bss.
// .bss/.lbss being adjacent reuses the NOBITS size optimization.
- if (osec.flags & SHF_X86_64_LARGE && ctx.arg.emachine == EM_X86_64) {
+ if (isLarge) {
rank |= ctx.arg.zLrodataAfterBss
? (osec.type == SHT_NOBITS ? 1 : RF_LARGE_ALT)
: RF_LARGE;
diff --git a/lld/test/ELF/x86-64-section-layout.s b/lld/test/ELF/x86-64-section-layout.s
index b03d3e6c2b999..d4d3d9be5deff 100644
--- a/lld/test/ELF/x86-64-section-layout.s
+++ b/lld/test/ELF/x86-64-section-layout.s
@@ -18,6 +18,10 @@
# RUN: ld.lld --section-start=.note=0x200300 a.o -z lrodata-after-bss -o a3
# RUN: llvm-readelf -S -l -sX a3 | FileCheck %s --check-prefix=CHECK3
+# RUN: llvm-mc -filetype=obj -triple=x86_64 c.s -o c.o
+# RUN: ld.lld c.o -o c
+# RUN: llvm-readelf -S -l c | FileCheck %s --check-prefix=CHECK4
+
# 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
@@ -116,6 +120,18 @@
# CHECK3-NEXT: 0000000000203307 0 NOTYPE GLOBAL DEFAULT [[#]] (.data) _edata
# CHECK3-NEXT: 0000000000207d0d 0 NOTYPE GLOBAL DEFAULT [[#]] (.ldata2) _end
+# CHECK4: .note NOTE
+# CHECK4-NEXT: .ltext PROGBITS
+# CHECK4-NEXT: .lrodata PROGBITS
+# CHECK4-NEXT: .rodata PROGBITS
+# CHECK4-NEXT: .text PROGBITS
+# CHECK4-NEXT: .data PROGBITS
+# CHECK4-NEXT: .bss NOBITS
+# CHECK4-NEXT: .ldata PROGBITS
+# CHECK4-NEXT: .lbss NOBITS
+# CHECK4-NEXT: .ltext_w PROGBITS
+# CHECK4-NEXT: .comment PROGBITS
+
#--- a.s
.globl _start, _etext, _edata, _end
_start:
@@ -155,3 +171,27 @@ SECTIONS {
.ldata2 : {}
.lbss : { *(.lbss .lbss.*) }
}
+
+#--- c.s
+.section .ltext,"axl", at progbits
+.globl f
+f:
+ ret
+
+.section .ltext_w,"awxl", at progbits
+.globl g
+g:
+ ret
+
+.section .text,"ax", at progbits
+.globl h
+h:
+ ret
+
+.section .note,"a", at note; .space 1
+.section .rodata,"a", at progbits; .space 1
+.section .data,"aw", at progbits; .space 1
+.section .bss,"aw", at nobits; .space 1
+.section .lrodata,"al"; .space 1
+.section .ldata,"awl"; .space 1
+.section .lbss,"awl", at nobits; .space 1
>From 8667a29152741d368b5fe9ea270ff0b45f144392 Mon Sep 17 00:00:00 2001
From: Arthur Eubanks <aeubanks at google.com>
Date: Thu, 12 Jun 2025 18:14:21 +0000
Subject: [PATCH 2/2] address comments
---
lld/ELF/Writer.cpp | 5 +----
lld/test/ELF/x86-64-section-layout.s | 1 +
2 files changed, 2 insertions(+), 4 deletions(-)
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 19f6b2877a537..2f0df82f3254e 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -728,10 +728,7 @@ unsigned elf::getSectionRank(Ctx &ctx, OutputSection &osec) {
// Place readonly .ltext before .lrodata and writable .ltext after .lbss to
// keep writable and readonly segments separate.
if (isLarge) {
- if (isWrite)
- rank |= RF_LARGE_EXEC_WRITE;
- else
- rank |= RF_LARGE_EXEC;
+ rank |= isWrite ? RF_LARGE_EXEC_WRITE : RF_LARGE_EXEC;
} else {
rank |= isWrite ? RF_EXEC_WRITE : RF_EXEC;
}
diff --git a/lld/test/ELF/x86-64-section-layout.s b/lld/test/ELF/x86-64-section-layout.s
index d4d3d9be5deff..1432271b885a8 100644
--- a/lld/test/ELF/x86-64-section-layout.s
+++ b/lld/test/ELF/x86-64-section-layout.s
@@ -173,6 +173,7 @@ SECTIONS {
}
#--- c.s
+## Test .ltext layout
.section .ltext,"axl", at progbits
.globl f
f:
More information about the llvm-commits
mailing list