comparison lld/MachO/OutputSegment.cpp @ 207:2e18cbf3894f

LLVM12
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Tue, 08 Jun 2021 06:07:14 +0900
parents 0572611fdcc8
children 5f17cb93ff66
comparison
equal deleted inserted replaced
173:0572611fdcc8 207:2e18cbf3894f
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 // 6 //
7 //===----------------------------------------------------------------------===// 7 //===----------------------------------------------------------------------===//
8 8
9 #include "OutputSegment.h" 9 #include "OutputSegment.h"
10 #include "ConcatOutputSection.h"
10 #include "InputSection.h" 11 #include "InputSection.h"
11 #include "MergedOutputSection.h"
12 #include "SyntheticSections.h" 12 #include "SyntheticSections.h"
13 13
14 #include "lld/Common/ErrorHandler.h" 14 #include "lld/Common/ErrorHandler.h"
15 #include "lld/Common/Memory.h" 15 #include "lld/Common/Memory.h"
16 #include "llvm/ADT/StringSwitch.h"
16 #include "llvm/BinaryFormat/MachO.h" 17 #include "llvm/BinaryFormat/MachO.h"
17 18
18 using namespace llvm; 19 using namespace llvm;
19 using namespace llvm::MachO; 20 using namespace llvm::MachO;
20 using namespace lld; 21 using namespace lld;
21 using namespace lld::macho; 22 using namespace lld::macho;
22 23
23 static uint32_t initProt(StringRef name) { 24 static uint32_t initProt(StringRef name) {
25 auto it = find_if(
26 config->segmentProtections,
27 [&](const SegmentProtection &segprot) { return segprot.name == name; });
28 if (it != config->segmentProtections.end())
29 return it->initProt;
30
24 if (name == segment_names::text) 31 if (name == segment_names::text)
25 return VM_PROT_READ | VM_PROT_EXECUTE; 32 return VM_PROT_READ | VM_PROT_EXECUTE;
26 if (name == segment_names::pageZero) 33 if (name == segment_names::pageZero)
27 return 0; 34 return 0;
28 if (name == segment_names::linkEdit) 35 if (name == segment_names::linkEdit)
29 return VM_PROT_READ; 36 return VM_PROT_READ;
30 return VM_PROT_READ | VM_PROT_WRITE; 37 return VM_PROT_READ | VM_PROT_WRITE;
31 } 38 }
32 39
33 static uint32_t maxProt(StringRef name) { 40 static uint32_t maxProt(StringRef name) {
34 if (name == segment_names::pageZero) 41 assert(config->arch() != AK_i386 &&
35 return 0; 42 "TODO: i386 has different maxProt requirements");
36 return VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE; 43 return initProt(name);
37 } 44 }
38 45
39 size_t OutputSegment::numNonHiddenSections() const { 46 size_t OutputSegment::numNonHiddenSections() const {
40 size_t count = 0; 47 size_t count = 0;
41 for (const OutputSegment::SectionMapEntry &i : sections) { 48 for (const OutputSection *osec : sections)
42 OutputSection *os = i.second; 49 count += (!osec->isHidden() ? 1 : 0);
43 count += (!os->isHidden() ? 1 : 0);
44 }
45 return count; 50 return count;
46 } 51 }
47 52
48 void OutputSegment::addOutputSection(OutputSection *os) { 53 void OutputSegment::addOutputSection(OutputSection *osec) {
49 os->parent = this; 54 inputOrder = std::min(inputOrder, osec->inputOrder);
50 std::pair<SectionMap::iterator, bool> result = 55
51 sections.insert(SectionMapEntry(os->name, os)); 56 osec->parent = this;
52 if (!result.second) { 57 sections.push_back(osec);
53 llvm_unreachable("Attempted to set section, but a section with the same " 58
54 "name already exists"); 59 for (const SectionAlign &sectAlign : config->sectionAlignments)
55 } 60 if (sectAlign.segName == name && sectAlign.sectName == osec->name)
61 osec->align = sectAlign.align;
56 } 62 }
57 63
58 OutputSection *OutputSegment::getOrCreateOutputSection(StringRef name) { 64 template <typename T, typename F> static auto compareByOrder(F ord) {
59 OutputSegment::SectionMap::iterator i = sections.find(name); 65 return [=](T a, T b) { return ord(a) < ord(b); };
60 if (i != sections.end()) {
61 return i->second;
62 }
63
64 auto *os = make<MergedOutputSection>(name);
65 addOutputSection(os);
66 return os;
67 } 66 }
68 67
69 void OutputSegment::sortOutputSections(OutputSegmentComparator *comparator) { 68 static int segmentOrder(OutputSegment *seg) {
70 llvm::stable_sort(sections, *comparator->sectionComparator(this)); 69 return StringSwitch<int>(seg->name)
70 .Case(segment_names::pageZero, -4)
71 .Case(segment_names::text, -3)
72 .Case(segment_names::dataConst, -2)
73 .Case(segment_names::data, -1)
74 .Case(segment_names::llvm, std::numeric_limits<int>::max() - 1)
75 // Make sure __LINKEDIT is the last segment (i.e. all its hidden
76 // sections must be ordered after other sections).
77 .Case(segment_names::linkEdit, std::numeric_limits<int>::max())
78 .Default(seg->inputOrder);
71 } 79 }
72 80
73 void OutputSegment::removeUnneededSections() { 81 static int sectionOrder(OutputSection *osec) {
74 sections.remove_if([](const std::pair<StringRef, OutputSection *> &p) { 82 StringRef segname = osec->parent->name;
75 return !p.second->isNeeded(); 83 // Sections are uniquely identified by their segment + section name.
76 }); 84 if (segname == segment_names::text) {
85 return StringSwitch<int>(osec->name)
86 .Case(section_names::header, -4)
87 .Case(section_names::text, -3)
88 .Case(section_names::stubs, -2)
89 .Case(section_names::stubHelper, -1)
90 .Case(section_names::unwindInfo, std::numeric_limits<int>::max() - 1)
91 .Case(section_names::ehFrame, std::numeric_limits<int>::max())
92 .Default(osec->inputOrder);
93 } else if (segname == segment_names::data ||
94 segname == segment_names::dataConst) {
95 // For each thread spawned, dyld will initialize its TLVs by copying the
96 // address range from the start of the first thread-local data section to
97 // the end of the last one. We therefore arrange these sections contiguously
98 // to minimize the amount of memory used. Additionally, since zerofill
99 // sections must be at the end of their segments, and since TLV data
100 // sections can be zerofills, we end up putting all TLV data sections at the
101 // end of the segment.
102 switch (sectionType(osec->flags)) {
103 case S_THREAD_LOCAL_REGULAR:
104 return std::numeric_limits<int>::max() - 2;
105 case S_THREAD_LOCAL_ZEROFILL:
106 return std::numeric_limits<int>::max() - 1;
107 case S_ZEROFILL:
108 return std::numeric_limits<int>::max();
109 default:
110 return StringSwitch<int>(osec->name)
111 .Case(section_names::got, -3)
112 .Case(section_names::lazySymbolPtr, -2)
113 .Case(section_names::const_, -1)
114 .Default(osec->inputOrder);
115 }
116 } else if (segname == segment_names::linkEdit) {
117 return StringSwitch<int>(osec->name)
118 .Case(section_names::rebase, -9)
119 .Case(section_names::binding, -8)
120 .Case(section_names::weakBinding, -7)
121 .Case(section_names::lazyBinding, -6)
122 .Case(section_names::export_, -5)
123 .Case(section_names::functionStarts, -4)
124 .Case(section_names::symbolTable, -3)
125 .Case(section_names::indirectSymbolTable, -2)
126 .Case(section_names::stringTable, -1)
127 .Case(section_names::codeSignature, std::numeric_limits<int>::max())
128 .Default(osec->inputOrder);
129 }
130 // ZeroFill sections must always be the at the end of their segments,
131 // otherwise subsequent sections may get overwritten with zeroes at runtime.
132 if (sectionType(osec->flags) == S_ZEROFILL)
133 return std::numeric_limits<int>::max();
134 return osec->inputOrder;
77 } 135 }
78 136
79 OutputSegmentComparator::OutputSegmentComparator() { 137 void OutputSegment::sortOutputSections() {
80 // This defines the order of segments and the sections within each segment. 138 llvm::sort(sections, compareByOrder<OutputSection *>(sectionOrder));
81 // Segments that are not mentioned here will end up at defaultPosition;
82 // sections that are not mentioned will end up at the end of the section
83 // list for their given segment.
84 std::vector<std::pair<StringRef, std::vector<StringRef>>> ordering{
85 {segment_names::pageZero, {}},
86 {segment_names::text, {section_names::header}},
87 {defaultPosition, {}},
88 // Make sure __LINKEDIT is the last segment (i.e. all its hidden
89 // sections must be ordered after other sections).
90 {segment_names::linkEdit,
91 {
92 section_names::binding,
93 section_names::export_,
94 section_names::symbolTable,
95 section_names::stringTable,
96 }},
97 };
98
99 for (uint32_t i = 0, n = ordering.size(); i < n; ++i) {
100 auto &p = ordering[i];
101 StringRef segname = p.first;
102 const std::vector<StringRef> &sectOrdering = p.second;
103 orderMap.insert(std::pair<StringRef, OutputSectionComparator>(
104 segname, OutputSectionComparator(i, sectOrdering)));
105 }
106
107 // Cache the position for the default comparator since this is the likely
108 // scenario.
109 defaultPositionComparator = &orderMap.find(defaultPosition)->second;
110 } 139 }
111 140
112 static llvm::DenseMap<StringRef, OutputSegment *> nameToOutputSegment; 141 void macho::sortOutputSegments() {
142 llvm::sort(outputSegments, compareByOrder<OutputSegment *>(segmentOrder));
143 }
144
145 static DenseMap<StringRef, OutputSegment *> nameToOutputSegment;
113 std::vector<OutputSegment *> macho::outputSegments; 146 std::vector<OutputSegment *> macho::outputSegments;
114
115 OutputSegment *macho::getOutputSegment(StringRef name) {
116 return nameToOutputSegment.lookup(name);
117 }
118 147
119 OutputSegment *macho::getOrCreateOutputSegment(StringRef name) { 148 OutputSegment *macho::getOrCreateOutputSegment(StringRef name) {
120 OutputSegment *&segRef = nameToOutputSegment[name]; 149 OutputSegment *&segRef = nameToOutputSegment[name];
121 if (segRef != nullptr) 150 if (segRef)
122 return segRef; 151 return segRef;
123 152
124 segRef = make<OutputSegment>(); 153 segRef = make<OutputSegment>();
125 segRef->name = name; 154 segRef->name = name;
126 segRef->maxProt = maxProt(name); 155 segRef->maxProt = maxProt(name);