xref: /freebsd/contrib/llvm-project/lld/MachO/InputSection.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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 
12fe6060f1SDimitry Andric #include "Config.h"
13fe6060f1SDimitry Andric #include "Relocations.h"
14349cc55cSDimitry Andric #include "Symbols.h"
15fe6060f1SDimitry Andric 
165ffd83dbSDimitry Andric #include "lld/Common/LLVM.h"
17fe6060f1SDimitry Andric #include "lld/Common/Memory.h"
185ffd83dbSDimitry Andric #include "llvm/ADT/ArrayRef.h"
19fe6060f1SDimitry Andric #include "llvm/ADT/BitVector.h"
20fe6060f1SDimitry Andric #include "llvm/ADT/CachedHashString.h"
21349cc55cSDimitry Andric #include "llvm/ADT/TinyPtrVector.h"
225ffd83dbSDimitry Andric #include "llvm/BinaryFormat/MachO.h"
235ffd83dbSDimitry Andric 
245ffd83dbSDimitry Andric namespace lld {
255ffd83dbSDimitry Andric namespace macho {
265ffd83dbSDimitry Andric 
275ffd83dbSDimitry Andric class InputFile;
285ffd83dbSDimitry Andric class OutputSection;
295ffd83dbSDimitry Andric 
305ffd83dbSDimitry Andric class InputSection {
315ffd83dbSDimitry Andric public:
3281ad6265SDimitry Andric   enum Kind : uint8_t {
33fe6060f1SDimitry Andric     ConcatKind,
34fe6060f1SDimitry Andric     CStringLiteralKind,
35fe6060f1SDimitry Andric     WordLiteralKind,
36fe6060f1SDimitry Andric   };
37fe6060f1SDimitry Andric 
kind()3881ad6265SDimitry Andric   Kind kind() const { return sectionKind; }
395ffd83dbSDimitry Andric   virtual ~InputSection() = default;
getSize()405ffd83dbSDimitry Andric   virtual uint64_t getSize() const { return data.size(); }
empty()41349cc55cSDimitry Andric   virtual bool empty() const { return data.empty(); }
getFile()4281ad6265SDimitry Andric   InputFile *getFile() const { return section.file; }
getName()4381ad6265SDimitry Andric   StringRef getName() const { return section.name; }
getSegName()4481ad6265SDimitry Andric   StringRef getSegName() const { return section.segname; }
getFlags()4581ad6265SDimitry Andric   uint32_t getFlags() const { return section.flags; }
46fe6060f1SDimitry Andric   uint64_t getFileSize() const;
47fe6060f1SDimitry Andric   // Translates \p off -- an offset relative to this InputSection -- into an
48fe6060f1SDimitry Andric   // offset from the beginning of its parent OutputSection.
49fe6060f1SDimitry Andric   virtual uint64_t getOffset(uint64_t off) const = 0;
50fe6060f1SDimitry Andric   // The offset from the beginning of the file.
51fe6060f1SDimitry Andric   uint64_t getVA(uint64_t off) const;
5281ad6265SDimitry Andric   // Return a user-friendly string for use in diagnostics.
5381ad6265SDimitry Andric   // Format: /path/to/object.o:(symbol _func+0x123)
5481ad6265SDimitry Andric   std::string getLocation(uint64_t off) const;
5581ad6265SDimitry Andric   // Return the source line corresponding to an address, or the empty string.
5681ad6265SDimitry Andric   // Format: Source.cpp:123 (/path/to/Source.cpp:123)
5781ad6265SDimitry Andric   std::string getSourceLocation(uint64_t off) const;
5806c3fb27SDimitry Andric   // Return the relocation at \p off, if it exists. This does a linear search.
5906c3fb27SDimitry Andric   const Reloc *getRelocAt(uint32_t off) const;
60fe6060f1SDimitry Andric   // Whether the data at \p off in this InputSection is live.
61fe6060f1SDimitry Andric   virtual bool isLive(uint64_t off) const = 0;
62fe6060f1SDimitry Andric   virtual void markLive(uint64_t off) = 0;
canonical()63fe6060f1SDimitry Andric   virtual InputSection *canonical() { return this; }
canonical()6404eeddc0SDimitry Andric   virtual const InputSection *canonical() const { return this; }
655ffd83dbSDimitry Andric 
6681ad6265SDimitry Andric protected:
InputSection(Kind kind,const Section & section,ArrayRef<uint8_t> data,uint32_t align)6781ad6265SDimitry Andric   InputSection(Kind kind, const Section &section, ArrayRef<uint8_t> data,
6881ad6265SDimitry Andric                uint32_t align)
69bdd1243dSDimitry Andric       : sectionKind(kind), keepUnique(false), hasAltEntry(false), align(align),
70bdd1243dSDimitry Andric         data(data), section(section) {}
715ffd83dbSDimitry Andric 
InputSection(const InputSection & rhs)7281ad6265SDimitry Andric   InputSection(const InputSection &rhs)
73bdd1243dSDimitry Andric       : sectionKind(rhs.sectionKind), keepUnique(false), hasAltEntry(false),
74bdd1243dSDimitry Andric         align(rhs.align), data(rhs.data), section(rhs.section) {}
7581ad6265SDimitry Andric 
7681ad6265SDimitry Andric   Kind sectionKind;
7781ad6265SDimitry Andric 
7881ad6265SDimitry Andric public:
79fe6060f1SDimitry Andric   // is address assigned?
800eae32dcSDimitry Andric   bool isFinal = false;
8181ad6265SDimitry Andric   // keep the address of the symbol(s) in this section unique in the final
8281ad6265SDimitry Andric   // binary ?
83bdd1243dSDimitry Andric   bool keepUnique : 1;
84bdd1243dSDimitry Andric   // Does this section have symbols at offsets other than zero? (NOTE: only
85bdd1243dSDimitry Andric   // applies to ConcatInputSections.)
86bdd1243dSDimitry Andric   bool hasAltEntry : 1;
8781ad6265SDimitry Andric   uint32_t align = 1;
885ffd83dbSDimitry Andric 
8981ad6265SDimitry Andric   OutputSection *parent = nullptr;
905ffd83dbSDimitry Andric   ArrayRef<uint8_t> data;
915ffd83dbSDimitry Andric   std::vector<Reloc> relocs;
92349cc55cSDimitry Andric   // The symbols that belong to this InputSection, sorted by value. With
93349cc55cSDimitry Andric   // .subsections_via_symbols, there is typically only one element here.
94349cc55cSDimitry Andric   llvm::TinyPtrVector<Defined *> symbols;
95fe6060f1SDimitry Andric 
9681ad6265SDimitry Andric   const Section &section;
97fe6060f1SDimitry Andric 
98*0fca6ea1SDimitry Andric protected:
9981ad6265SDimitry Andric   const Defined *getContainingSymbol(uint64_t off) const;
100fe6060f1SDimitry Andric };
101fe6060f1SDimitry Andric 
102fe6060f1SDimitry Andric // ConcatInputSections are combined into (Concat)OutputSections through simple
103fe6060f1SDimitry Andric // concatenation, in contrast with literal sections which may have their
104fe6060f1SDimitry Andric // contents merged before output.
105fe6060f1SDimitry Andric class ConcatInputSection final : public InputSection {
106fe6060f1SDimitry Andric public:
10781ad6265SDimitry Andric   ConcatInputSection(const Section &section, ArrayRef<uint8_t> data,
10881ad6265SDimitry Andric                      uint32_t align = 1)
InputSection(ConcatKind,section,data,align)10981ad6265SDimitry Andric       : InputSection(ConcatKind, section, data, align) {}
110349cc55cSDimitry Andric 
getOffset(uint64_t off)111fe6060f1SDimitry Andric   uint64_t getOffset(uint64_t off) const override { return outSecOff + off; }
getVA()112fe6060f1SDimitry Andric   uint64_t getVA() const { return InputSection::getVA(0); }
113fe6060f1SDimitry Andric   // ConcatInputSections are entirely live or dead, so the offset is irrelevant.
isLive(uint64_t off)114fe6060f1SDimitry Andric   bool isLive(uint64_t off) const override { return live; }
markLive(uint64_t off)115fe6060f1SDimitry Andric   void markLive(uint64_t off) override { live = true; }
isCoalescedWeak()116349cc55cSDimitry Andric   bool isCoalescedWeak() const { return wasCoalesced && symbols.empty(); }
shouldOmitFromOutput()117fe6060f1SDimitry Andric   bool shouldOmitFromOutput() const { return !live || isCoalescedWeak(); }
118fe6060f1SDimitry Andric   void writeTo(uint8_t *buf);
119fe6060f1SDimitry Andric 
120fe6060f1SDimitry Andric   void foldIdentical(ConcatInputSection *redundant);
canonical()121349cc55cSDimitry Andric   ConcatInputSection *canonical() override {
122fe6060f1SDimitry Andric     return replacement ? replacement : this;
123fe6060f1SDimitry Andric   }
canonical()12404eeddc0SDimitry Andric   const InputSection *canonical() const override {
12504eeddc0SDimitry Andric     return replacement ? replacement : this;
12604eeddc0SDimitry Andric   }
127fe6060f1SDimitry Andric 
classof(const InputSection * isec)128fe6060f1SDimitry Andric   static bool classof(const InputSection *isec) {
129fe6060f1SDimitry Andric     return isec->kind() == ConcatKind;
130fe6060f1SDimitry Andric   }
131fe6060f1SDimitry Andric 
132fe6060f1SDimitry Andric   // Points to the surviving section after this one is folded by ICF
133349cc55cSDimitry Andric   ConcatInputSection *replacement = nullptr;
134fe6060f1SDimitry Andric   // Equivalence-class ID for ICF
13581ad6265SDimitry Andric   uint32_t icfEqClass[2] = {0, 0};
136fe6060f1SDimitry Andric 
137fe6060f1SDimitry Andric   // With subsections_via_symbols, most symbols have their own InputSection,
138fe6060f1SDimitry Andric   // and for weak symbols (e.g. from inline functions), only the
139fe6060f1SDimitry Andric   // InputSection from one translation unit will make it to the output,
140fe6060f1SDimitry Andric   // while all copies in other translation units are coalesced into the
141fe6060f1SDimitry Andric   // first and not copied to the output.
142fe6060f1SDimitry Andric   bool wasCoalesced = false;
143fe6060f1SDimitry Andric   bool live = !config->deadStrip;
1440eae32dcSDimitry Andric   bool hasCallSites = false;
145fe6060f1SDimitry Andric   // This variable has two usages. Initially, it represents the input order.
146fe6060f1SDimitry Andric   // After assignAddresses is called, it represents the offset from the
147fe6060f1SDimitry Andric   // beginning of the output section this section was assigned to.
148fe6060f1SDimitry Andric   uint64_t outSecOff = 0;
149fe6060f1SDimitry Andric };
150fe6060f1SDimitry Andric 
15181ad6265SDimitry Andric // Initialize a fake InputSection that does not belong to any InputFile.
152*0fca6ea1SDimitry Andric // The created ConcatInputSection will always have 'live=true'
15381ad6265SDimitry Andric ConcatInputSection *makeSyntheticInputSection(StringRef segName,
15481ad6265SDimitry Andric                                               StringRef sectName,
15581ad6265SDimitry Andric                                               uint32_t flags = 0,
15681ad6265SDimitry Andric                                               ArrayRef<uint8_t> data = {},
15781ad6265SDimitry Andric                                               uint32_t align = 1);
15881ad6265SDimitry Andric 
159fe6060f1SDimitry Andric // Helper functions to make it easy to sprinkle asserts.
160fe6060f1SDimitry Andric 
shouldOmitFromOutput(InputSection * isec)161fe6060f1SDimitry Andric inline bool shouldOmitFromOutput(InputSection *isec) {
162fe6060f1SDimitry Andric   return isa<ConcatInputSection>(isec) &&
163fe6060f1SDimitry Andric          cast<ConcatInputSection>(isec)->shouldOmitFromOutput();
164fe6060f1SDimitry Andric }
165fe6060f1SDimitry Andric 
isCoalescedWeak(InputSection * isec)166fe6060f1SDimitry Andric inline bool isCoalescedWeak(InputSection *isec) {
167fe6060f1SDimitry Andric   return isa<ConcatInputSection>(isec) &&
168fe6060f1SDimitry Andric          cast<ConcatInputSection>(isec)->isCoalescedWeak();
169fe6060f1SDimitry Andric }
170fe6060f1SDimitry Andric 
171fe6060f1SDimitry Andric // We allocate a lot of these and binary search on them, so they should be as
172fe6060f1SDimitry Andric // compact as possible. Hence the use of 31 rather than 64 bits for the hash.
173fe6060f1SDimitry Andric struct StringPiece {
174fe6060f1SDimitry Andric   // Offset from the start of the containing input section.
175fe6060f1SDimitry Andric   uint32_t inSecOff;
176fe6060f1SDimitry Andric   uint32_t live : 1;
177fe6060f1SDimitry Andric   // Only set if deduplicating literals
178fe6060f1SDimitry Andric   uint32_t hash : 31;
179fe6060f1SDimitry Andric   // Offset from the start of the containing output section.
180fe6060f1SDimitry Andric   uint64_t outSecOff = 0;
181fe6060f1SDimitry Andric 
StringPieceStringPiece182fe6060f1SDimitry Andric   StringPiece(uint64_t off, uint32_t hash)
183fe6060f1SDimitry Andric       : inSecOff(off), live(!config->deadStrip), hash(hash) {}
184fe6060f1SDimitry Andric };
185fe6060f1SDimitry Andric 
186fe6060f1SDimitry Andric static_assert(sizeof(StringPiece) == 16, "StringPiece is too big!");
187fe6060f1SDimitry Andric 
188fe6060f1SDimitry Andric // CStringInputSections are composed of multiple null-terminated string
189fe6060f1SDimitry Andric // literals, which we represent using StringPieces. These literals can be
190fe6060f1SDimitry Andric // deduplicated and tail-merged, so translating offsets between the input and
191fe6060f1SDimitry Andric // outputs sections is more complicated.
192fe6060f1SDimitry Andric //
193fe6060f1SDimitry Andric // NOTE: One significant difference between LLD and ld64 is that we merge all
194fe6060f1SDimitry Andric // cstring literals, even those referenced directly by non-private symbols.
195fe6060f1SDimitry Andric // ld64 is more conservative and does not do that. This was mostly done for
196fe6060f1SDimitry Andric // implementation simplicity; if we find programs that need the more
197fe6060f1SDimitry Andric // conservative behavior we can certainly implement that.
198fe6060f1SDimitry Andric class CStringInputSection final : public InputSection {
199fe6060f1SDimitry Andric public:
CStringInputSection(const Section & section,ArrayRef<uint8_t> data,uint32_t align,bool dedupLiterals)20081ad6265SDimitry Andric   CStringInputSection(const Section &section, ArrayRef<uint8_t> data,
201bdd1243dSDimitry Andric                       uint32_t align, bool dedupLiterals)
202bdd1243dSDimitry Andric       : InputSection(CStringLiteralKind, section, data, align),
203bdd1243dSDimitry Andric         deduplicateLiterals(dedupLiterals) {}
204bdd1243dSDimitry Andric 
205fe6060f1SDimitry Andric   uint64_t getOffset(uint64_t off) const override;
isLive(uint64_t off)206fe6060f1SDimitry Andric   bool isLive(uint64_t off) const override { return getStringPiece(off).live; }
markLive(uint64_t off)207fe6060f1SDimitry Andric   void markLive(uint64_t off) override { getStringPiece(off).live = true; }
208fe6060f1SDimitry Andric   // Find the StringPiece that contains this offset.
209fe6060f1SDimitry Andric   StringPiece &getStringPiece(uint64_t off);
210fe6060f1SDimitry Andric   const StringPiece &getStringPiece(uint64_t off) const;
211fe6060f1SDimitry Andric   // Split at each null byte.
212fe6060f1SDimitry Andric   void splitIntoPieces();
213fe6060f1SDimitry Andric 
214fe6060f1SDimitry Andric   LLVM_ATTRIBUTE_ALWAYS_INLINE
getStringRef(size_t i)215fe6060f1SDimitry Andric   StringRef getStringRef(size_t i) const {
216fe6060f1SDimitry Andric     size_t begin = pieces[i].inSecOff;
217bdd1243dSDimitry Andric     // The endpoint should be *at* the null terminator, not after. This matches
218bdd1243dSDimitry Andric     // the behavior of StringRef(const char *Str).
219fe6060f1SDimitry Andric     size_t end =
220bdd1243dSDimitry Andric         ((pieces.size() - 1 == i) ? data.size() : pieces[i + 1].inSecOff) - 1;
221fe6060f1SDimitry Andric     return toStringRef(data.slice(begin, end - begin));
222fe6060f1SDimitry Andric   }
223fe6060f1SDimitry Andric 
getStringRefAtOffset(uint64_t off)22406c3fb27SDimitry Andric   StringRef getStringRefAtOffset(uint64_t off) const {
22506c3fb27SDimitry Andric     return getStringRef(getStringPieceIndex(off));
22606c3fb27SDimitry Andric   }
22706c3fb27SDimitry Andric 
228fe6060f1SDimitry Andric   // Returns i'th piece as a CachedHashStringRef. This function is very hot when
229fe6060f1SDimitry Andric   // string merging is enabled, so we want to inline.
230fe6060f1SDimitry Andric   LLVM_ATTRIBUTE_ALWAYS_INLINE
getCachedHashStringRef(size_t i)231fe6060f1SDimitry Andric   llvm::CachedHashStringRef getCachedHashStringRef(size_t i) const {
232bdd1243dSDimitry Andric     assert(deduplicateLiterals);
233fe6060f1SDimitry Andric     return {getStringRef(i), pieces[i].hash};
234fe6060f1SDimitry Andric   }
235fe6060f1SDimitry Andric 
classof(const InputSection * isec)236fe6060f1SDimitry Andric   static bool classof(const InputSection *isec) {
237fe6060f1SDimitry Andric     return isec->kind() == CStringLiteralKind;
238fe6060f1SDimitry Andric   }
239fe6060f1SDimitry Andric 
240bdd1243dSDimitry Andric   bool deduplicateLiterals = false;
241fe6060f1SDimitry Andric   std::vector<StringPiece> pieces;
24206c3fb27SDimitry Andric 
24306c3fb27SDimitry Andric private:
24406c3fb27SDimitry Andric   size_t getStringPieceIndex(uint64_t off) const;
245fe6060f1SDimitry Andric };
246fe6060f1SDimitry Andric 
247fe6060f1SDimitry Andric class WordLiteralInputSection final : public InputSection {
248fe6060f1SDimitry Andric public:
24981ad6265SDimitry Andric   WordLiteralInputSection(const Section &section, ArrayRef<uint8_t> data,
25081ad6265SDimitry Andric                           uint32_t align);
251fe6060f1SDimitry Andric   uint64_t getOffset(uint64_t off) const override;
isLive(uint64_t off)252fe6060f1SDimitry Andric   bool isLive(uint64_t off) const override {
253fe6060f1SDimitry Andric     return live[off >> power2LiteralSize];
254fe6060f1SDimitry Andric   }
markLive(uint64_t off)25504eeddc0SDimitry Andric   void markLive(uint64_t off) override {
25604eeddc0SDimitry Andric     live[off >> power2LiteralSize] = true;
25704eeddc0SDimitry Andric   }
258fe6060f1SDimitry Andric 
classof(const InputSection * isec)259fe6060f1SDimitry Andric   static bool classof(const InputSection *isec) {
260fe6060f1SDimitry Andric     return isec->kind() == WordLiteralKind;
261fe6060f1SDimitry Andric   }
262fe6060f1SDimitry Andric 
263fe6060f1SDimitry Andric private:
264fe6060f1SDimitry Andric   unsigned power2LiteralSize;
265fe6060f1SDimitry Andric   // The liveness of data[off] is tracked by live[off >> power2LiteralSize].
266fe6060f1SDimitry Andric   llvm::BitVector live;
2675ffd83dbSDimitry Andric };
2685ffd83dbSDimitry Andric 
sectionType(uint32_t flags)269e8d8bef9SDimitry Andric inline uint8_t sectionType(uint32_t flags) {
270e8d8bef9SDimitry Andric   return flags & llvm::MachO::SECTION_TYPE;
271e8d8bef9SDimitry Andric }
272e8d8bef9SDimitry Andric 
isZeroFill(uint32_t flags)273e8d8bef9SDimitry Andric inline bool isZeroFill(uint32_t flags) {
274e8d8bef9SDimitry Andric   return llvm::MachO::isVirtualSection(sectionType(flags));
275e8d8bef9SDimitry Andric }
276e8d8bef9SDimitry Andric 
isThreadLocalVariables(uint32_t flags)277e8d8bef9SDimitry Andric inline bool isThreadLocalVariables(uint32_t flags) {
278e8d8bef9SDimitry Andric   return sectionType(flags) == llvm::MachO::S_THREAD_LOCAL_VARIABLES;
279e8d8bef9SDimitry Andric }
280e8d8bef9SDimitry Andric 
281e8d8bef9SDimitry Andric // These sections contain the data for initializing thread-local variables.
isThreadLocalData(uint32_t flags)282e8d8bef9SDimitry Andric inline bool isThreadLocalData(uint32_t flags) {
283e8d8bef9SDimitry Andric   return sectionType(flags) == llvm::MachO::S_THREAD_LOCAL_REGULAR ||
284e8d8bef9SDimitry Andric          sectionType(flags) == llvm::MachO::S_THREAD_LOCAL_ZEROFILL;
285e8d8bef9SDimitry Andric }
286e8d8bef9SDimitry Andric 
isDebugSection(uint32_t flags)287e8d8bef9SDimitry Andric inline bool isDebugSection(uint32_t flags) {
288e8d8bef9SDimitry Andric   return (flags & llvm::MachO::SECTION_ATTRIBUTES_USR) ==
289e8d8bef9SDimitry Andric          llvm::MachO::S_ATTR_DEBUG;
290e8d8bef9SDimitry Andric }
291e8d8bef9SDimitry Andric 
isWordLiteralSection(uint32_t flags)292fe6060f1SDimitry Andric inline bool isWordLiteralSection(uint32_t flags) {
293fe6060f1SDimitry Andric   return sectionType(flags) == llvm::MachO::S_4BYTE_LITERALS ||
294fe6060f1SDimitry Andric          sectionType(flags) == llvm::MachO::S_8BYTE_LITERALS ||
295fe6060f1SDimitry Andric          sectionType(flags) == llvm::MachO::S_16BYTE_LITERALS;
296fe6060f1SDimitry Andric }
297e8d8bef9SDimitry Andric 
298fe6060f1SDimitry Andric bool isCodeSection(const InputSection *);
299fe6060f1SDimitry Andric bool isCfStringSection(const InputSection *);
30081ad6265SDimitry Andric bool isClassRefsSection(const InputSection *);
301bdd1243dSDimitry Andric bool isSelRefsSection(const InputSection *);
30281ad6265SDimitry Andric bool isEhFrameSection(const InputSection *);
303fcaf7f86SDimitry Andric bool isGccExceptTabSection(const InputSection *);
304fe6060f1SDimitry Andric 
305fe6060f1SDimitry Andric extern std::vector<ConcatInputSection *> inputSections;
306*0fca6ea1SDimitry Andric // This is used as a counter for specyfing input order for input sections
307*0fca6ea1SDimitry Andric extern int inputSectionsOrder;
308fe6060f1SDimitry Andric 
309fe6060f1SDimitry Andric namespace section_names {
310fe6060f1SDimitry Andric 
311fe6060f1SDimitry Andric constexpr const char authGot[] = "__auth_got";
312fe6060f1SDimitry Andric constexpr const char authPtr[] = "__auth_ptr";
313fe6060f1SDimitry Andric constexpr const char binding[] = "__binding";
314fe6060f1SDimitry Andric constexpr const char bitcodeBundle[] = "__bundle";
315fe6060f1SDimitry Andric constexpr const char cString[] = "__cstring";
316fe6060f1SDimitry Andric constexpr const char cfString[] = "__cfstring";
31781ad6265SDimitry Andric constexpr const char cgProfile[] = "__cg_profile";
318bdd1243dSDimitry Andric constexpr const char chainFixups[] = "__chainfixups";
319fe6060f1SDimitry Andric constexpr const char codeSignature[] = "__code_signature";
320fe6060f1SDimitry Andric constexpr const char common[] = "__common";
321fe6060f1SDimitry Andric constexpr const char compactUnwind[] = "__compact_unwind";
322fe6060f1SDimitry Andric constexpr const char data[] = "__data";
323fe6060f1SDimitry Andric constexpr const char debugAbbrev[] = "__debug_abbrev";
324fe6060f1SDimitry Andric constexpr const char debugInfo[] = "__debug_info";
32581ad6265SDimitry Andric constexpr const char debugLine[] = "__debug_line";
326fe6060f1SDimitry Andric constexpr const char debugStr[] = "__debug_str";
327bdd1243dSDimitry Andric constexpr const char debugStrOffs[] = "__debug_str_offs";
328fe6060f1SDimitry Andric constexpr const char ehFrame[] = "__eh_frame";
329349cc55cSDimitry Andric constexpr const char gccExceptTab[] = "__gcc_except_tab";
330fe6060f1SDimitry Andric constexpr const char export_[] = "__export";
331fe6060f1SDimitry Andric constexpr const char dataInCode[] = "__data_in_code";
332fe6060f1SDimitry Andric constexpr const char functionStarts[] = "__func_starts";
333fe6060f1SDimitry Andric constexpr const char got[] = "__got";
334fe6060f1SDimitry Andric constexpr const char header[] = "__mach_header";
335fe6060f1SDimitry Andric constexpr const char indirectSymbolTable[] = "__ind_sym_tab";
336bdd1243dSDimitry Andric constexpr const char initOffsets[] = "__init_offsets";
337fe6060f1SDimitry Andric constexpr const char const_[] = "__const";
338fe6060f1SDimitry Andric constexpr const char lazySymbolPtr[] = "__la_symbol_ptr";
339fe6060f1SDimitry Andric constexpr const char lazyBinding[] = "__lazy_binding";
340fe6060f1SDimitry Andric constexpr const char literals[] = "__literals";
341fe6060f1SDimitry Andric constexpr const char moduleInitFunc[] = "__mod_init_func";
342fe6060f1SDimitry Andric constexpr const char moduleTermFunc[] = "__mod_term_func";
343fe6060f1SDimitry Andric constexpr const char nonLazySymbolPtr[] = "__nl_symbol_ptr";
344fe6060f1SDimitry Andric constexpr const char objcCatList[] = "__objc_catlist";
345fe6060f1SDimitry Andric constexpr const char objcClassList[] = "__objc_classlist";
346*0fca6ea1SDimitry Andric constexpr const char objcMethList[] = "__objc_methlist";
34781ad6265SDimitry Andric constexpr const char objcClassRefs[] = "__objc_classrefs";
348fe6060f1SDimitry Andric constexpr const char objcConst[] = "__objc_const";
349fcaf7f86SDimitry Andric constexpr const char objCImageInfo[] = "__objc_imageinfo";
350bdd1243dSDimitry Andric constexpr const char objcStubs[] = "__objc_stubs";
351bdd1243dSDimitry Andric constexpr const char objcSelrefs[] = "__objc_selrefs";
352bdd1243dSDimitry Andric constexpr const char objcMethname[] = "__objc_methname";
353fe6060f1SDimitry Andric constexpr const char objcNonLazyCatList[] = "__objc_nlcatlist";
354fe6060f1SDimitry Andric constexpr const char objcNonLazyClassList[] = "__objc_nlclslist";
355fe6060f1SDimitry Andric constexpr const char objcProtoList[] = "__objc_protolist";
356fe6060f1SDimitry Andric constexpr const char pageZero[] = "__pagezero";
357fe6060f1SDimitry Andric constexpr const char pointers[] = "__pointers";
358fe6060f1SDimitry Andric constexpr const char rebase[] = "__rebase";
359fe6060f1SDimitry Andric constexpr const char staticInit[] = "__StaticInit";
360fe6060f1SDimitry Andric constexpr const char stringTable[] = "__string_table";
361fe6060f1SDimitry Andric constexpr const char stubHelper[] = "__stub_helper";
362fe6060f1SDimitry Andric constexpr const char stubs[] = "__stubs";
363fe6060f1SDimitry Andric constexpr const char swift[] = "__swift";
364fe6060f1SDimitry Andric constexpr const char symbolTable[] = "__symbol_table";
365fe6060f1SDimitry Andric constexpr const char textCoalNt[] = "__textcoal_nt";
366fe6060f1SDimitry Andric constexpr const char text[] = "__text";
367fe6060f1SDimitry Andric constexpr const char threadPtrs[] = "__thread_ptrs";
368fe6060f1SDimitry Andric constexpr const char threadVars[] = "__thread_vars";
369fe6060f1SDimitry Andric constexpr const char unwindInfo[] = "__unwind_info";
370fe6060f1SDimitry Andric constexpr const char weakBinding[] = "__weak_binding";
371fe6060f1SDimitry Andric constexpr const char zeroFill[] = "__zerofill";
37281ad6265SDimitry Andric constexpr const char addrSig[] = "__llvm_addrsig";
373fe6060f1SDimitry Andric 
374fe6060f1SDimitry Andric } // namespace section_names
3755ffd83dbSDimitry Andric 
376*0fca6ea1SDimitry Andric void addInputSection(InputSection *inputSection);
3775ffd83dbSDimitry Andric } // namespace macho
378e8d8bef9SDimitry Andric 
379e8d8bef9SDimitry Andric std::string toString(const macho::InputSection *);
380e8d8bef9SDimitry Andric 
3815ffd83dbSDimitry Andric } // namespace lld
3825ffd83dbSDimitry Andric 
3835ffd83dbSDimitry Andric #endif
384