[lld-macho][nfc] Remove unnecessary parameterization of section sort

As @alexshap pointed out [here](https://reviews.llvm.org/D102972#inline-975208),
it's a bit confusing to have the option to sort OutputSections with any
comparator when in practice we only use one.

Reviewed By: #lld-macho, alexshap, thakis

Differential Revision: https://reviews.llvm.org/D102974
This commit is contained in:
Jez Ng 2021-05-25 14:57:18 -04:00
parent fcab06bd85
commit 7599e98ab7
3 changed files with 87 additions and 81 deletions

View File

@ -13,6 +13,7 @@
#include "lld/Common/ErrorHandler.h"
#include "lld/Common/Memory.h"
#include "llvm/ADT/StringSwitch.h"
#include "llvm/BinaryFormat/MachO.h"
using namespace llvm;
@ -60,6 +61,87 @@ void OutputSegment::addOutputSection(OutputSection *osec) {
osec->align = sectAlign.align;
}
template <typename T, typename F> static auto compareByOrder(F ord) {
return [=](T a, T b) { return ord(a) < ord(b); };
}
static int segmentOrder(OutputSegment *seg) {
return StringSwitch<int>(seg->name)
.Case(segment_names::pageZero, -4)
.Case(segment_names::text, -3)
.Case(segment_names::dataConst, -2)
.Case(segment_names::data, -1)
.Case(segment_names::llvm, std::numeric_limits<int>::max() - 1)
// Make sure __LINKEDIT is the last segment (i.e. all its hidden
// sections must be ordered after other sections).
.Case(segment_names::linkEdit, std::numeric_limits<int>::max())
.Default(seg->inputOrder);
}
static int sectionOrder(OutputSection *osec) {
StringRef segname = osec->parent->name;
// Sections are uniquely identified by their segment + section name.
if (segname == segment_names::text) {
return StringSwitch<int>(osec->name)
.Case(section_names::header, -4)
.Case(section_names::text, -3)
.Case(section_names::stubs, -2)
.Case(section_names::stubHelper, -1)
.Case(section_names::unwindInfo, std::numeric_limits<int>::max() - 1)
.Case(section_names::ehFrame, std::numeric_limits<int>::max())
.Default(osec->inputOrder);
} else if (segname == segment_names::data ||
segname == segment_names::dataConst) {
// For each thread spawned, dyld will initialize its TLVs by copying the
// address range from the start of the first thread-local data section to
// the end of the last one. We therefore arrange these sections contiguously
// to minimize the amount of memory used. Additionally, since zerofill
// sections must be at the end of their segments, and since TLV data
// sections can be zerofills, we end up putting all TLV data sections at the
// end of the segment.
switch (sectionType(osec->flags)) {
case S_THREAD_LOCAL_REGULAR:
return std::numeric_limits<int>::max() - 2;
case S_THREAD_LOCAL_ZEROFILL:
return std::numeric_limits<int>::max() - 1;
case S_ZEROFILL:
return std::numeric_limits<int>::max();
default:
return StringSwitch<int>(osec->name)
.Case(section_names::got, -3)
.Case(section_names::lazySymbolPtr, -2)
.Case(section_names::const_, -1)
.Default(osec->inputOrder);
}
} else if (segname == segment_names::linkEdit) {
return StringSwitch<int>(osec->name)
.Case(section_names::rebase, -9)
.Case(section_names::binding, -8)
.Case(section_names::weakBinding, -7)
.Case(section_names::lazyBinding, -6)
.Case(section_names::export_, -5)
.Case(section_names::functionStarts, -4)
.Case(section_names::symbolTable, -3)
.Case(section_names::indirectSymbolTable, -2)
.Case(section_names::stringTable, -1)
.Case(section_names::codeSignature, std::numeric_limits<int>::max())
.Default(osec->inputOrder);
}
// ZeroFill sections must always be the at the end of their segments,
// otherwise subsequent sections may get overwritten with zeroes at runtime.
if (sectionType(osec->flags) == S_ZEROFILL)
return std::numeric_limits<int>::max();
return osec->inputOrder;
}
void OutputSegment::sortOutputSections() {
llvm::sort(sections, compareByOrder<OutputSection *>(sectionOrder));
}
void macho::sortOutputSegments() {
llvm::sort(outputSegments, compareByOrder<OutputSegment *>(segmentOrder));
}
static DenseMap<StringRef, OutputSegment *> nameToOutputSegment;
std::vector<OutputSegment *> macho::outputSegments;

View File

@ -42,10 +42,7 @@ public:
const OutputSection *lastSection() const { return sections.back(); }
void addOutputSection(OutputSection *os);
void sortOutputSections(
llvm::function_ref<bool(OutputSection *, OutputSection *)> comparator) {
llvm::sort(sections, comparator);
}
void sortOutputSections();
const std::vector<OutputSection *> &getSections() const { return sections; }
size_t numNonHiddenSections() const;
@ -65,6 +62,8 @@ private:
extern std::vector<OutputSegment *> outputSegments;
void sortOutputSegments();
OutputSegment *getOrCreateOutputSegment(StringRef name);
} // namespace macho

