summaryrefslogtreecommitdiff
path: root/lld
diff options
context:
space:
mode:
authorFangrui Song <i@maskray.me>2023-05-12 23:58:39 -0700
committerFangrui Song <i@maskray.me>2023-05-12 23:58:39 -0700
commit2473b1af085ad54e89666cedf684fdf10a84f058 (patch)
treeb72c69e06070fe1f5cc0eff282c40ac3313dabfa /lld
parent96ddbd6dd85f9bc27fc3bc101411c7928a0c2756 (diff)
downloadllvm-2473b1af085ad54e89666cedf684fdf10a84f058.tar.gz
[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.
Diffstat (limited to 'lld')
-rw-r--r--lld/ELF/Writer.cpp118
1 files changed, 44 insertions, 74 deletions
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;