[lld] 2473b1a - [ELF] Simplify getSectionRank and rewrite comments

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Fri May 12 23:58:45 PDT 2023


Author: Fangrui Song
Date: 2023-05-12T23:58:39-07:00
New Revision: 2473b1af085ad54e89666cedf684fdf10a84f058

URL: https://github.com/llvm/llvm-project/commit/2473b1af085ad54e89666cedf684fdf10a84f058
DIFF: https://github.com/llvm/llvm-project/commit/2473b1af085ad54e89666cedf684fdf10a84f058.diff

LOG: [ELF] Simplify getSectionRank and rewrite comments

Replace some RF_ flags with integer literals.
Rewrite the isWrite/isExec block to make the code block order reflect
the section order.
Rewrite some imprecise comments.

This is NFC, if we don't count invalid cases such as non-writable TLS
and non-writable RELRO.

Added: 
    

Modified: 
    lld/ELF/Writer.cpp

Removed: 
    


################################################################################
diff  --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index ffbe79872034..9266764ee0f6 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -829,10 +829,7 @@ enum RankFlags {
   RF_NOT_ADDR_SET = 1 << 27,
   RF_NOT_ALLOC = 1 << 26,
   RF_PARTITION = 1 << 18, // Partition number (8 bits)
-  RF_NOT_PART_EHDR = 1 << 17,
-  RF_NOT_PART_PHDR = 1 << 16,
-  RF_NOT_INTERP = 1 << 15,
-  RF_NOT_NOTE = 1 << 14,
+  RF_NOT_SPECIAL = 1 << 17,
   RF_WRITE = 1 << 13,
   RF_EXEC_WRITE = 1 << 12,
   RF_EXEC = 1 << 11,
@@ -840,12 +837,6 @@ enum RankFlags {
   RF_NOT_RELRO = 1 << 9,
   RF_NOT_TLS = 1 << 8,
   RF_BSS = 1 << 7,
-  RF_PPC_TOC = 1 << 4,
-  RF_PPC_GOT = 1 << 3,
-  RF_PPC_BRANCH_LT = 1 << 2,
-  RF_MIPS_GPREL = 1 << 1,
-  RF_MIPS_NOT_GOT = 1 << 0,
-  RF_RISCV_SDATA = 1 << 0,
 };
 
 static unsigned getSectionRank(const OutputSection &osec) {
@@ -864,71 +855,53 @@ static unsigned getSectionRank(const OutputSection &osec) {
 
   if (osec.type == SHT_LLVM_PART_EHDR)
     return rank;
-  rank |= RF_NOT_PART_EHDR;
-
   if (osec.type == SHT_LLVM_PART_PHDR)
-    return rank;
-  rank |= RF_NOT_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;
-  rank |= RF_NOT_INTERP;
+    return rank | 2;
 
-  // Put .note sections (which make up one PT_NOTE) at the beginning so that
-  // they are likely to be included in a core file even if core file size is
-  // limited. In particular, we want a .note.gnu.build-id and a .note.tag to be
-  // included in a core to match core files with executables.
+  // 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;
-  rank |= RF_NOT_NOTE;
+    return rank | 3;
+
+  rank |= RF_NOT_SPECIAL;
 
   // Sort sections based on their access permission in the following
-  // order: R, RX, RWX, RW.  This order is based on the following
-  // considerations:
-  // * Read-only sections come first such that they go in the
-  //   PT_LOAD covering the program headers at the start of the file.
-  // * Read-only, executable sections come next.
-  // * Writable, executable sections follow such that .plt on
-  //   architectures where it needs to be writable will be placed
-  //   between .text and .data.
-  // * Writable sections come last, such that .bss lands at the very
-  //   end of the last PT_LOAD.
+  // order: R, RX, RXW, RW(RELRO), RW(non-RELRO).
+  //
+  // Read-only sections come first such that they go in the PT_LOAD covering the
+  // program headers at the start of the file.
+  //
+  // The layout for writable sections is PT_LOAD(PT_GNU_RELRO(.data.rel.ro
+  // .bss.rel.ro) | .data .bss), where | marks where page alignment happens.
+  // An alternative ordering is PT_LOAD(.data | PT_GNU_RELRO( .data.rel.ro
+  // .bss.rel.ro) | .bss), but it may waste more bytes due to 2 alignment
+  // places.
   bool isExec = osec.flags & SHF_EXECINSTR;
   bool isWrite = osec.flags & SHF_WRITE;
 
-  if (isExec) {
-    if (isWrite)
-      rank |= RF_EXEC_WRITE;
-    else
-      rank |= RF_EXEC;
-  } else if (isWrite) {
+  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;
+  } else if (isExec) {
+    rank |= isWrite ? RF_EXEC_WRITE : RF_EXEC;
+  } else {
     rank |= RF_WRITE;
-  } else if (osec.type == SHT_PROGBITS) {
-    // Make non-executable and non-writable PROGBITS sections (e.g .rodata
-    // .eh_frame) closer to .text. They likely contain PC or GOT relative
-    // relocations and there could be relocation overflow if other huge sections
-    // (.dynstr .dynsym) were placed in between.
-    rank |= RF_RODATA;
-  }
-
-  // Place RelRo sections first. After considering SHT_NOBITS below, the
-  // ordering is PT_LOAD(PT_GNU_RELRO(.data.rel.ro .bss.rel.ro) | .data .bss),
-  // where | marks where page alignment happens. An alternative ordering is
-  // PT_LOAD(.data | PT_GNU_RELRO( .data.rel.ro .bss.rel.ro) | .bss), but it may
-  // waste more bytes due to 2 alignment places.
-  if (!isRelroSection(&osec))
-    rank |= RF_NOT_RELRO;
-
-  // If we got here we know that both A and B are in the same PT_LOAD.
-
-  // The TLS initialization block needs to be a single contiguous block in a R/W
-  // PT_LOAD, so stick TLS sections directly before the other RelRo R/W
-  // sections. Since p_filesz can be less than p_memsz, place NOBITS sections
-  // after PROGBITS.
-  if (!(osec.flags & SHF_TLS))
-    rank |= RF_NOT_TLS;
+    // The TLS initialization block needs to be a single contiguous block. Place
+    // TLS sections directly before the other RELRO sections.
+    if (!(osec.flags & SHF_TLS))
+      rank |= RF_NOT_TLS;
+    if (!isRelroSection(&osec))
+      rank |= RF_NOT_RELRO;
+  }
 
   // Within TLS sections, or within other RelRo sections, or within non-RelRo
   // sections, place non-NOBITS sections first.
@@ -943,24 +916,21 @@ static unsigned getSectionRank(const OutputSection &osec) {
     // their coverage by a single signed 16-bit offset from the TOC base
     // pointer.
     StringRef name = osec.name;
-    if (name == ".toc")
-      rank |= RF_PPC_TOC;
-
-    if (name == ".got")
-      rank |= RF_PPC_GOT;
-
     if (name == ".branch_lt")
-      rank |= RF_PPC_BRANCH_LT;
+      rank |= 1;
+    else if (name == ".got")
+      rank |= 2;
+    else if (name == ".toc")
+      rank |= 4;
   }
 
   if (config->emachine == EM_MIPS) {
+    if (osec.name != ".got")
+      rank |= 1;
     // All sections with SHF_MIPS_GPREL flag should be grouped together
     // because data in these sections is addressable with a gp relative address.
     if (osec.flags & SHF_MIPS_GPREL)
-      rank |= RF_MIPS_GPREL;
-
-    if (osec.name != ".got")
-      rank |= RF_MIPS_NOT_GOT;
+      rank |= 2;
   }
 
   if (config->emachine == EM_RISCV) {
@@ -968,7 +938,7 @@ static unsigned getSectionRank(const OutputSection &osec) {
     // and match GNU ld.
     StringRef name = osec.name;
     if (name == ".sdata" || (osec.type == SHT_NOBITS && name != ".sbss"))
-      rank |= RF_RISCV_SDATA;
+      rank |= 1;
   }
 
   return rank;


        


More information about the llvm-commits mailing list