View File

@ -755,94 +755,19 @@ static DenseMap<const InputSection *, size_t> buildInputSectionPriorities() {
return sectionPriorities;
}
static int segmentOrder(OutputSegment *seg) {
return StringSwitch<int>(seg->name)
.Case(segment_names::pageZero, -4)
.Case(segment_names::text, -3)
.Case(segment_names::dataConst, -2)
.Case(segment_names::data, -1)
.Case(segment_names::llvm, std::numeric_limits<int>::max() - 1)
// Make sure __LINKEDIT is the last segment (i.e. all its hidden
// sections must be ordered after other sections).
.Case(segment_names::linkEdit, std::numeric_limits<int>::max())
.Default(seg->inputOrder);
}
static int sectionOrder(OutputSection *osec) {
StringRef segname = osec->parent->name;
// Sections are uniquely identified by their segment + section name.
if (segname == segment_names::text) {
return StringSwitch<int>(osec->name)
.Case(section_names::header, -4)
.Case(section_names::text, -3)
.Case(section_names::stubs, -2)
.Case(section_names::stubHelper, -1)
.Case(section_names::unwindInfo, std::numeric_limits<int>::max() - 1)
.Case(section_names::ehFrame, std::numeric_limits<int>::max())
.Default(osec->inputOrder);
} else if (segname == segment_names::data ||
segname == segment_names::dataConst) {
// For each thread spawned, dyld will initialize its TLVs by copying the
// address range from the start of the first thread-local data section to
// the end of the last one. We therefore arrange these sections contiguously
// to minimize the amount of memory used. Additionally, since zerofill
// sections must be at the end of their segments, and since TLV data
// sections can be zerofills, we end up putting all TLV data sections at the
// end of the segment.
switch (sectionType(osec->flags)) {
case S_THREAD_LOCAL_REGULAR:
return std::numeric_limits<int>::max() - 2;
case S_THREAD_LOCAL_ZEROFILL:
return std::numeric_limits<int>::max() - 1;
case S_ZEROFILL:
return std::numeric_limits<int>::max();
default:
return StringSwitch<int>(osec->name)
.Case(section_names::got, -3)
.Case(section_names::lazySymbolPtr, -2)
.Case(section_names::const_, -1)
.Default(osec->inputOrder);
}
} else if (segname == segment_names::linkEdit) {
return StringSwitch<int>(osec->name)
.Case(section_names::rebase, -9)
.Case(section_names::binding, -8)
.Case(section_names::weakBinding, -7)
.Case(section_names::lazyBinding, -6)
.Case(section_names::export_, -5)
.Case(section_names::functionStarts, -4)
.Case(section_names::symbolTable, -3)
.Case(section_names::indirectSymbolTable, -2)
.Case(section_names::stringTable, -1)
.Case(section_names::codeSignature, std::numeric_limits<int>::max())
.Default(osec->inputOrder);
}
// ZeroFill sections must always be the at the end of their segments,
// otherwise subsequent sections may get overwritten with zeroes at runtime.
if (sectionType(osec->flags) == S_ZEROFILL)
return std::numeric_limits<int>::max();
return osec->inputOrder;
}
template <typename T, typename F>
static std::function<bool(T, T)> compareByOrder(F ord) {
return [=](T a, T b) { return ord(a) < ord(b); };
}
// Sorting only can happen once all outputs have been collected. Here we sort
// segments, output sections within each segment, and input sections within each
// output segment.
static void sortSegmentsAndSections() {
TimeTraceScope timeScope("Sort segments and sections");
llvm::sort(outputSegments, compareByOrder<OutputSegment *>(segmentOrder));
sortOutputSegments();
DenseMap<const InputSection *, size_t> isecPriorities =
buildInputSectionPriorities();
uint32_t sectionIndex = 0;
for (OutputSegment *seg : outputSegments) {
seg->sortOutputSections(compareByOrder<OutputSection *>(sectionOrder));
seg->sortOutputSections();
for (OutputSection *osec : seg->getSections()) {
// Now that the output sections are sorted, assign the final
// output section indices.