15ffd83dbSDimitry Andric //===- OutputSegment.cpp --------------------------------------------------===// 25ffd83dbSDimitry Andric // 35ffd83dbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 45ffd83dbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 55ffd83dbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65ffd83dbSDimitry Andric // 75ffd83dbSDimitry Andric //===----------------------------------------------------------------------===// 85ffd83dbSDimitry Andric 95ffd83dbSDimitry Andric #include "OutputSegment.h" 10fe6060f1SDimitry Andric #include "ConcatOutputSection.h" 115ffd83dbSDimitry Andric #include "InputSection.h" 12fe6060f1SDimitry Andric #include "Symbols.h" 135ffd83dbSDimitry Andric #include "SyntheticSections.h" 145ffd83dbSDimitry Andric 155ffd83dbSDimitry Andric #include "lld/Common/ErrorHandler.h" 165ffd83dbSDimitry Andric #include "lld/Common/Memory.h" 17fe6060f1SDimitry Andric #include "llvm/ADT/StringSwitch.h" 185ffd83dbSDimitry Andric #include "llvm/BinaryFormat/MachO.h" 195ffd83dbSDimitry Andric 205ffd83dbSDimitry Andric using namespace llvm; 215ffd83dbSDimitry Andric using namespace llvm::MachO; 225ffd83dbSDimitry Andric using namespace lld; 235ffd83dbSDimitry Andric using namespace lld::macho; 245ffd83dbSDimitry Andric 255ffd83dbSDimitry Andric static uint32_t initProt(StringRef name) { 26fe6060f1SDimitry Andric auto it = find_if( 27fe6060f1SDimitry Andric config->segmentProtections, 28fe6060f1SDimitry Andric [&](const SegmentProtection &segprot) { return segprot.name == name; }); 29fe6060f1SDimitry Andric if (it != config->segmentProtections.end()) 30fe6060f1SDimitry Andric return it->initProt; 31fe6060f1SDimitry Andric 325ffd83dbSDimitry Andric if (name == segment_names::text) 335ffd83dbSDimitry Andric return VM_PROT_READ | VM_PROT_EXECUTE; 345ffd83dbSDimitry Andric if (name == segment_names::pageZero) 355ffd83dbSDimitry Andric return 0; 365ffd83dbSDimitry Andric if (name == segment_names::linkEdit) 375ffd83dbSDimitry Andric return VM_PROT_READ; 385ffd83dbSDimitry Andric return VM_PROT_READ | VM_PROT_WRITE; 395ffd83dbSDimitry Andric } 405ffd83dbSDimitry Andric 415ffd83dbSDimitry Andric static uint32_t maxProt(StringRef name) { 42fe6060f1SDimitry Andric assert(config->arch() != AK_i386 && 43e8d8bef9SDimitry Andric "TODO: i386 has different maxProt requirements"); 44e8d8bef9SDimitry Andric return initProt(name); 455ffd83dbSDimitry Andric } 465ffd83dbSDimitry Andric 475ffd83dbSDimitry Andric size_t OutputSegment::numNonHiddenSections() const { 485ffd83dbSDimitry Andric size_t count = 0; 49fe6060f1SDimitry Andric for (const OutputSection *osec : sections) 505ffd83dbSDimitry Andric count += (!osec->isHidden() ? 1 : 0); 515ffd83dbSDimitry Andric return count; 525ffd83dbSDimitry Andric } 535ffd83dbSDimitry Andric 545ffd83dbSDimitry Andric void OutputSegment::addOutputSection(OutputSection *osec) { 55fe6060f1SDimitry Andric inputOrder = std::min(inputOrder, osec->inputOrder); 56fe6060f1SDimitry Andric 575ffd83dbSDimitry Andric osec->parent = this; 585ffd83dbSDimitry Andric sections.push_back(osec); 59fe6060f1SDimitry Andric 60fe6060f1SDimitry Andric for (const SectionAlign §Align : config->sectionAlignments) 61fe6060f1SDimitry Andric if (sectAlign.segName == name && sectAlign.sectName == osec->name) 62fe6060f1SDimitry Andric osec->align = sectAlign.align; 63fe6060f1SDimitry Andric } 64fe6060f1SDimitry Andric 65fe6060f1SDimitry Andric template <typename T, typename F> static auto compareByOrder(F ord) { 66fe6060f1SDimitry Andric return [=](T a, T b) { return ord(a) < ord(b); }; 67fe6060f1SDimitry Andric } 68fe6060f1SDimitry Andric 69fe6060f1SDimitry Andric static int segmentOrder(OutputSegment *seg) { 70fe6060f1SDimitry Andric return StringSwitch<int>(seg->name) 71fe6060f1SDimitry Andric .Case(segment_names::pageZero, -4) 72fe6060f1SDimitry Andric .Case(segment_names::text, -3) 73fe6060f1SDimitry Andric .Case(segment_names::dataConst, -2) 74fe6060f1SDimitry Andric .Case(segment_names::data, -1) 75fe6060f1SDimitry Andric .Case(segment_names::llvm, std::numeric_limits<int>::max() - 1) 76fe6060f1SDimitry Andric // Make sure __LINKEDIT is the last segment (i.e. all its hidden 77fe6060f1SDimitry Andric // sections must be ordered after other sections). 78fe6060f1SDimitry Andric .Case(segment_names::linkEdit, std::numeric_limits<int>::max()) 79fe6060f1SDimitry Andric .Default(seg->inputOrder); 80fe6060f1SDimitry Andric } 81fe6060f1SDimitry Andric 82fe6060f1SDimitry Andric static int sectionOrder(OutputSection *osec) { 83fe6060f1SDimitry Andric StringRef segname = osec->parent->name; 84fe6060f1SDimitry Andric // Sections are uniquely identified by their segment + section name. 85fe6060f1SDimitry Andric if (segname == segment_names::text) { 86fe6060f1SDimitry Andric return StringSwitch<int>(osec->name) 87fe6060f1SDimitry Andric .Case(section_names::header, -4) 88fe6060f1SDimitry Andric .Case(section_names::text, -3) 89fe6060f1SDimitry Andric .Case(section_names::stubs, -2) 90fe6060f1SDimitry Andric .Case(section_names::stubHelper, -1) 91fe6060f1SDimitry Andric .Case(section_names::unwindInfo, std::numeric_limits<int>::max() - 1) 92fe6060f1SDimitry Andric .Case(section_names::ehFrame, std::numeric_limits<int>::max()) 93fe6060f1SDimitry Andric .Default(osec->inputOrder); 94fe6060f1SDimitry Andric } else if (segname == segment_names::data || 95fe6060f1SDimitry Andric segname == segment_names::dataConst) { 96fe6060f1SDimitry Andric // For each thread spawned, dyld will initialize its TLVs by copying the 97fe6060f1SDimitry Andric // address range from the start of the first thread-local data section to 98fe6060f1SDimitry Andric // the end of the last one. We therefore arrange these sections contiguously 99fe6060f1SDimitry Andric // to minimize the amount of memory used. Additionally, since zerofill 100fe6060f1SDimitry Andric // sections must be at the end of their segments, and since TLV data 101fe6060f1SDimitry Andric // sections can be zerofills, we end up putting all TLV data sections at the 102fe6060f1SDimitry Andric // end of the segment. 103fe6060f1SDimitry Andric switch (sectionType(osec->flags)) { 104fe6060f1SDimitry Andric case S_THREAD_LOCAL_VARIABLE_POINTERS: 105fe6060f1SDimitry Andric return std::numeric_limits<int>::max() - 3; 106fe6060f1SDimitry Andric case S_THREAD_LOCAL_REGULAR: 107fe6060f1SDimitry Andric return std::numeric_limits<int>::max() - 2; 108fe6060f1SDimitry Andric case S_THREAD_LOCAL_ZEROFILL: 109fe6060f1SDimitry Andric return std::numeric_limits<int>::max() - 1; 110fe6060f1SDimitry Andric case S_ZEROFILL: 111fe6060f1SDimitry Andric return std::numeric_limits<int>::max(); 112fe6060f1SDimitry Andric default: 113fe6060f1SDimitry Andric return StringSwitch<int>(osec->name) 114fe6060f1SDimitry Andric .Case(section_names::got, -3) 115fe6060f1SDimitry Andric .Case(section_names::lazySymbolPtr, -2) 116fe6060f1SDimitry Andric .Case(section_names::const_, -1) 117fe6060f1SDimitry Andric .Default(osec->inputOrder); 118fe6060f1SDimitry Andric } 119fe6060f1SDimitry Andric } else if (segname == segment_names::linkEdit) { 120fe6060f1SDimitry Andric return StringSwitch<int>(osec->name) 121fe6060f1SDimitry Andric .Case(section_names::rebase, -10) 122fe6060f1SDimitry Andric .Case(section_names::binding, -9) 123fe6060f1SDimitry Andric .Case(section_names::weakBinding, -8) 124fe6060f1SDimitry Andric .Case(section_names::lazyBinding, -7) 125fe6060f1SDimitry Andric .Case(section_names::export_, -6) 126fe6060f1SDimitry Andric .Case(section_names::functionStarts, -5) 127fe6060f1SDimitry Andric .Case(section_names::dataInCode, -4) 128fe6060f1SDimitry Andric .Case(section_names::symbolTable, -3) 129fe6060f1SDimitry Andric .Case(section_names::indirectSymbolTable, -2) 130fe6060f1SDimitry Andric .Case(section_names::stringTable, -1) 131fe6060f1SDimitry Andric .Case(section_names::codeSignature, std::numeric_limits<int>::max()) 132fe6060f1SDimitry Andric .Default(osec->inputOrder); 133fe6060f1SDimitry Andric } 134fe6060f1SDimitry Andric // ZeroFill sections must always be the at the end of their segments: 135fe6060f1SDimitry Andric // dyld checks if a segment's file size is smaller than its in-memory 136fe6060f1SDimitry Andric // size to detect if a segment has zerofill sections, and if so it maps 137fe6060f1SDimitry Andric // the missing tail as zerofill. 138fe6060f1SDimitry Andric if (sectionType(osec->flags) == S_ZEROFILL) 139fe6060f1SDimitry Andric return std::numeric_limits<int>::max(); 140fe6060f1SDimitry Andric return osec->inputOrder; 141fe6060f1SDimitry Andric } 142fe6060f1SDimitry Andric 143fe6060f1SDimitry Andric void OutputSegment::sortOutputSections() { 144fe6060f1SDimitry Andric // Must be stable_sort() to keep special sections such as 145fe6060f1SDimitry Andric // S_THREAD_LOCAL_REGULAR in input order. 146fe6060f1SDimitry Andric llvm::stable_sort(sections, compareByOrder<OutputSection *>(sectionOrder)); 147fe6060f1SDimitry Andric } 148fe6060f1SDimitry Andric 149fe6060f1SDimitry Andric void OutputSegment::assignAddressesToStartEndSymbols() { 150fe6060f1SDimitry Andric for (Defined *d : segmentStartSymbols) 151fe6060f1SDimitry Andric d->value = addr; 152fe6060f1SDimitry Andric for (Defined *d : segmentEndSymbols) 153fe6060f1SDimitry Andric d->value = addr + vmSize; 154fe6060f1SDimitry Andric } 155fe6060f1SDimitry Andric 156fe6060f1SDimitry Andric void macho::sortOutputSegments() { 157fe6060f1SDimitry Andric llvm::stable_sort(outputSegments, 158fe6060f1SDimitry Andric compareByOrder<OutputSegment *>(segmentOrder)); 1595ffd83dbSDimitry Andric } 1605ffd83dbSDimitry Andric 161e8d8bef9SDimitry Andric static DenseMap<StringRef, OutputSegment *> nameToOutputSegment; 1625ffd83dbSDimitry Andric std::vector<OutputSegment *> macho::outputSegments; 1635ffd83dbSDimitry Andric 164*349cc55cSDimitry Andric void macho::resetOutputSegments() { 165*349cc55cSDimitry Andric outputSegments.clear(); 166*349cc55cSDimitry Andric nameToOutputSegment.clear(); 167*349cc55cSDimitry Andric } 168*349cc55cSDimitry Andric 169fe6060f1SDimitry Andric static StringRef maybeRenameSegment(StringRef name) { 170fe6060f1SDimitry Andric auto newName = config->segmentRenameMap.find(name); 171fe6060f1SDimitry Andric if (newName != config->segmentRenameMap.end()) 172fe6060f1SDimitry Andric return newName->second; 173fe6060f1SDimitry Andric return name; 174fe6060f1SDimitry Andric } 175fe6060f1SDimitry Andric 1765ffd83dbSDimitry Andric OutputSegment *macho::getOrCreateOutputSegment(StringRef name) { 177fe6060f1SDimitry Andric name = maybeRenameSegment(name); 178fe6060f1SDimitry Andric 1795ffd83dbSDimitry Andric OutputSegment *&segRef = nameToOutputSegment[name]; 180e8d8bef9SDimitry Andric if (segRef) 1815ffd83dbSDimitry Andric return segRef; 1825ffd83dbSDimitry Andric 1835ffd83dbSDimitry Andric segRef = make<OutputSegment>(); 1845ffd83dbSDimitry Andric segRef->name = name; 1855ffd83dbSDimitry Andric segRef->maxProt = maxProt(name); 1865ffd83dbSDimitry Andric segRef->initProt = initProt(name); 1875ffd83dbSDimitry Andric 1885ffd83dbSDimitry Andric outputSegments.push_back(segRef); 1895ffd83dbSDimitry Andric return segRef; 1905ffd83dbSDimitry Andric } 191