Mercurial > hg > CbC > CbC_llvm
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 §Align : 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> §Ordering = 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); |