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

Arthur Eubanks via llvm-commits llvm-commits at lists.llvm.org
Thu Oct 26 10:37:59 PDT 2023


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

So that when mixing small and large text, large text stays out of the way of the rest of the binary.


>From b1c068a3d8687aaae0ca2ac362f84e0663a7a091 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 end

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                   | 19 ++++++++++++-------
 lld/test/ELF/x86-64-section-layout.s | 11 ++++++++---
 2 files changed, 20 insertions(+), 10 deletions(-)

diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 57e1aa06c6aa873..313ff0f872e9440 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_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,7 @@ 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;
 
   if (!isWrite && !isExec) {
     // Make PROGBITS sections (e.g .rodata .eh_frame) closer to .text to
@@ -965,10 +967,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 after all other not special sections.
+    if (isLarge)
+      rank |= RF_LARGE_TEXT;
   } else {
     rank |= RF_WRITE;
     // The TLS initialization block needs to be a single contiguous block. Place
@@ -981,7 +986,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..5ae24f132f9f7b9 100644
--- a/lld/test/ELF/x86-64-section-layout.s
+++ b/lld/test/ELF/x86-64-section-layout.s
@@ -30,7 +30,8 @@
 # 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:  .ltext     PROGBITS        0000000000206b0c 000b0c 000001 00 AXl  0   0  1
+# CHECK-NEXT:  .comment   PROGBITS        0000000000000000 000b0d {{.*}} 01  MS  0   0  1
 
 # CHECK:       Program Headers:
 # CHECK-NEXT:    Type  Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
@@ -44,7 +45,8 @@
 # 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: .ltext     PROGBITS        000000000020430a 00030a 000001 00 AXl  0   0  1
+# CHECK1-NEXT: .comment   PROGBITS        0000000000000000 00030b {{.*}} 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
@@ -60,7 +62,8 @@
 # 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: .ltext     PROGBITS        0000000000201b0c 001b0c 000001 00 AXl  0   0  1
+# CHECK2-NEXT: .comment   PROGBITS        0000000000000000 001b0d {{.*}} 01  MS  0   0  1
 
 # CHECK2:      Program Headers:
 # CHECK2-NEXT:   Type  Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
@@ -68,6 +71,7 @@
 # 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:   LOAD  0x001b0c 0x0000000000201b0c 0x0000000000201b0c 0x000001 0x000001 R E 0x1000
 # CHECK2-NEXT:   TLS   0x000305 0x0000000000200305 0x0000000000200305 0x000001 0x000003 R   0x1
 
 #--- a.s
@@ -75,6 +79,7 @@
 _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