[lld] 747d670 - [ELF] Make .interp/SHT_NOTE not special

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Thu May 30 11:18:07 PDT 2024


Author: Fangrui Song
Date: 2024-05-30T11:18:03-07:00
New Revision: 747d670baef35f0615b32652e93c97a2ff8dba18

URL: https://github.com/llvm/llvm-project/commit/747d670baef35f0615b32652e93c97a2ff8dba18
DIFF: https://github.com/llvm/llvm-project/commit/747d670baef35f0615b32652e93c97a2ff8dba18.diff

LOG: [ELF] Make .interp/SHT_NOTE not special

Follow-up to a previous simplification
2473b1af085ad54e89666cedf684fdf10a84f058.

The xor difference between a SHT_NOTE and a read-only SHT_PROGBITS
(previously >=NOT_SPECIAL) should be smaller than RF_EXEC. Otherwise,
for the following section layout, `findOrphanPos` would place .text
before note.

```
// simplified from linkerscript/custom-section-type.s
non orphans:
progbits 0x8060c00 NOT_SPECIAL
note     0x8040003

orphan:
.text    0x8061000 NOT_SPECIAL
```

rw-text.lds in orphan.s (added by
73e07e924470ebab76a634e41fadf425a859e0ea) demonstrates a similar case.
The new behavior is more similar to GNU ld.

#93763 fixed BOLT's brittle reliance on the previous .interp behavior.

Added: 
    

Modified: 
    lld/ELF/Writer.cpp
    lld/test/ELF/linkerscript/orphan.s

Removed: 
    


################################################################################
diff  --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index d2cc6d8ff5f2c..c498153f3348b 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -618,7 +618,6 @@ enum RankFlags {
   RF_NOT_ADDR_SET = 1 << 27,
   RF_NOT_ALLOC = 1 << 26,
   RF_PARTITION = 1 << 18, // Partition number (8 bits)
-  RF_NOT_SPECIAL = 1 << 17,
   RF_LARGE_ALT = 1 << 15,
   RF_WRITE = 1 << 14,
   RF_EXEC_WRITE = 1 << 13,
@@ -644,24 +643,6 @@ unsigned elf::getSectionRank(OutputSection &osec) {
   if (!(osec.flags & SHF_ALLOC))
     return rank | RF_NOT_ALLOC;
 
-  if (osec.type == SHT_LLVM_PART_EHDR)
-    return rank;
-  if (osec.type == SHT_LLVM_PART_PHDR)
-    return rank | 1;
-
-  // Put .interp first because some loaders want to see that section
-  // on the first page of the executable file when loaded into memory.
-  if (osec.name == ".interp")
-    return rank | 2;
-
-  // Put .note sections at the beginning so that they are likely to be included
-  // in a truncate core file. In particular, .note.gnu.build-id, if available,
-  // can identify the object file.
-  if (osec.type == SHT_NOTE)
-    return rank | 3;
-
-  rank |= RF_NOT_SPECIAL;
-
   // Sort sections based on their access permission in the following
   // order: R, RX, RXW, RW(RELRO), RW(non-RELRO).
   //
@@ -677,11 +658,6 @@ unsigned elf::getSectionRank(OutputSection &osec) {
   bool isWrite = osec.flags & SHF_WRITE;
 
   if (!isWrite && !isExec) {
-    // Make PROGBITS sections (e.g .rodata .eh_frame) closer to .text to
-    // alleviate relocation overflow pressure. Large special sections such as
-    // .dynstr and .dynsym can be away from .text.
-    if (osec.type == SHT_PROGBITS)
-      rank |= RF_RODATA;
     // Among PROGBITS sections, place .lrodata further from .text.
     // For -z lrodata-after-bss, place .lrodata after .lbss like GNU ld. This
     // layout has one extra PT_LOAD, but alleviates relocation overflow
@@ -691,6 +667,25 @@ unsigned elf::getSectionRank(OutputSection &osec) {
       rank |= config->zLrodataAfterBss ? RF_LARGE_ALT : 0;
     else
       rank |= config->zLrodataAfterBss ? 0 : RF_LARGE;
+
+    if (osec.type == SHT_LLVM_PART_EHDR)
+      ;
+    else if (osec.type == SHT_LLVM_PART_PHDR)
+      rank |= 1;
+    else if (osec.name == ".interp")
+      rank |= 2;
+    // Put .note sections at the beginning so that they are likely to be
+    // included in a truncate core file. In particular, .note.gnu.build-id, if
+    // available, can identify the object file.
+    else if (osec.type == SHT_NOTE)
+      rank |= 3;
+    // Make PROGBITS sections (e.g .rodata .eh_frame) closer to .text to
+    // alleviate relocation overflow pressure. Large special sections such as
+    // .dynstr and .dynsym can be away from .text.
+    else if (osec.type != SHT_PROGBITS)
+      rank |= 4;
+    else
+      rank |= RF_RODATA;
   } else if (isExec) {
     rank |= isWrite ? RF_EXEC_WRITE : RF_EXEC;
   } else {

diff  --git a/lld/test/ELF/linkerscript/orphan.s b/lld/test/ELF/linkerscript/orphan.s
index cff6a3eb3a0b8..4f01b181d0416 100644
--- a/lld/test/ELF/linkerscript/orphan.s
+++ b/lld/test/ELF/linkerscript/orphan.s
@@ -55,13 +55,13 @@
 
 # RUN: ld.lld a.o -T rw-text.lds -o rw-text
 # RUN: llvm-readelf -S rw-text | FileCheck %s --check-prefix=RW-TEXT
-# RW-TEXT:      .interp   PROGBITS 00000000000002{{..}} 0
-# RW-TEXT-NEXT: .note.my  NOTE     00000000000002{{..}} 0
-# RW-TEXT-NEXT: .jcr      PROGBITS 00000000000002{{..}} 0
+# RW-TEXT:      .jcr      PROGBITS 00000000000002{{..}} 0
 # RW-TEXT-NEXT: .rw1      PROGBITS 00000000000002{{..}} 0
 # RW-TEXT-NEXT: .rw2      PROGBITS 00000000000002{{..}} 0
 # RW-TEXT-NEXT: .rw3      PROGBITS 00000000000002{{..}} 0
 # RW-TEXT-NEXT: .bss      NOBITS   00000000000002{{..}} 0
+# RW-TEXT-NEXT: .interp   PROGBITS 00000000000002{{..}} 0
+# RW-TEXT-NEXT: .note.my  NOTE     00000000000002{{..}} 0
 # RW-TEXT-NEXT: .text     PROGBITS 0000000000001{{...}} 0
 # RW-TEXT-NEXT: .mytext   PROGBITS 0000000000001{{...}} 0
 


        


More information about the llvm-commits mailing list