[lld] [lld/ELF] Place large executable sections at the end (PR #70358)

Arthur Eubanks via llvm-commits llvm-commits at lists.llvm.org
Fri Nov 10 13:28:29 PST 2023


https://github.com/aeubanks updated https://github.com/llvm/llvm-project/pull/70358

>From bf4472ca95ba14242b073b246ccc3fde224a8196 Mon Sep 17 00:00:00 2001
From: Arthur Eubanks <aeubanks at google.com>
Date: Thu, 26 Oct 2023 10:36:23 -0700
Subject: [PATCH] [lld/ELF] Place large executable sections at the beginning

So that when mixing small and large text, large text stays out of the way of the rest of the binary.
---
 lld/ELF/Writer.cpp                   | 21 ++++---
 lld/test/ELF/x86-64-section-layout.s | 83 +++++++++++++++-------------
 2 files changed, 59 insertions(+), 45 deletions(-)

diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index a84e4864ab0e5a5..ffa77713a53b792 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -902,11 +902,12 @@ 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_NOT_LARGE_TEXT = 1 << 16,
+  RF_WRITE = 1 << 15,
+  RF_EXEC_WRITE = 1 << 14,
+  RF_EXEC = 1 << 13,
+  RF_RODATA = 1 << 12,
+  RF_LARGE = 1 << 11,
   RF_NOT_RELRO = 1 << 9,
   RF_NOT_TLS = 1 << 8,
   RF_BSS = 1 << 7,
@@ -957,6 +958,9 @@ static unsigned getSectionRank(OutputSection &osec) {
   // places.
   bool isExec = osec.flags & SHF_EXECINSTR;
   bool isWrite = osec.flags & SHF_WRITE;
+  bool isLarge = osec.flags & SHF_X86_64_LARGE && config->emachine == EM_X86_64;
+
+  rank |= RF_NOT_LARGE_TEXT;
 
   if (!isWrite && !isExec) {
     // Make PROGBITS sections (e.g .rodata .eh_frame) closer to .text to
@@ -965,10 +969,13 @@ static unsigned getSectionRank(OutputSection &osec) {
     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))
+    if (!isLarge)
       rank |= RF_LARGE;
   } else if (isExec) {
     rank |= isWrite ? RF_EXEC_WRITE : RF_EXEC;
+    // Place .ltext before .(l)rodata.
+    if (isLarge)
+      rank &= ~RF_NOT_LARGE_TEXT;
   } else {
     rank |= RF_WRITE;
     // The TLS initialization block needs to be a single contiguous block. Place
@@ -981,7 +988,7 @@ static unsigned getSectionRank(OutputSection &osec) {
       rank |= RF_NOT_RELRO;
     // Place .ldata and .lbss after .bss. Making .bss closer to .text alleviates
     // relocation overflow pressure.
-    if (osec.flags & SHF_X86_64_LARGE && config->emachine == EM_X86_64)
+    if (isLarge)
       rank |= RF_LARGE;
   }
 
diff --git a/lld/test/ELF/x86-64-section-layout.s b/lld/test/ELF/x86-64-section-layout.s
index 37201279fa0a5d0..b0f61cac7dad66c 100644
--- a/lld/test/ELF/x86-64-section-layout.s
+++ b/lld/test/ELF/x86-64-section-layout.s
@@ -18,63 +18,70 @@
 # 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
+# CHECK-NEXT:  .ltext     PROGBITS        0000000000201301 000301 000001 00 AXl  0   0  1
+# CHECK-NEXT:  .lrodata   PROGBITS        0000000000202302 000302 000002 00  Al  0   0  1
+# CHECK-NEXT:  .rodata    PROGBITS        0000000000202304 000304 000001 00   A  0   0  1
+# CHECK-NEXT:  .text      PROGBITS        0000000000203308 000308 000001 00  AX  0   0  4
+# CHECK-NEXT:  .tdata     PROGBITS        0000000000204309 000309 000001 00 WAT  0   0  1
+# CHECK-NEXT:  .tbss      NOBITS          000000000020430a 00030a 000002 00 WAT  0   0  1
+# CHECK-NEXT:  .relro_padding NOBITS      000000000020430a 00030a 000cf6 00  WA  0   0  1
+# CHECK-NEXT:  .data      PROGBITS        000000000020530a 00030a 000001 00  WA  0   0  1
+# CHECK-NEXT:  .bss       NOBITS          000000000020530b 00030b 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-NEXT:  .ldata     PROGBITS        0000000000207b0b 000b0b 000002 00 WAl  0   0  1
+# CHECK-NEXT:  .ldata2    PROGBITS        0000000000207b0d 000b0d 000001 00 WAl  0   0  1
+# CHECK-NEXT:  .lbss      NOBITS          0000000000207b0e 000b0e 000002 00 WAl  0   0  1
+# CHECK-NEXT:  .comment   PROGBITS        0000000000000000 000b0e {{.*}} 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  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  0x000000 0x0000000000200000 0x0000000000200000 0x000301 0x000301 R   0x1000
+# CHECK-NEXT:    LOAD  0x000301 0x0000000000201301 0x0000000000201301 0x000001 0x000001 R E 0x1000
+# CHECK-NEXT:    LOAD  0x000302 0x0000000000202302 0x0000000000202302 0x000003 0x000003 R   0x1000
+# CHECK-NEXT:    LOAD  0x000308 0x0000000000203308 0x0000000000203308 0x000001 0x000001 R E 0x1000
+# CHECK-NEXT:    LOAD  0x000309 0x0000000000204309 0x0000000000204309 0x000001 0x000cf7 RW  0x1000
+# CHECK-NEXT:    LOAD  0x00030a 0x000000000020530a 0x000000000020530a 0x000001 0x001801 RW  0x1000
+# CHECK-NEXT:    LOAD  0x000b0b 0x0000000000207b0b 0x0000000000207b0b 0x000003 0x000005 RW  0x1000
 
-# 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:      .data      PROGBITS        000000000020530a 00030a 000001 00  WA  0   0  1
+# CHECK1-NEXT: .ldata     PROGBITS        000000000020530b 00030b 000002 00 WAl  0   0  1
+# CHECK1-NEXT: .ldata2    PROGBITS        000000000020530d 00030d 000001 00 WAl  0   0  1
+# CHECK1-NEXT: .comment   PROGBITS        0000000000000000 00030e {{.*}} 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
+# CHECK2-NEXT: .ltext     PROGBITS        0000000000200301 000301 000001 00 AXl  0   0  1
+# CHECK2-NEXT: .lrodata   PROGBITS        0000000000200302 000302 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: .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
+# CHECK2-NEXT: .lrodata.1 PROGBITS        0000000000200303 000303 000001 00  Al  0   0  1
+# CHECK2-NEXT: .rodata    PROGBITS        0000000000200304 000304 000001 00   A  0   0  1
+# CHECK2-NEXT: .text      PROGBITS        0000000000200308 000308 000001 00  AX  0   0  4
+# CHECK2-NEXT: .tdata     PROGBITS        0000000000200309 000309 000001 00 WAT  0   0  1
+# CHECK2-NEXT: .tbss      NOBITS          000000000020030a 00030a 000001 00 WAT  0   0  1
+# CHECK2-NEXT: .tbss.1    NOBITS          000000000020030b 00030a 000001 00 WAT  0   0  1
+# CHECK2-NEXT: .data      PROGBITS        000000000020030a 00030a 000001 00  WA  0   0  1
+# CHECK2-NEXT: .bss       NOBITS          000000000020030b 00030b 001800 00  WA  0   0  1
+# CHECK2-NEXT: .ldata     PROGBITS        0000000000201b0b 001b0b 000002 00 WAl  0   0  1
+# CHECK2-NEXT: .ldata2    PROGBITS        0000000000201b0d 001b0d 000001 00 WAl  0   0  1
+# CHECK2-NEXT: .lbss      NOBITS          0000000000201b0e 001b0e 000002 00 WAl  0   0  1
+# CHECK2-NEXT: .comment   PROGBITS        0000000000000000 001b0e {{.*}} 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  0x000304 0x0000000000200304 0x0000000000200304 0x000001 0x000001 R E 0x1000
-# CHECK2-NEXT:   LOAD  0x000305 0x0000000000200305 0x0000000000200305 0x001805 0x001807 RW  0x1000
-# CHECK2-NEXT:   TLS   0x000305 0x0000000000200305 0x0000000000200305 0x000001 0x000003 R   0x1
+# CHECK2-NEXT:   LOAD  0x000000 0x0000000000200000 0x0000000000200000 0x000301 0x000301 R   0x1000
+# CHECK2-NEXT:   LOAD  0x000301 0x0000000000200301 0x0000000000200301 0x000001 0x000001 R E 0x1000
+# CHECK2-NEXT:   LOAD  0x000302 0x0000000000200302 0x0000000000200302 0x000003 0x000003 R   0x1000
+# CHECK2-NEXT:   LOAD  0x000308 0x0000000000200308 0x0000000000200308 0x000001 0x000001 R E 0x1000
+# CHECK2-NEXT:   LOAD  0x000309 0x0000000000200309 0x0000000000200309 0x001805 0x001807 RW  0x1000
+# CHECK2-NEXT:   TLS   0x000309 0x0000000000200309 0x0000000000200309 0x000001 0x000003 R   0x1
 
 #--- a.s
 .globl _start
 _start:
   ret
 
+.section .ltext,"axl", at progbits; .space 1
 .section .note,"a", at note; .space 1
 .section .rodata,"a", at progbits; .space 1
 .section .data,"aw", at progbits; .space 1



More information about the llvm-commits mailing list