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 "ConcatOutputSection.h" 11 #include "InputSection.h" 12 #include "Sections.h" 13 #include "Symbols.h" 14 #include "SyntheticSections.h" 15 16 #include "lld/Common/Memory.h" 17 #include "llvm/ADT/StringSwitch.h" 18 #include "llvm/BinaryFormat/MachO.h" 19 20 using namespace llvm; 21 using namespace llvm::MachO; 22 using namespace lld; 23 using namespace lld::macho; 24 25 static uint32_t initProt(StringRef name) { 26 auto it = find_if( 27 config->segmentProtections, 28 [&](const SegmentProtection &segprot) { return segprot.name == name; }); 29 if (it != config->segmentProtections.end()) 30 return it->initProt; 31 32 if (name == segment_names::text) 33 return VM_PROT_READ | VM_PROT_EXECUTE; 34 if (name == segment_names::pageZero) 35 return 0; 36 if (name == segment_names::linkEdit) 37 return VM_PROT_READ; 38 return VM_PROT_READ | VM_PROT_WRITE; 39 } 40 41 static uint32_t maxProt(StringRef name) { 42 assert(config->arch() != AK_i386 && 43 "TODO: i386 has different maxProt requirements"); 44 auto it = find_if( 45 config->segmentProtections, 46 [&](const SegmentProtection &segprot) { return segprot.name == name; }); 47 if (it != config->segmentProtections.end()) 48 return it->maxProt; 49 50 return initProt(name); 51 } 52 53 static uint32_t flags(StringRef name) { 54 // If we ever implement shared cache output support, SG_READ_ONLY should not 55 // be used for dylibs that can be placed in it. 56 return name == segment_names::dataConst ? (uint32_t)SG_READ_ONLY : 0; 57 } 58 59 size_t OutputSegment::numNonHiddenSections() const { 60 size_t count = 0; 61 for (const OutputSection *osec : sections) 62 count += (!osec->isHidden() ? 1 : 0); 63 return count; 64 } 65 66 void OutputSegment::addOutputSection(OutputSection *osec) { 67 inputOrder = std::min(inputOrder, osec->inputOrder); 68 69 osec->parent = this; 70 sections.push_back(osec); 71 72 for (const SectionAlign §Align : config->sectionAlignments) 73 if (sectAlign.segName == name && sectAlign.sectName == osec->name) 74 osec->align = sectAlign.align; 75 } 76 77 template <typename T, typename F> static auto compareByOrder(F ord) { 78 return [=](T a, T b) { return ord(a) < ord(b); }; 79 } 80 81 static int segmentOrder(OutputSegment *seg) { 82 return StringSwitch<int>(seg->name) 83 .Case(segment_names::pageZero, -4) 84 .Case(segment_names::text, -3) 85 .Case(segment_names::dataConst, -2) 86 .Case(segment_names::data, -1) 87 .Case(segment_names::llvm, std::numeric_limits<int>::max() - 1) 88 // Make sure __LINKEDIT is the last segment (i.e. all its hidden 89 // sections must be ordered after other sections). 90 .Case(segment_names::linkEdit, std::numeric_limits<int>::max()) 91 .Default(seg->inputOrder); 92 } 93 94 static int sectionOrder(OutputSection *osec) { 95 StringRef segname = osec->parent->name; 96 // Sections are uniquely identified by their segment + section name. 97 if (segname == segment_names::text) { 98 if (osec->name == section_names::header) 99 return -7; 100 // `__text` needs to precede the other code sections since its 101 // expected to be the largest. This means in effect that it will 102 // be the section that determines whether we need thunks or not. 103 if (osec->name == section_names::text) 104 return -6; 105 106 // Prioritize specific section ordering based on our knowledge. This ensures 107 // that certain sections are placed in a particular order, even if they 108 // are also categorized as code sections. This explicit ordering takes 109 // precedence over the general code section ordering. 110 int knownPriority = 111 StringSwitch<int>(osec->name) 112 .Case(section_names::stubs, -4) 113 .Case(section_names::stubHelper, -3) 114 .Case(section_names::objcStubs, -2) 115 .Case(section_names::initOffsets, -1) 116 .Case(section_names::unwindInfo, 117 std::numeric_limits<int>::max() - 1) 118 .Case(section_names::ehFrame, std::numeric_limits<int>::max()) 119 .Default(0); 120 121 if (knownPriority != 0) 122 return knownPriority; 123 124 // Ensure all code sections are contiguous with `__text` for thunk 125 // calculations. 126 if (sections::isCodeSection(osec->name, segment_names::text, osec->flags)) { 127 return -5; 128 } 129 130 return osec->inputOrder; 131 } else if (segname == segment_names::data || 132 segname == segment_names::dataConst) { 133 // For each thread spawned, dyld will initialize its TLVs by copying the 134 // address range from the start of the first thread-local data section to 135 // the end of the last one. We therefore arrange these sections contiguously 136 // to minimize the amount of memory used. Additionally, since zerofill 137 // sections must be at the end of their segments, and since TLV data 138 // sections can be zerofills, we end up putting all TLV data sections at the 139 // end of the segment. 140 switch (sectionType(osec->flags)) { 141 case S_THREAD_LOCAL_VARIABLE_POINTERS: 142 return std::numeric_limits<int>::max() - 3; 143 case S_THREAD_LOCAL_REGULAR: 144 return std::numeric_limits<int>::max() - 2; 145 case S_THREAD_LOCAL_ZEROFILL: 146 return std::numeric_limits<int>::max() - 1; 147 case S_ZEROFILL: 148 return std::numeric_limits<int>::max(); 149 default: 150 return StringSwitch<int>(osec->name) 151 .Case(section_names::got, -3) 152 .Case(section_names::lazySymbolPtr, -2) 153 .Case(section_names::const_, -1) 154 .Default(osec->inputOrder); 155 } 156 } else if (segname == segment_names::linkEdit) { 157 return StringSwitch<int>(osec->name) 158 .Case(section_names::chainFixups, -11) 159 .Case(section_names::rebase, -10) 160 .Case(section_names::binding, -9) 161 .Case(section_names::weakBinding, -8) 162 .Case(section_names::lazyBinding, -7) 163 .Case(section_names::export_, -6) 164 .Case(section_names::functionStarts, -5) 165 .Case(section_names::dataInCode, -4) 166 .Case(section_names::symbolTable, -3) 167 .Case(section_names::indirectSymbolTable, -2) 168 .Case(section_names::stringTable, -1) 169 .Case(section_names::codeSignature, std::numeric_limits<int>::max()) 170 .Default(osec->inputOrder); 171 } 172 // ZeroFill sections must always be the at the end of their segments: 173 // dyld checks if a segment's file size is smaller than its in-memory 174 // size to detect if a segment has zerofill sections, and if so it maps 175 // the missing tail as zerofill. 176 if (sectionType(osec->flags) == S_ZEROFILL) 177 return std::numeric_limits<int>::max(); 178 return osec->inputOrder; 179 } 180 181 void OutputSegment::sortOutputSections() { 182 // Must be stable_sort() to keep special sections such as 183 // S_THREAD_LOCAL_REGULAR in input order. 184 llvm::stable_sort(sections, compareByOrder<OutputSection *>(sectionOrder)); 185 } 186 187 void OutputSegment::assignAddressesToStartEndSymbols() { 188 for (Defined *d : segmentStartSymbols) 189 d->value = addr; 190 for (Defined *d : segmentEndSymbols) 191 d->value = addr + vmSize; 192 } 193 194 void macho::sortOutputSegments() { 195 llvm::stable_sort(outputSegments, 196 compareByOrder<OutputSegment *>(segmentOrder)); 197 } 198 199 static DenseMap<StringRef, OutputSegment *> nameToOutputSegment; 200 std::vector<OutputSegment *> macho::outputSegments; 201 202 void macho::resetOutputSegments() { 203 outputSegments.clear(); 204 nameToOutputSegment.clear(); 205 } 206 207 static StringRef maybeRenameSegment(StringRef name) { 208 auto newName = config->segmentRenameMap.find(name); 209 if (newName != config->segmentRenameMap.end()) 210 return newName->second; 211 return name; 212 } 213 214 OutputSegment *macho::getOrCreateOutputSegment(StringRef name) { 215 name = maybeRenameSegment(name); 216 217 OutputSegment *&segRef = nameToOutputSegment[name]; 218 if (segRef) 219 return segRef; 220 221 segRef = make<OutputSegment>(); 222 segRef->name = name; 223 segRef->maxProt = maxProt(name); 224 segRef->initProt = initProt(name); 225 segRef->flags = flags(name); 226 227 outputSegments.push_back(segRef); 228 return segRef; 229 } 230