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   auto it = find_if(
25       config->segmentProtections,
26       [&](const SegmentProtection &segprot) { return segprot.name == name; });
27   if (it != config->segmentProtections.end())
28     return it->initProt;
29 
30   if (name == segment_names::text)
31     return VM_PROT_READ | VM_PROT_EXECUTE;
32   if (name == segment_names::pageZero)
33     return 0;
34   if (name == segment_names::linkEdit)
35     return VM_PROT_READ;
36   return VM_PROT_READ | VM_PROT_WRITE;
37 }
38 
39 static uint32_t maxProt(StringRef name) {
40   assert(config->arch() != AK_i386 &&
41          "TODO: i386 has different maxProt requirements");
42   return initProt(name);
43 }
44 
45 size_t OutputSegment::numNonHiddenSections() const {
46   size_t count = 0;
47   for (const OutputSection *osec : sections)
48     count += (!osec->isHidden() ? 1 : 0);
49   return count;
50 }
51 
52 void OutputSegment::addOutputSection(OutputSection *osec) {
53   osec->parent = this;
54   sections.push_back(osec);
55 
56   for (const SectionAlign &sectAlign : config->sectionAlignments)
57     if (sectAlign.segName == name && sectAlign.sectName == osec->name)
58       osec->align = sectAlign.align;
59 }
60 
61 static DenseMap<StringRef, OutputSegment *> nameToOutputSegment;
62 std::vector<OutputSegment *> macho::outputSegments;
63 
64 OutputSegment *macho::getOrCreateOutputSegment(StringRef name) {
65   OutputSegment *&segRef = nameToOutputSegment[name];
66   if (segRef)
67     return segRef;
68 
69   segRef = make<OutputSegment>();
70   segRef->name = name;
71   segRef->maxProt = maxProt(name);
72   segRef->initProt = initProt(name);
73 
74   outputSegments.push_back(segRef);
75   return segRef;
76 }
77