Skip to content

Commit 0389a49

Browse files
committed
[lld/ELF] Place large executable sections at beginning or end
1 parent 3a0205a commit 0389a49

File tree

2 files changed

+59
-7
lines changed

2 files changed

+59
-7
lines changed

lld/ELF/Writer.cpp

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -653,15 +653,17 @@ enum RankFlags {
653653
RF_NOT_ADDR_SET = 1 << 27,
654654
RF_NOT_ALLOC = 1 << 26,
655655
RF_PARTITION = 1 << 18, // Partition number (8 bits)
656+
RF_LARGE_EXEC_WRITE = 1 << 16,
656657
RF_LARGE_ALT = 1 << 15,
657658
RF_WRITE = 1 << 14,
658659
RF_EXEC_WRITE = 1 << 13,
659660
RF_EXEC = 1 << 12,
660661
RF_RODATA = 1 << 11,
661-
RF_LARGE = 1 << 10,
662-
RF_NOT_RELRO = 1 << 9,
663-
RF_NOT_TLS = 1 << 8,
664-
RF_BSS = 1 << 7,
662+
RF_LARGE_EXEC = 1 << 10,
663+
RF_LARGE = 1 << 9,
664+
RF_NOT_RELRO = 1 << 8,
665+
RF_NOT_TLS = 1 << 7,
666+
RF_BSS = 1 << 6,
665667
};
666668

667669
unsigned elf::getSectionRank(Ctx &ctx, OutputSection &osec) {
@@ -691,14 +693,15 @@ unsigned elf::getSectionRank(Ctx &ctx, OutputSection &osec) {
691693
// places.
692694
bool isExec = osec.flags & SHF_EXECINSTR;
693695
bool isWrite = osec.flags & SHF_WRITE;
696+
bool isLarge = osec.flags & SHF_X86_64_LARGE && ctx.arg.emachine == EM_X86_64;
694697

695698
if (!isWrite && !isExec) {
696699
// Among PROGBITS sections, place .lrodata further from .text.
697700
// For -z lrodata-after-bss, place .lrodata after .lbss like GNU ld. This
698701
// layout has one extra PT_LOAD, but alleviates relocation overflow
699702
// pressure for absolute relocations referencing small data from -fno-pic
700703
// relocatable files.
701-
if (osec.flags & SHF_X86_64_LARGE && ctx.arg.emachine == EM_X86_64)
704+
if (isLarge)
702705
rank |= ctx.arg.zLrodataAfterBss ? RF_LARGE_ALT : 0;
703706
else
704707
rank |= ctx.arg.zLrodataAfterBss ? 0 : RF_LARGE;
@@ -722,7 +725,16 @@ unsigned elf::getSectionRank(Ctx &ctx, OutputSection &osec) {
722725
else
723726
rank |= RF_RODATA;
724727
} else if (isExec) {
725-
rank |= isWrite ? RF_EXEC_WRITE : RF_EXEC;
728+
// Place readonly .ltext before .lrodata and writable .ltext after .lbss to
729+
// keep writable and readonly segments separate.
730+
if (isLarge) {
731+
if (isWrite)
732+
rank |= RF_LARGE_EXEC_WRITE;
733+
else
734+
rank |= RF_LARGE_EXEC;
735+
} else {
736+
rank |= isWrite ? RF_EXEC_WRITE : RF_EXEC;
737+
}
726738
} else {
727739
rank |= RF_WRITE;
728740
// The TLS initialization block needs to be a single contiguous block. Place
@@ -737,7 +749,7 @@ unsigned elf::getSectionRank(Ctx &ctx, OutputSection &osec) {
737749
// alleviates relocation overflow pressure.
738750
// For -z lrodata-after-bss, place .lbss/.lrodata/.ldata after .bss.
739751
// .bss/.lbss being adjacent reuses the NOBITS size optimization.
740-
if (osec.flags & SHF_X86_64_LARGE && ctx.arg.emachine == EM_X86_64) {
752+
if (isLarge) {
741753
rank |= ctx.arg.zLrodataAfterBss
742754
? (osec.type == SHT_NOBITS ? 1 : RF_LARGE_ALT)
743755
: RF_LARGE;

lld/test/ELF/x86-64-section-layout.s

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,10 @@
1818
# RUN: ld.lld --section-start=.note=0x200300 a.o -z lrodata-after-bss -o a3
1919
# RUN: llvm-readelf -S -l -sX a3 | FileCheck %s --check-prefix=CHECK3
2020

21+
# RUN: llvm-mc -filetype=obj -triple=x86_64 c.s -o c.o
22+
# RUN: ld.lld c.o -o c
23+
# RUN: llvm-readelf -S -l c | FileCheck %s --check-prefix=CHECK4
24+
2125
# CHECK: Name Type Address Off Size ES Flg Lk Inf Al
2226
# CHECK-NEXT: NULL 0000000000000000 000000 000000 00 0 0 0
2327
# CHECK-NEXT: .note NOTE 0000000000200300 000300 000001 00 A 0 0 1
@@ -116,6 +120,18 @@
116120
# CHECK3-NEXT: 0000000000203307 0 NOTYPE GLOBAL DEFAULT [[#]] (.data) _edata
117121
# CHECK3-NEXT: 0000000000207d0d 0 NOTYPE GLOBAL DEFAULT [[#]] (.ldata2) _end
118122

123+
# CHECK4: .note NOTE
124+
# CHECK4-NEXT: .ltext PROGBITS
125+
# CHECK4-NEXT: .lrodata PROGBITS
126+
# CHECK4-NEXT: .rodata PROGBITS
127+
# CHECK4-NEXT: .text PROGBITS
128+
# CHECK4-NEXT: .data PROGBITS
129+
# CHECK4-NEXT: .bss NOBITS
130+
# CHECK4-NEXT: .ldata PROGBITS
131+
# CHECK4-NEXT: .lbss NOBITS
132+
# CHECK4-NEXT: .ltext_w PROGBITS
133+
# CHECK4-NEXT: .comment PROGBITS
134+
119135
#--- a.s
120136
.globl _start, _etext, _edata, _end
121137
_start:
@@ -155,3 +171,27 @@ SECTIONS {
155171
.ldata2 : {}
156172
.lbss : { *(.lbss .lbss.*) }
157173
}
174+
175+
#--- c.s
176+
.section .ltext,"axl",@progbits
177+
.globl f
178+
f:
179+
ret
180+
181+
.section .ltext_w,"awxl",@progbits
182+
.globl g
183+
g:
184+
ret
185+
186+
.section .text,"ax",@progbits
187+
.globl h
188+
h:
189+
ret
190+
191+
.section .note,"a",@note; .space 1
192+
.section .rodata,"a",@progbits; .space 1
193+
.section .data,"aw",@progbits; .space 1
194+
.section .bss,"aw",@nobits; .space 1
195+
.section .lrodata,"al"; .space 1
196+
.section .ldata,"awl"; .space 1
197+
.section .lbss,"awl",@nobits; .space 1

0 commit comments

Comments
 (0)