xref: /freebsd/contrib/llvm-project/lld/MachO/InputSection.h (revision fe6060f10f634930ff71b7c50291ddc610da2475)
15ffd83dbSDimitry Andric //===- InputSection.h -------------------------------------------*- C++ -*-===//
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 #ifndef LLD_MACHO_INPUT_SECTION_H
105ffd83dbSDimitry Andric #define LLD_MACHO_INPUT_SECTION_H
115ffd83dbSDimitry Andric 
12*fe6060f1SDimitry Andric #include "Config.h"
13*fe6060f1SDimitry Andric #include "Relocations.h"
14*fe6060f1SDimitry Andric 
155ffd83dbSDimitry Andric #include "lld/Common/LLVM.h"
16*fe6060f1SDimitry Andric #include "lld/Common/Memory.h"
175ffd83dbSDimitry Andric #include "llvm/ADT/ArrayRef.h"
18*fe6060f1SDimitry Andric #include "llvm/ADT/BitVector.h"
19*fe6060f1SDimitry Andric #include "llvm/ADT/CachedHashString.h"
205ffd83dbSDimitry Andric #include "llvm/BinaryFormat/MachO.h"
215ffd83dbSDimitry Andric 
225ffd83dbSDimitry Andric namespace lld {
235ffd83dbSDimitry Andric namespace macho {
245ffd83dbSDimitry Andric 
255ffd83dbSDimitry Andric class InputFile;
265ffd83dbSDimitry Andric class OutputSection;
27*fe6060f1SDimitry Andric class Defined;
285ffd83dbSDimitry Andric 
295ffd83dbSDimitry Andric class InputSection {
305ffd83dbSDimitry Andric public:
31*fe6060f1SDimitry Andric   enum Kind {
32*fe6060f1SDimitry Andric     ConcatKind,
33*fe6060f1SDimitry Andric     CStringLiteralKind,
34*fe6060f1SDimitry Andric     WordLiteralKind,
35*fe6060f1SDimitry Andric   };
36*fe6060f1SDimitry Andric 
37*fe6060f1SDimitry Andric   Kind kind() const { return shared->sectionKind; }
385ffd83dbSDimitry Andric   virtual ~InputSection() = default;
395ffd83dbSDimitry Andric   virtual uint64_t getSize() const { return data.size(); }
40*fe6060f1SDimitry Andric   InputFile *getFile() const { return shared->file; }
41*fe6060f1SDimitry Andric   StringRef getName() const { return shared->name; }
42*fe6060f1SDimitry Andric   StringRef getSegName() const { return shared->segname; }
43*fe6060f1SDimitry Andric   uint32_t getFlags() const { return shared->flags; }
44*fe6060f1SDimitry Andric   uint64_t getFileSize() const;
45*fe6060f1SDimitry Andric   // Translates \p off -- an offset relative to this InputSection -- into an
46*fe6060f1SDimitry Andric   // offset from the beginning of its parent OutputSection.
47*fe6060f1SDimitry Andric   virtual uint64_t getOffset(uint64_t off) const = 0;
48*fe6060f1SDimitry Andric   // The offset from the beginning of the file.
49*fe6060f1SDimitry Andric   uint64_t getVA(uint64_t off) const;
50*fe6060f1SDimitry Andric   // Whether the data at \p off in this InputSection is live.
51*fe6060f1SDimitry Andric   virtual bool isLive(uint64_t off) const = 0;
52*fe6060f1SDimitry Andric   virtual void markLive(uint64_t off) = 0;
53*fe6060f1SDimitry Andric   virtual InputSection *canonical() { return this; }
545ffd83dbSDimitry Andric 
555ffd83dbSDimitry Andric   OutputSection *parent = nullptr;
565ffd83dbSDimitry Andric 
575ffd83dbSDimitry Andric   uint32_t align = 1;
58*fe6060f1SDimitry Andric   uint32_t callSiteCount : 31;
59*fe6060f1SDimitry Andric   // is address assigned?
60*fe6060f1SDimitry Andric   uint32_t isFinal : 1;
615ffd83dbSDimitry Andric 
625ffd83dbSDimitry Andric   ArrayRef<uint8_t> data;
635ffd83dbSDimitry Andric   std::vector<Reloc> relocs;
64*fe6060f1SDimitry Andric 
65*fe6060f1SDimitry Andric protected:
66*fe6060f1SDimitry Andric   // The fields in this struct are immutable. Since we create a lot of
67*fe6060f1SDimitry Andric   // InputSections with identical values for them (due to
68*fe6060f1SDimitry Andric   // .subsections_via_symbols), factoring them out into a shared struct reduces
69*fe6060f1SDimitry Andric   // memory consumption and makes copying cheaper.
70*fe6060f1SDimitry Andric   struct Shared {
71*fe6060f1SDimitry Andric     InputFile *file;
72*fe6060f1SDimitry Andric     StringRef name;
73*fe6060f1SDimitry Andric     StringRef segname;
74*fe6060f1SDimitry Andric     uint32_t flags;
75*fe6060f1SDimitry Andric     Kind sectionKind;
76*fe6060f1SDimitry Andric     Shared(InputFile *file, StringRef name, StringRef segname, uint32_t flags,
77*fe6060f1SDimitry Andric            Kind kind)
78*fe6060f1SDimitry Andric         : file(file), name(name), segname(segname), flags(flags),
79*fe6060f1SDimitry Andric           sectionKind(kind) {}
80*fe6060f1SDimitry Andric   };
81*fe6060f1SDimitry Andric 
82*fe6060f1SDimitry Andric   InputSection(Kind kind, StringRef segname, StringRef name)
83*fe6060f1SDimitry Andric       : callSiteCount(0), isFinal(false),
84*fe6060f1SDimitry Andric         shared(make<Shared>(nullptr, name, segname, 0, kind)) {}
85*fe6060f1SDimitry Andric 
86*fe6060f1SDimitry Andric   InputSection(Kind kind, StringRef segname, StringRef name, InputFile *file,
87*fe6060f1SDimitry Andric                ArrayRef<uint8_t> data, uint32_t align, uint32_t flags)
88*fe6060f1SDimitry Andric       : align(align), callSiteCount(0), isFinal(false), data(data),
89*fe6060f1SDimitry Andric         shared(make<Shared>(file, name, segname, flags, kind)) {}
90*fe6060f1SDimitry Andric 
91*fe6060f1SDimitry Andric   const Shared *const shared;
92*fe6060f1SDimitry Andric };
93*fe6060f1SDimitry Andric 
94*fe6060f1SDimitry Andric // ConcatInputSections are combined into (Concat)OutputSections through simple
95*fe6060f1SDimitry Andric // concatenation, in contrast with literal sections which may have their
96*fe6060f1SDimitry Andric // contents merged before output.
97*fe6060f1SDimitry Andric class ConcatInputSection final : public InputSection {
98*fe6060f1SDimitry Andric public:
99*fe6060f1SDimitry Andric   ConcatInputSection(StringRef segname, StringRef name)
100*fe6060f1SDimitry Andric       : InputSection(ConcatKind, segname, name) {}
101*fe6060f1SDimitry Andric 
102*fe6060f1SDimitry Andric   ConcatInputSection(StringRef segname, StringRef name, InputFile *file,
103*fe6060f1SDimitry Andric                      ArrayRef<uint8_t> data, uint32_t align = 1,
104*fe6060f1SDimitry Andric                      uint32_t flags = 0)
105*fe6060f1SDimitry Andric       : InputSection(ConcatKind, segname, name, file, data, align, flags) {}
106*fe6060f1SDimitry Andric 
107*fe6060f1SDimitry Andric   uint64_t getOffset(uint64_t off) const override { return outSecOff + off; }
108*fe6060f1SDimitry Andric   uint64_t getVA() const { return InputSection::getVA(0); }
109*fe6060f1SDimitry Andric   // ConcatInputSections are entirely live or dead, so the offset is irrelevant.
110*fe6060f1SDimitry Andric   bool isLive(uint64_t off) const override { return live; }
111*fe6060f1SDimitry Andric   void markLive(uint64_t off) override { live = true; }
112*fe6060f1SDimitry Andric   bool isCoalescedWeak() const { return wasCoalesced && numRefs == 0; }
113*fe6060f1SDimitry Andric   bool shouldOmitFromOutput() const { return !live || isCoalescedWeak(); }
114*fe6060f1SDimitry Andric   bool isHashableForICF() const;
115*fe6060f1SDimitry Andric   void hashForICF();
116*fe6060f1SDimitry Andric   void writeTo(uint8_t *buf);
117*fe6060f1SDimitry Andric 
118*fe6060f1SDimitry Andric   void foldIdentical(ConcatInputSection *redundant);
119*fe6060f1SDimitry Andric   InputSection *canonical() override {
120*fe6060f1SDimitry Andric     return replacement ? replacement : this;
121*fe6060f1SDimitry Andric   }
122*fe6060f1SDimitry Andric 
123*fe6060f1SDimitry Andric   static bool classof(const InputSection *isec) {
124*fe6060f1SDimitry Andric     return isec->kind() == ConcatKind;
125*fe6060f1SDimitry Andric   }
126*fe6060f1SDimitry Andric 
127*fe6060f1SDimitry Andric   // Points to the surviving section after this one is folded by ICF
128*fe6060f1SDimitry Andric   InputSection *replacement = nullptr;
129*fe6060f1SDimitry Andric   // Equivalence-class ID for ICF
130*fe6060f1SDimitry Andric   uint64_t icfEqClass[2] = {0, 0};
131*fe6060f1SDimitry Andric 
132*fe6060f1SDimitry Andric   // With subsections_via_symbols, most symbols have their own InputSection,
133*fe6060f1SDimitry Andric   // and for weak symbols (e.g. from inline functions), only the
134*fe6060f1SDimitry Andric   // InputSection from one translation unit will make it to the output,
135*fe6060f1SDimitry Andric   // while all copies in other translation units are coalesced into the
136*fe6060f1SDimitry Andric   // first and not copied to the output.
137*fe6060f1SDimitry Andric   bool wasCoalesced = false;
138*fe6060f1SDimitry Andric   bool live = !config->deadStrip;
139*fe6060f1SDimitry Andric   // How many symbols refer to this InputSection.
140*fe6060f1SDimitry Andric   uint32_t numRefs = 0;
141*fe6060f1SDimitry Andric   // This variable has two usages. Initially, it represents the input order.
142*fe6060f1SDimitry Andric   // After assignAddresses is called, it represents the offset from the
143*fe6060f1SDimitry Andric   // beginning of the output section this section was assigned to.
144*fe6060f1SDimitry Andric   uint64_t outSecOff = 0;
145*fe6060f1SDimitry Andric };
146*fe6060f1SDimitry Andric 
147*fe6060f1SDimitry Andric // Verify ConcatInputSection's size on 64-bit builds.
148*fe6060f1SDimitry Andric static_assert(sizeof(int) != 8 || sizeof(ConcatInputSection) == 112,
149*fe6060f1SDimitry Andric               "Try to minimize ConcatInputSection's size, we create many "
150*fe6060f1SDimitry Andric               "instances of it");
151*fe6060f1SDimitry Andric 
152*fe6060f1SDimitry Andric // Helper functions to make it easy to sprinkle asserts.
153*fe6060f1SDimitry Andric 
154*fe6060f1SDimitry Andric inline bool shouldOmitFromOutput(InputSection *isec) {
155*fe6060f1SDimitry Andric   return isa<ConcatInputSection>(isec) &&
156*fe6060f1SDimitry Andric          cast<ConcatInputSection>(isec)->shouldOmitFromOutput();
157*fe6060f1SDimitry Andric }
158*fe6060f1SDimitry Andric 
159*fe6060f1SDimitry Andric inline bool isCoalescedWeak(InputSection *isec) {
160*fe6060f1SDimitry Andric   return isa<ConcatInputSection>(isec) &&
161*fe6060f1SDimitry Andric          cast<ConcatInputSection>(isec)->isCoalescedWeak();
162*fe6060f1SDimitry Andric }
163*fe6060f1SDimitry Andric 
164*fe6060f1SDimitry Andric // We allocate a lot of these and binary search on them, so they should be as
165*fe6060f1SDimitry Andric // compact as possible. Hence the use of 31 rather than 64 bits for the hash.
166*fe6060f1SDimitry Andric struct StringPiece {
167*fe6060f1SDimitry Andric   // Offset from the start of the containing input section.
168*fe6060f1SDimitry Andric   uint32_t inSecOff;
169*fe6060f1SDimitry Andric   uint32_t live : 1;
170*fe6060f1SDimitry Andric   // Only set if deduplicating literals
171*fe6060f1SDimitry Andric   uint32_t hash : 31;
172*fe6060f1SDimitry Andric   // Offset from the start of the containing output section.
173*fe6060f1SDimitry Andric   uint64_t outSecOff = 0;
174*fe6060f1SDimitry Andric 
175*fe6060f1SDimitry Andric   StringPiece(uint64_t off, uint32_t hash)
176*fe6060f1SDimitry Andric       : inSecOff(off), live(!config->deadStrip), hash(hash) {}
177*fe6060f1SDimitry Andric };
178*fe6060f1SDimitry Andric 
179*fe6060f1SDimitry Andric static_assert(sizeof(StringPiece) == 16, "StringPiece is too big!");
180*fe6060f1SDimitry Andric 
181*fe6060f1SDimitry Andric // CStringInputSections are composed of multiple null-terminated string
182*fe6060f1SDimitry Andric // literals, which we represent using StringPieces. These literals can be
183*fe6060f1SDimitry Andric // deduplicated and tail-merged, so translating offsets between the input and
184*fe6060f1SDimitry Andric // outputs sections is more complicated.
185*fe6060f1SDimitry Andric //
186*fe6060f1SDimitry Andric // NOTE: One significant difference between LLD and ld64 is that we merge all
187*fe6060f1SDimitry Andric // cstring literals, even those referenced directly by non-private symbols.
188*fe6060f1SDimitry Andric // ld64 is more conservative and does not do that. This was mostly done for
189*fe6060f1SDimitry Andric // implementation simplicity; if we find programs that need the more
190*fe6060f1SDimitry Andric // conservative behavior we can certainly implement that.
191*fe6060f1SDimitry Andric class CStringInputSection final : public InputSection {
192*fe6060f1SDimitry Andric public:
193*fe6060f1SDimitry Andric   CStringInputSection(StringRef segname, StringRef name, InputFile *file,
194*fe6060f1SDimitry Andric                       ArrayRef<uint8_t> data, uint32_t align, uint32_t flags)
195*fe6060f1SDimitry Andric       : InputSection(CStringLiteralKind, segname, name, file, data, align,
196*fe6060f1SDimitry Andric                      flags) {}
197*fe6060f1SDimitry Andric   uint64_t getOffset(uint64_t off) const override;
198*fe6060f1SDimitry Andric   bool isLive(uint64_t off) const override { return getStringPiece(off).live; }
199*fe6060f1SDimitry Andric   void markLive(uint64_t off) override { getStringPiece(off).live = true; }
200*fe6060f1SDimitry Andric   // Find the StringPiece that contains this offset.
201*fe6060f1SDimitry Andric   StringPiece &getStringPiece(uint64_t off);
202*fe6060f1SDimitry Andric   const StringPiece &getStringPiece(uint64_t off) const;
203*fe6060f1SDimitry Andric   // Split at each null byte.
204*fe6060f1SDimitry Andric   void splitIntoPieces();
205*fe6060f1SDimitry Andric 
206*fe6060f1SDimitry Andric   LLVM_ATTRIBUTE_ALWAYS_INLINE
207*fe6060f1SDimitry Andric   StringRef getStringRef(size_t i) const {
208*fe6060f1SDimitry Andric     size_t begin = pieces[i].inSecOff;
209*fe6060f1SDimitry Andric     size_t end =
210*fe6060f1SDimitry Andric         (pieces.size() - 1 == i) ? data.size() : pieces[i + 1].inSecOff;
211*fe6060f1SDimitry Andric     return toStringRef(data.slice(begin, end - begin));
212*fe6060f1SDimitry Andric   }
213*fe6060f1SDimitry Andric 
214*fe6060f1SDimitry Andric   // Returns i'th piece as a CachedHashStringRef. This function is very hot when
215*fe6060f1SDimitry Andric   // string merging is enabled, so we want to inline.
216*fe6060f1SDimitry Andric   LLVM_ATTRIBUTE_ALWAYS_INLINE
217*fe6060f1SDimitry Andric   llvm::CachedHashStringRef getCachedHashStringRef(size_t i) const {
218*fe6060f1SDimitry Andric     assert(config->dedupLiterals);
219*fe6060f1SDimitry Andric     return {getStringRef(i), pieces[i].hash};
220*fe6060f1SDimitry Andric   }
221*fe6060f1SDimitry Andric 
222*fe6060f1SDimitry Andric   static bool classof(const InputSection *isec) {
223*fe6060f1SDimitry Andric     return isec->kind() == CStringLiteralKind;
224*fe6060f1SDimitry Andric   }
225*fe6060f1SDimitry Andric 
226*fe6060f1SDimitry Andric   std::vector<StringPiece> pieces;
227*fe6060f1SDimitry Andric };
228*fe6060f1SDimitry Andric 
229*fe6060f1SDimitry Andric class WordLiteralInputSection final : public InputSection {
230*fe6060f1SDimitry Andric public:
231*fe6060f1SDimitry Andric   WordLiteralInputSection(StringRef segname, StringRef name, InputFile *file,
232*fe6060f1SDimitry Andric                           ArrayRef<uint8_t> data, uint32_t align,
233*fe6060f1SDimitry Andric                           uint32_t flags);
234*fe6060f1SDimitry Andric   uint64_t getOffset(uint64_t off) const override;
235*fe6060f1SDimitry Andric   bool isLive(uint64_t off) const override {
236*fe6060f1SDimitry Andric     return live[off >> power2LiteralSize];
237*fe6060f1SDimitry Andric   }
238*fe6060f1SDimitry Andric   void markLive(uint64_t off) override { live[off >> power2LiteralSize] = 1; }
239*fe6060f1SDimitry Andric 
240*fe6060f1SDimitry Andric   static bool classof(const InputSection *isec) {
241*fe6060f1SDimitry Andric     return isec->kind() == WordLiteralKind;
242*fe6060f1SDimitry Andric   }
243*fe6060f1SDimitry Andric 
244*fe6060f1SDimitry Andric private:
245*fe6060f1SDimitry Andric   unsigned power2LiteralSize;
246*fe6060f1SDimitry Andric   // The liveness of data[off] is tracked by live[off >> power2LiteralSize].
247*fe6060f1SDimitry Andric   llvm::BitVector live;
2485ffd83dbSDimitry Andric };
2495ffd83dbSDimitry Andric 
250e8d8bef9SDimitry Andric inline uint8_t sectionType(uint32_t flags) {
251e8d8bef9SDimitry Andric   return flags & llvm::MachO::SECTION_TYPE;
252e8d8bef9SDimitry Andric }
253e8d8bef9SDimitry Andric 
254e8d8bef9SDimitry Andric inline bool isZeroFill(uint32_t flags) {
255e8d8bef9SDimitry Andric   return llvm::MachO::isVirtualSection(sectionType(flags));
256e8d8bef9SDimitry Andric }
257e8d8bef9SDimitry Andric 
258e8d8bef9SDimitry Andric inline bool isThreadLocalVariables(uint32_t flags) {
259e8d8bef9SDimitry Andric   return sectionType(flags) == llvm::MachO::S_THREAD_LOCAL_VARIABLES;
260e8d8bef9SDimitry Andric }
261e8d8bef9SDimitry Andric 
262e8d8bef9SDimitry Andric // These sections contain the data for initializing thread-local variables.
263e8d8bef9SDimitry Andric inline bool isThreadLocalData(uint32_t flags) {
264e8d8bef9SDimitry Andric   return sectionType(flags) == llvm::MachO::S_THREAD_LOCAL_REGULAR ||
265e8d8bef9SDimitry Andric          sectionType(flags) == llvm::MachO::S_THREAD_LOCAL_ZEROFILL;
266e8d8bef9SDimitry Andric }
267e8d8bef9SDimitry Andric 
268e8d8bef9SDimitry Andric inline bool isDebugSection(uint32_t flags) {
269e8d8bef9SDimitry Andric   return (flags & llvm::MachO::SECTION_ATTRIBUTES_USR) ==
270e8d8bef9SDimitry Andric          llvm::MachO::S_ATTR_DEBUG;
271e8d8bef9SDimitry Andric }
272e8d8bef9SDimitry Andric 
273*fe6060f1SDimitry Andric inline bool isWordLiteralSection(uint32_t flags) {
274*fe6060f1SDimitry Andric   return sectionType(flags) == llvm::MachO::S_4BYTE_LITERALS ||
275*fe6060f1SDimitry Andric          sectionType(flags) == llvm::MachO::S_8BYTE_LITERALS ||
276*fe6060f1SDimitry Andric          sectionType(flags) == llvm::MachO::S_16BYTE_LITERALS;
277*fe6060f1SDimitry Andric }
278e8d8bef9SDimitry Andric 
279*fe6060f1SDimitry Andric bool isCodeSection(const InputSection *);
280*fe6060f1SDimitry Andric 
281*fe6060f1SDimitry Andric bool isCfStringSection(const InputSection *);
282*fe6060f1SDimitry Andric 
283*fe6060f1SDimitry Andric extern std::vector<ConcatInputSection *> inputSections;
284*fe6060f1SDimitry Andric 
285*fe6060f1SDimitry Andric namespace section_names {
286*fe6060f1SDimitry Andric 
287*fe6060f1SDimitry Andric constexpr const char authGot[] = "__auth_got";
288*fe6060f1SDimitry Andric constexpr const char authPtr[] = "__auth_ptr";
289*fe6060f1SDimitry Andric constexpr const char binding[] = "__binding";
290*fe6060f1SDimitry Andric constexpr const char bitcodeBundle[] = "__bundle";
291*fe6060f1SDimitry Andric constexpr const char cString[] = "__cstring";
292*fe6060f1SDimitry Andric constexpr const char cfString[] = "__cfstring";
293*fe6060f1SDimitry Andric constexpr const char codeSignature[] = "__code_signature";
294*fe6060f1SDimitry Andric constexpr const char common[] = "__common";
295*fe6060f1SDimitry Andric constexpr const char compactUnwind[] = "__compact_unwind";
296*fe6060f1SDimitry Andric constexpr const char data[] = "__data";
297*fe6060f1SDimitry Andric constexpr const char debugAbbrev[] = "__debug_abbrev";
298*fe6060f1SDimitry Andric constexpr const char debugInfo[] = "__debug_info";
299*fe6060f1SDimitry Andric constexpr const char debugStr[] = "__debug_str";
300*fe6060f1SDimitry Andric constexpr const char ehFrame[] = "__eh_frame";
301*fe6060f1SDimitry Andric constexpr const char export_[] = "__export";
302*fe6060f1SDimitry Andric constexpr const char dataInCode[] = "__data_in_code";
303*fe6060f1SDimitry Andric constexpr const char functionStarts[] = "__func_starts";
304*fe6060f1SDimitry Andric constexpr const char got[] = "__got";
305*fe6060f1SDimitry Andric constexpr const char header[] = "__mach_header";
306*fe6060f1SDimitry Andric constexpr const char indirectSymbolTable[] = "__ind_sym_tab";
307*fe6060f1SDimitry Andric constexpr const char const_[] = "__const";
308*fe6060f1SDimitry Andric constexpr const char lazySymbolPtr[] = "__la_symbol_ptr";
309*fe6060f1SDimitry Andric constexpr const char lazyBinding[] = "__lazy_binding";
310*fe6060f1SDimitry Andric constexpr const char literals[] = "__literals";
311*fe6060f1SDimitry Andric constexpr const char moduleInitFunc[] = "__mod_init_func";
312*fe6060f1SDimitry Andric constexpr const char moduleTermFunc[] = "__mod_term_func";
313*fe6060f1SDimitry Andric constexpr const char nonLazySymbolPtr[] = "__nl_symbol_ptr";
314*fe6060f1SDimitry Andric constexpr const char objcCatList[] = "__objc_catlist";
315*fe6060f1SDimitry Andric constexpr const char objcClassList[] = "__objc_classlist";
316*fe6060f1SDimitry Andric constexpr const char objcConst[] = "__objc_const";
317*fe6060f1SDimitry Andric constexpr const char objcImageInfo[] = "__objc_imageinfo";
318*fe6060f1SDimitry Andric constexpr const char objcNonLazyCatList[] = "__objc_nlcatlist";
319*fe6060f1SDimitry Andric constexpr const char objcNonLazyClassList[] = "__objc_nlclslist";
320*fe6060f1SDimitry Andric constexpr const char objcProtoList[] = "__objc_protolist";
321*fe6060f1SDimitry Andric constexpr const char pageZero[] = "__pagezero";
322*fe6060f1SDimitry Andric constexpr const char pointers[] = "__pointers";
323*fe6060f1SDimitry Andric constexpr const char rebase[] = "__rebase";
324*fe6060f1SDimitry Andric constexpr const char staticInit[] = "__StaticInit";
325*fe6060f1SDimitry Andric constexpr const char stringTable[] = "__string_table";
326*fe6060f1SDimitry Andric constexpr const char stubHelper[] = "__stub_helper";
327*fe6060f1SDimitry Andric constexpr const char stubs[] = "__stubs";
328*fe6060f1SDimitry Andric constexpr const char swift[] = "__swift";
329*fe6060f1SDimitry Andric constexpr const char symbolTable[] = "__symbol_table";
330*fe6060f1SDimitry Andric constexpr const char textCoalNt[] = "__textcoal_nt";
331*fe6060f1SDimitry Andric constexpr const char text[] = "__text";
332*fe6060f1SDimitry Andric constexpr const char threadPtrs[] = "__thread_ptrs";
333*fe6060f1SDimitry Andric constexpr const char threadVars[] = "__thread_vars";
334*fe6060f1SDimitry Andric constexpr const char unwindInfo[] = "__unwind_info";
335*fe6060f1SDimitry Andric constexpr const char weakBinding[] = "__weak_binding";
336*fe6060f1SDimitry Andric constexpr const char zeroFill[] = "__zerofill";
337*fe6060f1SDimitry Andric 
338*fe6060f1SDimitry Andric } // namespace section_names
3395ffd83dbSDimitry Andric 
3405ffd83dbSDimitry Andric } // namespace macho
341e8d8bef9SDimitry Andric 
342e8d8bef9SDimitry Andric std::string toString(const macho::InputSection *);
343e8d8bef9SDimitry Andric 
3445ffd83dbSDimitry Andric } // namespace lld
3455ffd83dbSDimitry Andric 
3465ffd83dbSDimitry Andric #endif
347