llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-lld-elf @llvm/pr-subscribers-lld Author: Fangrui Song (MaskRay) <details> <summary>Changes</summary> https://reviews.llvm.org/D150510 places .lrodata before .rodata to minimize the number of permission transitions in the memory image. However, this layout is not ideal for -fno-pic code (which is still important). Small code model -fno-pic code has R_X86_64_32S relocations with a range of [0,2**31) (if we ignore the negative area). Placing `.lrodata` earlier exerts relocation pressure on such code. Non-x86 64-bit architectures generally have a similar [0,2**31) limitation if they don't use PC-relative relocations. If we place .lrodata later, two layouts are appealing: * .bss/.lbss/.lrodata/.ldata (GNU ld) * .bss/.ldata/.lbss/.lrodata The GNU ld style has the nice property that there is only one BSS (except .tbss/.relro_padding). Let's match GNU ld. While here, also place `_edata` at a location similar to GNU ld. --- Full diff: https://github.com/llvm/llvm-project/pull/81224.diff 3 Files Affected: - (modified) lld/ELF/Writer.cpp (+20-13) - (modified) lld/test/ELF/lto/codemodel.ll (+4-4) - (modified) lld/test/ELF/x86-64-section-layout.s (+44-35) ``````````diff diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 53ca70b59076fd..47e15ba869d4f4 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -911,11 +911,11 @@ enum RankFlags { RF_NOT_ALLOC = 1 << 26, RF_PARTITION = 1 << 18, // Partition number (8 bits) RF_NOT_SPECIAL = 1 << 17, - RF_WRITE = 1 << 16, - RF_EXEC_WRITE = 1 << 15, - RF_EXEC = 1 << 14, - RF_RODATA = 1 << 13, - RF_LARGE = 1 << 12, + RF_LARGE = 1 << 14, + RF_WRITE = 1 << 13, + RF_EXEC_WRITE = 1 << 12, + RF_EXEC = 1 << 11, + RF_RODATA = 1 << 10, RF_NOT_RELRO = 1 << 9, RF_NOT_TLS = 1 << 8, RF_BSS = 1 << 7, @@ -973,8 +973,11 @@ static unsigned getSectionRank(OutputSection &osec) { // .dynstr and .dynsym can be away from .text. if (osec.type == SHT_PROGBITS) rank |= RF_RODATA; - // Among PROGBITS sections, place .lrodata further from .text. - if (!(osec.flags & SHF_X86_64_LARGE && config->emachine == EM_X86_64)) + // Place .lrodata after .lbss like GNU ld. An alternative layout is to place + // .lrodata before .rodata (one fewer PT_LOAD), but does not alleviate + // relocation overflow pressure for absolute relocations referencing small + // data from -fno-pic relocatable files. + if (osec.flags & SHF_X86_64_LARGE && config->emachine == EM_X86_64) rank |= RF_LARGE; } else if (isExec) { rank |= isWrite ? RF_EXEC_WRITE : RF_EXEC; @@ -988,10 +991,10 @@ static unsigned getSectionRank(OutputSection &osec) { osec.relro = true; else rank |= RF_NOT_RELRO; - // Place .ldata and .lbss after .bss. Making .bss closer to .text alleviates - // relocation overflow pressure. + // Place .lbss/.lrodata/.ldata after .bss. .bss/.lbss being adjacent reuses + // the NOBITS size optimization. if (osec.flags & SHF_X86_64_LARGE && config->emachine == EM_X86_64) - rank |= RF_LARGE; + rank |= osec.type == SHT_NOBITS ? 1 : RF_LARGE; } // Within TLS sections, or within other RelRo sections, or within non-RelRo @@ -1124,11 +1127,15 @@ template <class ELFT> void Writer<ELFT>::setReservedSymbolSections() { } if (last) { - // _edata points to the end of the last mapped initialized section. + // _edata points to the end of the last mapped initialized section before + // the first regular NOBITS section (except .tbss and .relro_padding). In + // the presence of large data sections, .ldata may be after _edata. OutputSection *edata = nullptr; for (OutputSection *os : outputSections) { - if (os->type != SHT_NOBITS) - edata = os; + if (os->type == SHT_NOBITS && !(os->flags & SHF_TLS) && + (!in.relroPadding || in.relroPadding->getParent() != os)) + break; + edata = os; if (os == last->lastSec) break; } diff --git a/lld/test/ELF/lto/codemodel.ll b/lld/test/ELF/lto/codemodel.ll index a35f87729411d7..cf7d0e409ec4b1 100644 --- a/lld/test/ELF/lto/codemodel.ll +++ b/lld/test/ELF/lto/codemodel.ll @@ -2,8 +2,8 @@ ; RUN: llvm-as %s -o %t.o ; RUN: ld.lld %t.o -o %ts -mllvm -code-model=small ; RUN: ld.lld %t.o -o %tl -mllvm -code-model=large -; RUN: llvm-objdump --no-print-imm-hex -d %ts | FileCheck %s --check-prefix=CHECK-SMALL -; RUN: llvm-objdump --no-print-imm-hex -d %tl | FileCheck %s --check-prefix=CHECK-LARGE +; RUN: llvm-objdump -d %ts | FileCheck %s --check-prefix=CHECK-SMALL +; RUN: llvm-objdump -d %tl | FileCheck %s --check-prefix=CHECK-LARGE target triple = "x86_64-unknown-linux-gnu" target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" @@ -13,8 +13,8 @@ target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16 define ptr @_start() nounwind readonly { entry: ; CHECK-SMALL-LABEL: <_start>: -; CHECK-SMALL: movl $2097440, %eax +; CHECK-SMALL: movl ${{.*}}, %eax ; CHECK-LARGE-LABEL: <_start>: -; CHECK-LARGE: movabsq $2097440, %rax +; CHECK-LARGE: movabsq ${{.*}}, %rax ret ptr @data } diff --git a/lld/test/ELF/x86-64-section-layout.s b/lld/test/ELF/x86-64-section-layout.s index 37201279fa0a5d..1e1f36ed64009d 100644 --- a/lld/test/ELF/x86-64-section-layout.s +++ b/lld/test/ELF/x86-64-section-layout.s @@ -6,7 +6,7 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64 --defsym=BSS=1 a.s -o a.o # RUN: ld.lld --section-start=.note=0x200300 a.o -o a -# RUN: llvm-readelf -S -l a | FileCheck %s +# RUN: llvm-readelf -S -l -sX a | FileCheck %s # RUN: llvm-mc -filetype=obj -triple=x86_64 a.s -o a1.o # RUN: ld.lld --section-start=.note=0x200300 a1.o -o a1 @@ -15,63 +15,72 @@ # RUN: ld.lld -T b.lds -z norelro a.o -o b # RUN: llvm-readelf -S -l b | FileCheck %s --check-prefix=CHECK2 -# 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 -# CHECK-NEXT: .lrodata PROGBITS 0000000000200301 000301 000002 00 Al 0 0 1 -# CHECK-NEXT: .rodata PROGBITS 0000000000200303 000303 000001 00 A 0 0 1 -# CHECK-NEXT: .text PROGBITS 0000000000201304 000304 000001 00 AX 0 0 4 -# CHECK-NEXT: .tdata PROGBITS 0000000000202305 000305 000001 00 WAT 0 0 1 -# CHECK-NEXT: .tbss NOBITS 0000000000202306 000306 000002 00 WAT 0 0 1 -# CHECK-NEXT: .relro_padding NOBITS 0000000000202306 000306 000cfa 00 WA 0 0 1 -# CHECK-NEXT: .data PROGBITS 0000000000203306 000306 000001 00 WA 0 0 1 -# CHECK-NEXT: .bss NOBITS 0000000000203307 000307 001800 00 WA 0 0 1 -## We spend size(.bss) % MAXPAGESIZE bytes for .bss. -# CHECK-NEXT: .ldata PROGBITS 0000000000205b07 000b07 000002 00 WAl 0 0 1 -# CHECK-NEXT: .ldata2 PROGBITS 0000000000205b09 000b09 000001 00 WAl 0 0 1 -# CHECK-NEXT: .lbss NOBITS 0000000000205b0a 000b0a 000002 00 WAl 0 0 1 -# CHECK-NEXT: .comment PROGBITS 0000000000000000 000b0a {{.*}} 01 MS 0 0 1 +# 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 +# CHECK-NEXT: .rodata PROGBITS 0000000000200301 000301 000001 00 A 0 0 1 +# CHECK-NEXT: .text PROGBITS 0000000000201304 000304 000001 00 AX 0 0 4 +# CHECK-NEXT: .tdata PROGBITS 0000000000202305 000305 000001 00 WAT 0 0 1 +# CHECK-NEXT: .tbss NOBITS 0000000000202306 000306 000002 00 WAT 0 0 1 +# CHECK-NEXT: .relro_padding NOBITS 0000000000202306 000306 000cfa 00 WA 0 0 1 +# CHECK-NEXT: .data PROGBITS 0000000000203306 000306 000001 00 WA 0 0 1 +# CHECK-NEXT: .bss NOBITS 0000000000203307 000307 001800 00 WA 0 0 1 +## We spend (size(.bss) + size(.lbss)) % MAXPAGESIZE bytes. +# CHECK-NEXT: .lbss NOBITS 0000000000204b07 000307 001201 00 WAl 0 0 1 +# CHECK-NEXT: .lrodata PROGBITS 0000000000206d08 000d08 000002 00 Al 0 0 1 +# CHECK-NEXT: .ldata PROGBITS 0000000000207d0a 000d0a 000002 00 WAl 0 0 1 +# CHECK-NEXT: .ldata2 PROGBITS 0000000000207d0c 000d0c 000001 00 WAl 0 0 1 +# CHECK-NEXT: .comment PROGBITS 0000000000000000 000d0d {{.*}} 01 MS 0 0 1 # CHECK: Program Headers: # CHECK-NEXT: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align # CHECK-NEXT: PHDR 0x000040 0x0000000000200040 0x0000000000200040 {{.*}} {{.*}} R 0x8 -# CHECK-NEXT: LOAD 0x000000 0x0000000000200000 0x0000000000200000 0x000304 0x000304 R 0x1000 +# CHECK-NEXT: LOAD 0x000000 0x0000000000200000 0x0000000000200000 0x000302 0x000302 R 0x1000 # CHECK-NEXT: LOAD 0x000304 0x0000000000201304 0x0000000000201304 0x000001 0x000001 R E 0x1000 # CHECK-NEXT: LOAD 0x000305 0x0000000000202305 0x0000000000202305 0x000001 0x000cfb RW 0x1000 -# CHECK-NEXT: LOAD 0x000306 0x0000000000203306 0x0000000000203306 0x000001 0x001801 RW 0x1000 -# CHECK-NEXT: LOAD 0x000b07 0x0000000000205b07 0x0000000000205b07 0x000003 0x000005 RW 0x1000 +# CHECK-NEXT: LOAD 0x000306 0x0000000000203306 0x0000000000203306 0x000001 0x002a02 RW 0x1000 +# CHECK-NEXT: LOAD 0x000d08 0x0000000000206d08 0x0000000000206d08 0x000002 0x000002 R 0x1000 +# CHECK-NEXT: LOAD 0x000d0a 0x0000000000207d0a 0x0000000000207d0a 0x000003 0x000003 RW 0x1000 +# CHECK-NEXT: TLS 0x000305 0x0000000000202305 0x0000000000202305 0x000001 0x000003 R 0x1 + +# CHECK: 0000000000201304 0 NOTYPE GLOBAL DEFAULT [[#]] (.text) _start +# CHECK-NEXT: 0000000000203307 0 NOTYPE GLOBAL DEFAULT [[#]] (.data) _edata +# CHECK-NEXT: 0000000000207d0d 0 NOTYPE GLOBAL DEFAULT [[#]] (.ldata2) _end # CHECK1: .data PROGBITS 0000000000203306 000306 000001 00 WA 0 0 1 -# CHECK1-NEXT: .ldata PROGBITS 0000000000203307 000307 000002 00 WAl 0 0 1 -# CHECK1-NEXT: .ldata2 PROGBITS 0000000000203309 000309 000001 00 WAl 0 0 1 -# CHECK1-NEXT: .comment PROGBITS 0000000000000000 00030a {{.*}} 01 MS 0 0 1 +# CHECK1-NEXT: .lrodata PROGBITS 0000000000204307 000307 000002 00 Al 0 0 1 +# CHECK1-NEXT: .ldata PROGBITS 0000000000205309 000309 000002 00 WAl 0 0 1 +# CHECK1-NEXT: .ldata2 PROGBITS 000000000020530b 00030b 000001 00 WAl 0 0 1 +# CHECK1-NEXT: .comment PROGBITS 0000000000000000 00030c {{.*}} 01 MS 0 0 1 # CHECK2: .note NOTE 0000000000200300 000300 000001 00 A 0 0 1 -# CHECK2-NEXT: .lrodata PROGBITS 0000000000200301 000301 000001 00 Al 0 0 1 -## With a SECTIONS command, we suppress the default rule placing .lrodata.* into .lrodata. -# CHECK2-NEXT: .lrodata.1 PROGBITS 0000000000200302 000302 000001 00 Al 0 0 1 -# CHECK2-NEXT: .rodata PROGBITS 0000000000200303 000303 000001 00 A 0 0 1 +# CHECK2-NEXT: .rodata PROGBITS 0000000000200301 000301 000001 00 A 0 0 1 # CHECK2-NEXT: .text PROGBITS 0000000000200304 000304 000001 00 AX 0 0 4 # CHECK2-NEXT: .tdata PROGBITS 0000000000200305 000305 000001 00 WAT 0 0 1 # CHECK2-NEXT: .tbss NOBITS 0000000000200306 000306 000001 00 WAT 0 0 1 # CHECK2-NEXT: .tbss.1 NOBITS 0000000000200307 000306 000001 00 WAT 0 0 1 # CHECK2-NEXT: .data PROGBITS 0000000000200306 000306 000001 00 WA 0 0 1 # CHECK2-NEXT: .bss NOBITS 0000000000200307 000307 001800 00 WA 0 0 1 -# CHECK2-NEXT: .ldata PROGBITS 0000000000201b07 001b07 000002 00 WAl 0 0 1 -# CHECK2-NEXT: .ldata2 PROGBITS 0000000000201b09 001b09 000001 00 WAl 0 0 1 -# CHECK2-NEXT: .lbss NOBITS 0000000000201b0a 001b0a 000002 00 WAl 0 0 1 -# CHECK2-NEXT: .comment PROGBITS 0000000000000000 001b0a {{.*}} 01 MS 0 0 1 +## With a SECTIONS command, we suppress the default rule placing .lrodata.* into .lrodata. +# CHECK2-NEXT: .lrodata PROGBITS 0000000000201b07 000b07 000001 00 Al 0 0 1 +# CHECK2-NEXT: .lrodata.1 PROGBITS 0000000000201b08 000b08 000001 00 Al 0 0 1 +# CHECK2-NEXT: .ldata PROGBITS 0000000000201b09 000b09 000002 00 WAl 0 0 1 +# CHECK2-NEXT: .ldata2 PROGBITS 0000000000201b0b 000b0b 000001 00 WAl 0 0 1 +# CHECK2-NEXT: .lbss NOBITS 0000000000201b0c 000b0c 001201 00 WAl 0 0 1 +# CHECK2-NEXT: .comment PROGBITS 0000000000000000 000b0c {{.*}} 01 MS 0 0 1 # CHECK2: Program Headers: # CHECK2-NEXT: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align # CHECK2-NEXT: PHDR 0x000040 0x0000000000200040 0x0000000000200040 {{.*}} {{.*}} R 0x8 -# CHECK2-NEXT: LOAD 0x000000 0x0000000000200000 0x0000000000200000 0x000304 0x000304 R 0x1000 +# CHECK2-NEXT: LOAD 0x000000 0x0000000000200000 0x0000000000200000 0x000302 0x000302 R 0x1000 # CHECK2-NEXT: LOAD 0x000304 0x0000000000200304 0x0000000000200304 0x000001 0x000001 R E 0x1000 -# CHECK2-NEXT: LOAD 0x000305 0x0000000000200305 0x0000000000200305 0x001805 0x001807 RW 0x1000 +# CHECK2-NEXT: LOAD 0x000305 0x0000000000200305 0x0000000000200305 0x000002 0x001802 RW 0x1000 +# CHECK2-NEXT: LOAD 0x000b07 0x0000000000201b07 0x0000000000201b07 0x000002 0x000002 R 0x1000 +# CHECK2-NEXT: LOAD 0x000b09 0x0000000000201b09 0x0000000000201b09 0x000003 0x001204 RW 0x1000 # CHECK2-NEXT: TLS 0x000305 0x0000000000200305 0x0000000000200305 0x000001 0x000003 R 0x1 #--- a.s -.globl _start +.globl _start, _edata, _end _start: ret @@ -92,7 +101,7 @@ _start: ## Input .ldata.rel.ro sections are placed in the output .ldata section. .section .ldata.rel.ro,"awl"; .space 1 .ifdef BSS -.section .lbss,"awl",@nobits; .space 1 +.section .lbss,"awl",@nobits; .space 0x1200 ## Input .lbss.rel.ro sections are placed in the output .lbss section. .section .lbss.rel.ro,"awl",@nobits; .space 1 .endif `````````` </details> https://github.com/llvm/llvm-project/pull/81224 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits