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> §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 } 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