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() ? 0 : 1); 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 OutputSegmentComparator::OutputSegmentComparator() { 74 // This defines the order of segments and the sections within each segment. 75 // Segments that are not mentioned here will end up at defaultPosition; 76 // sections that are not mentioned will end up at the end of the section 77 // list for their given segment. 78 std::vector<std::pair<StringRef, std::vector<StringRef>>> ordering{ 79 {segment_names::pageZero, {}}, 80 {segment_names::text, {section_names::header}}, 81 {defaultPosition, {}}, 82 // Make sure __LINKEDIT is the last segment (i.e. all its hidden 83 // sections must be ordered after other sections). 84 {segment_names::linkEdit, 85 { 86 section_names::binding, 87 section_names::export_, 88 section_names::symbolTable, 89 section_names::stringTable, 90 }}, 91 }; 92 93 for (uint32_t i = 0, n = ordering.size(); i < n; ++i) { 94 auto &p = ordering[i]; 95 StringRef segname = p.first; 96 const std::vector<StringRef> §Ordering = p.second; 97 orderMap.insert(std::pair<StringRef, OutputSectionComparator>( 98 segname, OutputSectionComparator(i, sectOrdering))); 99 } 100 101 // Cache the position for the default comparator since this is the likely 102 // scenario. 103 defaultPositionComparator = &orderMap.find(defaultPosition)->second; 104 } 105 106 static llvm::DenseMap<StringRef, OutputSegment *> nameToOutputSegment; 107 std::vector<OutputSegment *> macho::outputSegments; 108 109 OutputSegment *macho::getOutputSegment(StringRef name) { 110 return nameToOutputSegment.lookup(name); 111 } 112 113 OutputSegment *macho::getOrCreateOutputSegment(StringRef name) { 114 OutputSegment *&segRef = nameToOutputSegment[name]; 115 if (segRef != nullptr) 116 return segRef; 117 118 segRef = make<OutputSegment>(); 119 segRef->name = name; 120 segRef->maxProt = maxProt(name); 121 segRef->initProt = initProt(name); 122 123 outputSegments.push_back(segRef); 124 return segRef; 125 } 126 127 void macho::sortOutputSegmentsAndSections() { 128 // Sorting only can happen once all outputs have been collected. 129 // Since output sections are grouped by segment, sorting happens 130 // first over all segments, then over sections per segment. 131 auto comparator = OutputSegmentComparator(); 132 llvm::stable_sort(outputSegments, comparator); 133 134 // Now that the output sections are sorted, assign the final 135 // output section indices. 136 uint32_t sectionIndex = 0; 137 for (OutputSegment *seg : outputSegments) { 138 seg->sortOutputSections(&comparator); 139 for (auto &p : seg->getSections()) { 140 OutputSection *section = p.second; 141 if (!section->isHidden()) { 142 section->index = ++sectionIndex; 143 } 144 } 145 } 146 } 147