xref: /openbsd-src/gnu/llvm/lld/MachO/OutputSegment.cpp (revision dfe94b169149f14cc1aee2cf6dad58a8d9a1860c)
1bb684c34Spatrick //===- OutputSegment.cpp --------------------------------------------------===//
2bb684c34Spatrick //
3bb684c34Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4bb684c34Spatrick // See https://llvm.org/LICENSE.txt for license information.
5bb684c34Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6bb684c34Spatrick //
7bb684c34Spatrick //===----------------------------------------------------------------------===//
8bb684c34Spatrick 
9bb684c34Spatrick #include "OutputSegment.h"
101cf9926bSpatrick #include "ConcatOutputSection.h"
11bb684c34Spatrick #include "InputSection.h"
121cf9926bSpatrick #include "Symbols.h"
13bb684c34Spatrick #include "SyntheticSections.h"
14bb684c34Spatrick 
15bb684c34Spatrick #include "lld/Common/ErrorHandler.h"
16bb684c34Spatrick #include "lld/Common/Memory.h"
171cf9926bSpatrick #include "llvm/ADT/StringSwitch.h"
18bb684c34Spatrick #include "llvm/BinaryFormat/MachO.h"
19bb684c34Spatrick 
20bb684c34Spatrick using namespace llvm;
21bb684c34Spatrick using namespace llvm::MachO;
22bb684c34Spatrick using namespace lld;
23bb684c34Spatrick using namespace lld::macho;
24bb684c34Spatrick 
initProt(StringRef name)25bb684c34Spatrick static uint32_t initProt(StringRef name) {
261cf9926bSpatrick   auto it = find_if(
271cf9926bSpatrick       config->segmentProtections,
281cf9926bSpatrick       [&](const SegmentProtection &segprot) { return segprot.name == name; });
291cf9926bSpatrick   if (it != config->segmentProtections.end())
301cf9926bSpatrick     return it->initProt;
311cf9926bSpatrick 
32bb684c34Spatrick   if (name == segment_names::text)
33bb684c34Spatrick     return VM_PROT_READ | VM_PROT_EXECUTE;
34bb684c34Spatrick   if (name == segment_names::pageZero)
35bb684c34Spatrick     return 0;
36bb684c34Spatrick   if (name == segment_names::linkEdit)
37bb684c34Spatrick     return VM_PROT_READ;
38bb684c34Spatrick   return VM_PROT_READ | VM_PROT_WRITE;
39bb684c34Spatrick }
40bb684c34Spatrick 
maxProt(StringRef name)41bb684c34Spatrick static uint32_t maxProt(StringRef name) {
421cf9926bSpatrick   assert(config->arch() != AK_i386 &&
431cf9926bSpatrick          "TODO: i386 has different maxProt requirements");
441cf9926bSpatrick   return initProt(name);
45bb684c34Spatrick }
46bb684c34Spatrick 
flags(StringRef name)47*dfe94b16Srobert static uint32_t flags(StringRef name) {
48*dfe94b16Srobert   // If we ever implement shared cache output support, SG_READ_ONLY should not
49*dfe94b16Srobert   // be used for dylibs that can be placed in it.
50*dfe94b16Srobert   return name == segment_names::dataConst ? (uint32_t)SG_READ_ONLY : 0;
51*dfe94b16Srobert }
52*dfe94b16Srobert 
numNonHiddenSections() const53bb684c34Spatrick size_t OutputSegment::numNonHiddenSections() const {
54bb684c34Spatrick   size_t count = 0;
551cf9926bSpatrick   for (const OutputSection *osec : sections)
56bb684c34Spatrick     count += (!osec->isHidden() ? 1 : 0);
57bb684c34Spatrick   return count;
58bb684c34Spatrick }
59bb684c34Spatrick 
addOutputSection(OutputSection * osec)60bb684c34Spatrick void OutputSegment::addOutputSection(OutputSection *osec) {
611cf9926bSpatrick   inputOrder = std::min(inputOrder, osec->inputOrder);
621cf9926bSpatrick 
63bb684c34Spatrick   osec->parent = this;
64bb684c34Spatrick   sections.push_back(osec);
651cf9926bSpatrick 
661cf9926bSpatrick   for (const SectionAlign &sectAlign : config->sectionAlignments)
671cf9926bSpatrick     if (sectAlign.segName == name && sectAlign.sectName == osec->name)
681cf9926bSpatrick       osec->align = sectAlign.align;
69bb684c34Spatrick }
70bb684c34Spatrick 
compareByOrder(F ord)711cf9926bSpatrick template <typename T, typename F> static auto compareByOrder(F ord) {
721cf9926bSpatrick   return [=](T a, T b) { return ord(a) < ord(b); };
731cf9926bSpatrick }
741cf9926bSpatrick 
segmentOrder(OutputSegment * seg)751cf9926bSpatrick static int segmentOrder(OutputSegment *seg) {
761cf9926bSpatrick   return StringSwitch<int>(seg->name)
771cf9926bSpatrick       .Case(segment_names::pageZero, -4)
781cf9926bSpatrick       .Case(segment_names::text, -3)
791cf9926bSpatrick       .Case(segment_names::dataConst, -2)
801cf9926bSpatrick       .Case(segment_names::data, -1)
811cf9926bSpatrick       .Case(segment_names::llvm, std::numeric_limits<int>::max() - 1)
821cf9926bSpatrick       // Make sure __LINKEDIT is the last segment (i.e. all its hidden
831cf9926bSpatrick       // sections must be ordered after other sections).
841cf9926bSpatrick       .Case(segment_names::linkEdit, std::numeric_limits<int>::max())
851cf9926bSpatrick       .Default(seg->inputOrder);
861cf9926bSpatrick }
871cf9926bSpatrick 
sectionOrder(OutputSection * osec)881cf9926bSpatrick static int sectionOrder(OutputSection *osec) {
891cf9926bSpatrick   StringRef segname = osec->parent->name;
901cf9926bSpatrick   // Sections are uniquely identified by their segment + section name.
911cf9926bSpatrick   if (segname == segment_names::text) {
921cf9926bSpatrick     return StringSwitch<int>(osec->name)
93*dfe94b16Srobert         .Case(section_names::header, -6)
94*dfe94b16Srobert         .Case(section_names::text, -5)
95*dfe94b16Srobert         .Case(section_names::stubs, -4)
96*dfe94b16Srobert         .Case(section_names::stubHelper, -3)
97*dfe94b16Srobert         .Case(section_names::objcStubs, -2)
98*dfe94b16Srobert         .Case(section_names::initOffsets, -1)
991cf9926bSpatrick         .Case(section_names::unwindInfo, std::numeric_limits<int>::max() - 1)
1001cf9926bSpatrick         .Case(section_names::ehFrame, std::numeric_limits<int>::max())
1011cf9926bSpatrick         .Default(osec->inputOrder);
1021cf9926bSpatrick   } else if (segname == segment_names::data ||
1031cf9926bSpatrick              segname == segment_names::dataConst) {
1041cf9926bSpatrick     // For each thread spawned, dyld will initialize its TLVs by copying the
1051cf9926bSpatrick     // address range from the start of the first thread-local data section to
1061cf9926bSpatrick     // the end of the last one. We therefore arrange these sections contiguously
1071cf9926bSpatrick     // to minimize the amount of memory used. Additionally, since zerofill
1081cf9926bSpatrick     // sections must be at the end of their segments, and since TLV data
1091cf9926bSpatrick     // sections can be zerofills, we end up putting all TLV data sections at the
1101cf9926bSpatrick     // end of the segment.
1111cf9926bSpatrick     switch (sectionType(osec->flags)) {
1121cf9926bSpatrick     case S_THREAD_LOCAL_VARIABLE_POINTERS:
1131cf9926bSpatrick       return std::numeric_limits<int>::max() - 3;
1141cf9926bSpatrick     case S_THREAD_LOCAL_REGULAR:
1151cf9926bSpatrick       return std::numeric_limits<int>::max() - 2;
1161cf9926bSpatrick     case S_THREAD_LOCAL_ZEROFILL:
1171cf9926bSpatrick       return std::numeric_limits<int>::max() - 1;
1181cf9926bSpatrick     case S_ZEROFILL:
1191cf9926bSpatrick       return std::numeric_limits<int>::max();
1201cf9926bSpatrick     default:
1211cf9926bSpatrick       return StringSwitch<int>(osec->name)
1221cf9926bSpatrick           .Case(section_names::got, -3)
1231cf9926bSpatrick           .Case(section_names::lazySymbolPtr, -2)
1241cf9926bSpatrick           .Case(section_names::const_, -1)
1251cf9926bSpatrick           .Default(osec->inputOrder);
1261cf9926bSpatrick     }
1271cf9926bSpatrick   } else if (segname == segment_names::linkEdit) {
1281cf9926bSpatrick     return StringSwitch<int>(osec->name)
129*dfe94b16Srobert         .Case(section_names::chainFixups, -11)
1301cf9926bSpatrick         .Case(section_names::rebase, -10)
1311cf9926bSpatrick         .Case(section_names::binding, -9)
1321cf9926bSpatrick         .Case(section_names::weakBinding, -8)
1331cf9926bSpatrick         .Case(section_names::lazyBinding, -7)
1341cf9926bSpatrick         .Case(section_names::export_, -6)
1351cf9926bSpatrick         .Case(section_names::functionStarts, -5)
1361cf9926bSpatrick         .Case(section_names::dataInCode, -4)
1371cf9926bSpatrick         .Case(section_names::symbolTable, -3)
1381cf9926bSpatrick         .Case(section_names::indirectSymbolTable, -2)
1391cf9926bSpatrick         .Case(section_names::stringTable, -1)
1401cf9926bSpatrick         .Case(section_names::codeSignature, std::numeric_limits<int>::max())
1411cf9926bSpatrick         .Default(osec->inputOrder);
1421cf9926bSpatrick   }
1431cf9926bSpatrick   // ZeroFill sections must always be the at the end of their segments:
1441cf9926bSpatrick   // dyld checks if a segment's file size is smaller than its in-memory
1451cf9926bSpatrick   // size to detect if a segment has zerofill sections, and if so it maps
1461cf9926bSpatrick   // the missing tail as zerofill.
1471cf9926bSpatrick   if (sectionType(osec->flags) == S_ZEROFILL)
1481cf9926bSpatrick     return std::numeric_limits<int>::max();
1491cf9926bSpatrick   return osec->inputOrder;
1501cf9926bSpatrick }
1511cf9926bSpatrick 
sortOutputSections()1521cf9926bSpatrick void OutputSegment::sortOutputSections() {
1531cf9926bSpatrick   // Must be stable_sort() to keep special sections such as
1541cf9926bSpatrick   // S_THREAD_LOCAL_REGULAR in input order.
1551cf9926bSpatrick   llvm::stable_sort(sections, compareByOrder<OutputSection *>(sectionOrder));
1561cf9926bSpatrick }
1571cf9926bSpatrick 
assignAddressesToStartEndSymbols()1581cf9926bSpatrick void OutputSegment::assignAddressesToStartEndSymbols() {
1591cf9926bSpatrick   for (Defined *d : segmentStartSymbols)
1601cf9926bSpatrick     d->value = addr;
1611cf9926bSpatrick   for (Defined *d : segmentEndSymbols)
1621cf9926bSpatrick     d->value = addr + vmSize;
1631cf9926bSpatrick }
1641cf9926bSpatrick 
sortOutputSegments()1651cf9926bSpatrick void macho::sortOutputSegments() {
1661cf9926bSpatrick   llvm::stable_sort(outputSegments,
1671cf9926bSpatrick                     compareByOrder<OutputSegment *>(segmentOrder));
1681cf9926bSpatrick }
1691cf9926bSpatrick 
1701cf9926bSpatrick static DenseMap<StringRef, OutputSegment *> nameToOutputSegment;
171bb684c34Spatrick std::vector<OutputSegment *> macho::outputSegments;
172bb684c34Spatrick 
resetOutputSegments()173*dfe94b16Srobert void macho::resetOutputSegments() {
174*dfe94b16Srobert   outputSegments.clear();
175*dfe94b16Srobert   nameToOutputSegment.clear();
176*dfe94b16Srobert }
177*dfe94b16Srobert 
maybeRenameSegment(StringRef name)1781cf9926bSpatrick static StringRef maybeRenameSegment(StringRef name) {
1791cf9926bSpatrick   auto newName = config->segmentRenameMap.find(name);
1801cf9926bSpatrick   if (newName != config->segmentRenameMap.end())
1811cf9926bSpatrick     return newName->second;
1821cf9926bSpatrick   return name;
1831cf9926bSpatrick }
1841cf9926bSpatrick 
getOrCreateOutputSegment(StringRef name)185bb684c34Spatrick OutputSegment *macho::getOrCreateOutputSegment(StringRef name) {
1861cf9926bSpatrick   name = maybeRenameSegment(name);
1871cf9926bSpatrick 
188bb684c34Spatrick   OutputSegment *&segRef = nameToOutputSegment[name];
1891cf9926bSpatrick   if (segRef)
190bb684c34Spatrick     return segRef;
191bb684c34Spatrick 
192bb684c34Spatrick   segRef = make<OutputSegment>();
193bb684c34Spatrick   segRef->name = name;
194bb684c34Spatrick   segRef->maxProt = maxProt(name);
195bb684c34Spatrick   segRef->initProt = initProt(name);
196*dfe94b16Srobert   segRef->flags = flags(name);
197bb684c34Spatrick 
198bb684c34Spatrick   outputSegments.push_back(segRef);
199bb684c34Spatrick   return segRef;
200bb684c34Spatrick }
201