1 //===- OutputSegment.cpp --------------------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "OutputSegment.h"
10 #include "InputSection.h"
11 #include "MergedOutputSection.h"
12 #include "SyntheticSections.h"
13 
14 #include "lld/Common/ErrorHandler.h"
15 #include "lld/Common/Memory.h"
16 #include "llvm/BinaryFormat/MachO.h"
17 
18 using namespace llvm;
19 using namespace llvm::MachO;
20 using namespace lld;
21 using namespace lld::macho;
22 
23 static uint32_t initProt(StringRef name) {
24   if (name == segment_names::text)
25     return VM_PROT_READ | VM_PROT_EXECUTE;
26   if (name == segment_names::pageZero)
27     return 0;
28   if (name == segment_names::linkEdit)
29     return VM_PROT_READ;
30   return VM_PROT_READ | VM_PROT_WRITE;
31 }
32 
33 static uint32_t maxProt(StringRef name) {
34   if (name == segment_names::pageZero)
35     return 0;
36   return VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE;
37 }
38 
39 size_t OutputSegment::numNonHiddenSections() const {
40   size_t count = 0;
41   for (const OutputSegment::SectionMapEntry &i : sections) {
42     OutputSection *os = i.second;
43     count += (!os->isHidden() ? 1 : 0);
44   }
45   return count;
46 }
47 
48 void OutputSegment::addOutputSection(OutputSection *os) {
49   os->parent = this;
50   std::pair<SectionMap::iterator, bool> result =
51       sections.insert(SectionMapEntry(os->name, os));
52   if (!result.second) {
53     llvm_unreachable("Attempted to set section, but a section with the same "
54                      "name already exists");
55   }
56 }
57 
58 OutputSection *OutputSegment::getOrCreateOutputSection(StringRef name) {
59   OutputSegment::SectionMap::iterator i = sections.find(name);
60   if (i != sections.end()) {
61     return i->second;
62   }
63 
64   auto *os = make<MergedOutputSection>(name);
65   addOutputSection(os);
66   return os;
67 }
68 
69 void OutputSegment::sortOutputSections(OutputSegmentComparator *comparator) {
70   llvm::stable_sort(sections, *comparator->sectionComparator(this));
71 }
72 
73 void OutputSegment::removeUnneededSections() {
74   sections.remove_if([](const std::pair<StringRef, OutputSection *> &p) {
75     return !p.second->isNeeded();
76   });
77 }
78 
79 OutputSegmentComparator::OutputSegmentComparator() {
80   // This defines the order of segments and the sections within each segment.
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 }
111 
112 static llvm::DenseMap<StringRef, OutputSegment *> nameToOutputSegment;
113 std::vector<OutputSegment *> macho::outputSegments;
114 
115 OutputSegment *macho::getOutputSegment(StringRef name) {
116   return nameToOutputSegment.lookup(name);
117 }
118 
119 OutputSegment *macho::getOrCreateOutputSegment(StringRef name) {
120   OutputSegment *&segRef = nameToOutputSegment[name];
121   if (segRef != nullptr)
122     return segRef;
123 
124   segRef = make<OutputSegment>();
125   segRef->name = name;
126   segRef->maxProt = maxProt(name);
127   segRef->initProt = initProt(name);
128 
129   outputSegments.push_back(segRef);
130   return segRef;
131 }
132 
133 void macho::sortOutputSegmentsAndSections() {
134   // Sorting only can happen once all outputs have been collected.
135   // Since output sections are grouped by segment, sorting happens
136   // first over all segments, then over sections per segment.
137   auto comparator = OutputSegmentComparator();
138   llvm::stable_sort(outputSegments, comparator);
139 
140   // Now that the output sections are sorted, assign the final
141   // output section indices.
142   uint32_t sectionIndex = 0;
143   for (OutputSegment *seg : outputSegments) {
144     seg->sortOutputSections(&comparator);
145     for (auto &p : seg->getSections()) {
146       OutputSection *section = p.second;
147       if (!section->isHidden())
148         section->index = ++sectionIndex;
149     }
150   }
151 }
152