Skip to content

Commit 2473b1a

Browse files
committed
[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.
1 parent 96ddbd6 commit 2473b1a

File tree

1 file changed

+44
-74
lines changed

1 file changed

+44
-74
lines changed

lld/ELF/Writer.cpp

Lines changed: 44 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -829,23 +829,14 @@ enum RankFlags {
829829
RF_NOT_ADDR_SET = 1 << 27,
830830
RF_NOT_ALLOC = 1 << 26,
831831
RF_PARTITION = 1 << 18, // Partition number (8 bits)
832-
RF_NOT_PART_EHDR = 1 << 17,
833-
RF_NOT_PART_PHDR = 1 << 16,
834-
RF_NOT_INTERP = 1 << 15,
835-
RF_NOT_NOTE = 1 << 14,
832+
RF_NOT_SPECIAL = 1 << 17,
836833
RF_WRITE = 1 << 13,
837834
RF_EXEC_WRITE = 1 << 12,
838835
RF_EXEC = 1 << 11,
839836
RF_RODATA = 1 << 10,
840837
RF_NOT_RELRO = 1 << 9,
841838
RF_NOT_TLS = 1 << 8,
842839
RF_BSS = 1 << 7,
843-
RF_PPC_TOC = 1 << 4,
844-
RF_PPC_GOT = 1 << 3,
845-
RF_PPC_BRANCH_LT = 1 << 2,
846-
RF_MIPS_GPREL = 1 << 1,
847-
RF_MIPS_NOT_GOT = 1 << 0,
848-
RF_RISCV_SDATA = 1 << 0,
849840
};
850841

851842
static unsigned getSectionRank(const OutputSection &osec) {
@@ -864,71 +855,53 @@ static unsigned getSectionRank(const OutputSection &osec) {
864855

865856
if (osec.type == SHT_LLVM_PART_EHDR)
866857
return rank;
867-
rank |= RF_NOT_PART_EHDR;
868-
869858
if (osec.type == SHT_LLVM_PART_PHDR)
870-
return rank;
871-
rank |= RF_NOT_PART_PHDR;
859+
return rank | 1;
872860

873861
// Put .interp first because some loaders want to see that section
874862
// on the first page of the executable file when loaded into memory.
875863
if (osec.name == ".interp")
876-
return rank;
877-
rank |= RF_NOT_INTERP;
864+
return rank | 2;
878865

879-
// Put .note sections (which make up one PT_NOTE) at the beginning so that
880-
// they are likely to be included in a core file even if core file size is
881-
// limited. In particular, we want a .note.gnu.build-id and a .note.tag to be
882-
// included in a core to match core files with executables.
866+
// Put .note sections at the beginning so that they are likely to be included
867+
// in a truncate core file. In particular, .note.gnu.build-id, if available,
868+
// can identify the object file.
883869
if (osec.type == SHT_NOTE)
884-
return rank;
885-
rank |= RF_NOT_NOTE;
870+
return rank | 3;
871+
872+
rank |= RF_NOT_SPECIAL;
886873

887874
// Sort sections based on their access permission in the following
888-
// order: R, RX, RWX, RW. This order is based on the following
889-
// considerations:
890-
// * Read-only sections come first such that they go in the
891-
// PT_LOAD covering the program headers at the start of the file.
892-
// * Read-only, executable sections come next.
893-
// * Writable, executable sections follow such that .plt on
894-
// architectures where it needs to be writable will be placed
895-
// between .text and .data.
896-
// * Writable sections come last, such that .bss lands at the very
897-
// end of the last PT_LOAD.
875+
// order: R, RX, RXW, RW(RELRO), RW(non-RELRO).
876+
//
877+
// Read-only sections come first such that they go in the PT_LOAD covering the
878+
// program headers at the start of the file.
879+
//
880+
// The layout for writable sections is PT_LOAD(PT_GNU_RELRO(.data.rel.ro
881+
// .bss.rel.ro) | .data .bss), where | marks where page alignment happens.
882+
// An alternative ordering is PT_LOAD(.data | PT_GNU_RELRO( .data.rel.ro
883+
// .bss.rel.ro) | .bss), but it may waste more bytes due to 2 alignment
884+
// places.
898885
bool isExec = osec.flags & SHF_EXECINSTR;
899886
bool isWrite = osec.flags & SHF_WRITE;
900887

901-
if (isExec) {
902-
if (isWrite)
903-
rank |= RF_EXEC_WRITE;
904-
else
905-
rank |= RF_EXEC;
906-
} else if (isWrite) {
888+
if (!isWrite && !isExec) {
889+
// Make PROGBITS sections (e.g .rodata .eh_frame) closer to .text to
890+
// alleviate relocation overflow pressure. Large special sections such as
891+
// .dynstr and .dynsym can be away from .text.
892+
if (osec.type == SHT_PROGBITS)
893+
rank |= RF_RODATA;
894+
} else if (isExec) {
895+
rank |= isWrite ? RF_EXEC_WRITE : RF_EXEC;
896+
} else {
907897
rank |= RF_WRITE;
908-
} else if (osec.type == SHT_PROGBITS) {
909-
// Make non-executable and non-writable PROGBITS sections (e.g .rodata
910-
// .eh_frame) closer to .text. They likely contain PC or GOT relative
911-
// relocations and there could be relocation overflow if other huge sections
912-
// (.dynstr .dynsym) were placed in between.
913-
rank |= RF_RODATA;
914-
}
915-
916-
// Place RelRo sections first. After considering SHT_NOBITS below, the
917-
// ordering is PT_LOAD(PT_GNU_RELRO(.data.rel.ro .bss.rel.ro) | .data .bss),
918-
// where | marks where page alignment happens. An alternative ordering is
919-
// PT_LOAD(.data | PT_GNU_RELRO( .data.rel.ro .bss.rel.ro) | .bss), but it may
920-
// waste more bytes due to 2 alignment places.
921-
if (!isRelroSection(&osec))
922-
rank |= RF_NOT_RELRO;
923-
924-
// If we got here we know that both A and B are in the same PT_LOAD.
925-
926-
// The TLS initialization block needs to be a single contiguous block in a R/W
927-
// PT_LOAD, so stick TLS sections directly before the other RelRo R/W
928-
// sections. Since p_filesz can be less than p_memsz, place NOBITS sections
929-
// after PROGBITS.
930-
if (!(osec.flags & SHF_TLS))
931-
rank |= RF_NOT_TLS;
898+
// The TLS initialization block needs to be a single contiguous block. Place
899+
// TLS sections directly before the other RELRO sections.
900+
if (!(osec.flags & SHF_TLS))
901+
rank |= RF_NOT_TLS;
902+
if (!isRelroSection(&osec))
903+
rank |= RF_NOT_RELRO;
904+
}
932905

933906
// Within TLS sections, or within other RelRo sections, or within non-RelRo
934907
// sections, place non-NOBITS sections first.
@@ -943,32 +916,29 @@ static unsigned getSectionRank(const OutputSection &osec) {
943916
// their coverage by a single signed 16-bit offset from the TOC base
944917
// pointer.
945918
StringRef name = osec.name;
946-
if (name == ".toc")
947-
rank |= RF_PPC_TOC;
948-
949-
if (name == ".got")
950-
rank |= RF_PPC_GOT;
951-
952919
if (name == ".branch_lt")
953-
rank |= RF_PPC_BRANCH_LT;
920+
rank |= 1;
921+
else if (name == ".got")
922+
rank |= 2;
923+
else if (name == ".toc")
924+
rank |= 4;
954925
}
955926

956927
if (config->emachine == EM_MIPS) {
928+
if (osec.name != ".got")
929+
rank |= 1;
957930
// All sections with SHF_MIPS_GPREL flag should be grouped together
958931
// because data in these sections is addressable with a gp relative address.
959932
if (osec.flags & SHF_MIPS_GPREL)
960-
rank |= RF_MIPS_GPREL;
961-
962-
if (osec.name != ".got")
963-
rank |= RF_MIPS_NOT_GOT;
933+
rank |= 2;
964934
}
965935

966936
if (config->emachine == EM_RISCV) {
967937
// .sdata and .sbss are placed closer to make GP relaxation more profitable
968938
// and match GNU ld.
969939
StringRef name = osec.name;
970940
if (name == ".sdata" || (osec.type == SHT_NOBITS && name != ".sbss"))
971-
rank |= RF_RISCV_SDATA;
941+
rank |= 1;
972942
}
973943

974944
return rank;

0 commit comments

Comments
 (0)