1bb684c34Spatrick //===- InputSection.h -------------------------------------------*- C++ -*-===//
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 #ifndef LLD_MACHO_INPUT_SECTION_H
10bb684c34Spatrick #define LLD_MACHO_INPUT_SECTION_H
11bb684c34Spatrick
121cf9926bSpatrick #include "Config.h"
131cf9926bSpatrick #include "Relocations.h"
14*dfe94b16Srobert #include "Symbols.h"
151cf9926bSpatrick
16bb684c34Spatrick #include "lld/Common/LLVM.h"
171cf9926bSpatrick #include "lld/Common/Memory.h"
18bb684c34Spatrick #include "llvm/ADT/ArrayRef.h"
191cf9926bSpatrick #include "llvm/ADT/BitVector.h"
201cf9926bSpatrick #include "llvm/ADT/CachedHashString.h"
21*dfe94b16Srobert #include "llvm/ADT/TinyPtrVector.h"
22bb684c34Spatrick #include "llvm/BinaryFormat/MachO.h"
23bb684c34Spatrick
24bb684c34Spatrick namespace lld {
25bb684c34Spatrick namespace macho {
26bb684c34Spatrick
27bb684c34Spatrick class InputFile;
28bb684c34Spatrick class OutputSection;
29bb684c34Spatrick
30bb684c34Spatrick class InputSection {
31bb684c34Spatrick public:
32*dfe94b16Srobert enum Kind : uint8_t {
331cf9926bSpatrick ConcatKind,
341cf9926bSpatrick CStringLiteralKind,
351cf9926bSpatrick WordLiteralKind,
361cf9926bSpatrick };
371cf9926bSpatrick
kind()38*dfe94b16Srobert Kind kind() const { return sectionKind; }
39bb684c34Spatrick virtual ~InputSection() = default;
getSize()40bb684c34Spatrick virtual uint64_t getSize() const { return data.size(); }
empty()41*dfe94b16Srobert virtual bool empty() const { return data.empty(); }
getFile()42*dfe94b16Srobert InputFile *getFile() const { return section.file; }
getName()43*dfe94b16Srobert StringRef getName() const { return section.name; }
getSegName()44*dfe94b16Srobert StringRef getSegName() const { return section.segname; }
getFlags()45*dfe94b16Srobert uint32_t getFlags() const { return section.flags; }
461cf9926bSpatrick uint64_t getFileSize() const;
471cf9926bSpatrick // Translates \p off -- an offset relative to this InputSection -- into an
481cf9926bSpatrick // offset from the beginning of its parent OutputSection.
491cf9926bSpatrick virtual uint64_t getOffset(uint64_t off) const = 0;
501cf9926bSpatrick // The offset from the beginning of the file.
511cf9926bSpatrick uint64_t getVA(uint64_t off) const;
52*dfe94b16Srobert // Return a user-friendly string for use in diagnostics.
53*dfe94b16Srobert // Format: /path/to/object.o:(symbol _func+0x123)
54*dfe94b16Srobert std::string getLocation(uint64_t off) const;
55*dfe94b16Srobert // Return the source line corresponding to an address, or the empty string.
56*dfe94b16Srobert // Format: Source.cpp:123 (/path/to/Source.cpp:123)
57*dfe94b16Srobert std::string getSourceLocation(uint64_t off) const;
581cf9926bSpatrick // Whether the data at \p off in this InputSection is live.
591cf9926bSpatrick virtual bool isLive(uint64_t off) const = 0;
601cf9926bSpatrick virtual void markLive(uint64_t off) = 0;
canonical()611cf9926bSpatrick virtual InputSection *canonical() { return this; }
canonical()62*dfe94b16Srobert virtual const InputSection *canonical() const { return this; }
631cf9926bSpatrick
641cf9926bSpatrick protected:
InputSection(Kind kind,const Section & section,ArrayRef<uint8_t> data,uint32_t align)65*dfe94b16Srobert InputSection(Kind kind, const Section §ion, ArrayRef<uint8_t> data,
66*dfe94b16Srobert uint32_t align)
67*dfe94b16Srobert : sectionKind(kind), keepUnique(false), hasAltEntry(false), align(align),
68*dfe94b16Srobert data(data), section(section) {}
69*dfe94b16Srobert
InputSection(const InputSection & rhs)70*dfe94b16Srobert InputSection(const InputSection &rhs)
71*dfe94b16Srobert : sectionKind(rhs.sectionKind), keepUnique(false), hasAltEntry(false),
72*dfe94b16Srobert align(rhs.align), data(rhs.data), section(rhs.section) {}
73*dfe94b16Srobert
741cf9926bSpatrick Kind sectionKind;
75bb684c34Spatrick
76*dfe94b16Srobert public:
77*dfe94b16Srobert // is address assigned?
78*dfe94b16Srobert bool isFinal = false;
79*dfe94b16Srobert // keep the address of the symbol(s) in this section unique in the final
80*dfe94b16Srobert // binary ?
81*dfe94b16Srobert bool keepUnique : 1;
82*dfe94b16Srobert // Does this section have symbols at offsets other than zero? (NOTE: only
83*dfe94b16Srobert // applies to ConcatInputSections.)
84*dfe94b16Srobert bool hasAltEntry : 1;
85*dfe94b16Srobert uint32_t align = 1;
861cf9926bSpatrick
87*dfe94b16Srobert OutputSection *parent = nullptr;
88*dfe94b16Srobert ArrayRef<uint8_t> data;
89*dfe94b16Srobert std::vector<Reloc> relocs;
90*dfe94b16Srobert // The symbols that belong to this InputSection, sorted by value. With
91*dfe94b16Srobert // .subsections_via_symbols, there is typically only one element here.
92*dfe94b16Srobert llvm::TinyPtrVector<Defined *> symbols;
931cf9926bSpatrick
94*dfe94b16Srobert protected:
95*dfe94b16Srobert const Section §ion;
96*dfe94b16Srobert
97*dfe94b16Srobert const Defined *getContainingSymbol(uint64_t off) const;
981cf9926bSpatrick };
991cf9926bSpatrick
1001cf9926bSpatrick // ConcatInputSections are combined into (Concat)OutputSections through simple
1011cf9926bSpatrick // concatenation, in contrast with literal sections which may have their
1021cf9926bSpatrick // contents merged before output.
1031cf9926bSpatrick class ConcatInputSection final : public InputSection {
1041cf9926bSpatrick public:
105*dfe94b16Srobert ConcatInputSection(const Section §ion, ArrayRef<uint8_t> data,
106*dfe94b16Srobert uint32_t align = 1)
InputSection(ConcatKind,section,data,align)107*dfe94b16Srobert : InputSection(ConcatKind, section, data, align) {}
1081cf9926bSpatrick
getOffset(uint64_t off)1091cf9926bSpatrick uint64_t getOffset(uint64_t off) const override { return outSecOff + off; }
getVA()1101cf9926bSpatrick uint64_t getVA() const { return InputSection::getVA(0); }
1111cf9926bSpatrick // ConcatInputSections are entirely live or dead, so the offset is irrelevant.
isLive(uint64_t off)1121cf9926bSpatrick bool isLive(uint64_t off) const override { return live; }
markLive(uint64_t off)1131cf9926bSpatrick void markLive(uint64_t off) override { live = true; }
isCoalescedWeak()114*dfe94b16Srobert bool isCoalescedWeak() const { return wasCoalesced && symbols.empty(); }
shouldOmitFromOutput()1151cf9926bSpatrick bool shouldOmitFromOutput() const { return !live || isCoalescedWeak(); }
1161cf9926bSpatrick void writeTo(uint8_t *buf);
1171cf9926bSpatrick
1181cf9926bSpatrick void foldIdentical(ConcatInputSection *redundant);
canonical()119*dfe94b16Srobert ConcatInputSection *canonical() override {
120*dfe94b16Srobert return replacement ? replacement : this;
121*dfe94b16Srobert }
canonical()122*dfe94b16Srobert const InputSection *canonical() const override {
1231cf9926bSpatrick return replacement ? replacement : this;
1241cf9926bSpatrick }
1251cf9926bSpatrick
classof(const InputSection * isec)1261cf9926bSpatrick static bool classof(const InputSection *isec) {
1271cf9926bSpatrick return isec->kind() == ConcatKind;
1281cf9926bSpatrick }
1291cf9926bSpatrick
1301cf9926bSpatrick // Points to the surviving section after this one is folded by ICF
131*dfe94b16Srobert ConcatInputSection *replacement = nullptr;
1321cf9926bSpatrick // Equivalence-class ID for ICF
133*dfe94b16Srobert uint32_t icfEqClass[2] = {0, 0};
1341cf9926bSpatrick
1351cf9926bSpatrick // With subsections_via_symbols, most symbols have their own InputSection,
1361cf9926bSpatrick // and for weak symbols (e.g. from inline functions), only the
1371cf9926bSpatrick // InputSection from one translation unit will make it to the output,
1381cf9926bSpatrick // while all copies in other translation units are coalesced into the
1391cf9926bSpatrick // first and not copied to the output.
1401cf9926bSpatrick bool wasCoalesced = false;
1411cf9926bSpatrick bool live = !config->deadStrip;
142*dfe94b16Srobert bool hasCallSites = false;
1431cf9926bSpatrick // This variable has two usages. Initially, it represents the input order.
1441cf9926bSpatrick // After assignAddresses is called, it represents the offset from the
1451cf9926bSpatrick // beginning of the output section this section was assigned to.
1461cf9926bSpatrick uint64_t outSecOff = 0;
1471cf9926bSpatrick };
1481cf9926bSpatrick
149*dfe94b16Srobert // Initialize a fake InputSection that does not belong to any InputFile.
150*dfe94b16Srobert ConcatInputSection *makeSyntheticInputSection(StringRef segName,
151*dfe94b16Srobert StringRef sectName,
152*dfe94b16Srobert uint32_t flags = 0,
153*dfe94b16Srobert ArrayRef<uint8_t> data = {},
154*dfe94b16Srobert uint32_t align = 1);
1551cf9926bSpatrick
1561cf9926bSpatrick // Helper functions to make it easy to sprinkle asserts.
1571cf9926bSpatrick
shouldOmitFromOutput(InputSection * isec)1581cf9926bSpatrick inline bool shouldOmitFromOutput(InputSection *isec) {
1591cf9926bSpatrick return isa<ConcatInputSection>(isec) &&
1601cf9926bSpatrick cast<ConcatInputSection>(isec)->shouldOmitFromOutput();
1611cf9926bSpatrick }
1621cf9926bSpatrick
isCoalescedWeak(InputSection * isec)1631cf9926bSpatrick inline bool isCoalescedWeak(InputSection *isec) {
1641cf9926bSpatrick return isa<ConcatInputSection>(isec) &&
1651cf9926bSpatrick cast<ConcatInputSection>(isec)->isCoalescedWeak();
1661cf9926bSpatrick }
1671cf9926bSpatrick
1681cf9926bSpatrick // We allocate a lot of these and binary search on them, so they should be as
1691cf9926bSpatrick // compact as possible. Hence the use of 31 rather than 64 bits for the hash.
1701cf9926bSpatrick struct StringPiece {
1711cf9926bSpatrick // Offset from the start of the containing input section.
1721cf9926bSpatrick uint32_t inSecOff;
1731cf9926bSpatrick uint32_t live : 1;
1741cf9926bSpatrick // Only set if deduplicating literals
1751cf9926bSpatrick uint32_t hash : 31;
1761cf9926bSpatrick // Offset from the start of the containing output section.
1771cf9926bSpatrick uint64_t outSecOff = 0;
1781cf9926bSpatrick
StringPieceStringPiece1791cf9926bSpatrick StringPiece(uint64_t off, uint32_t hash)
1801cf9926bSpatrick : inSecOff(off), live(!config->deadStrip), hash(hash) {}
1811cf9926bSpatrick };
1821cf9926bSpatrick
1831cf9926bSpatrick static_assert(sizeof(StringPiece) == 16, "StringPiece is too big!");
1841cf9926bSpatrick
1851cf9926bSpatrick // CStringInputSections are composed of multiple null-terminated string
1861cf9926bSpatrick // literals, which we represent using StringPieces. These literals can be
1871cf9926bSpatrick // deduplicated and tail-merged, so translating offsets between the input and
1881cf9926bSpatrick // outputs sections is more complicated.
1891cf9926bSpatrick //
1901cf9926bSpatrick // NOTE: One significant difference between LLD and ld64 is that we merge all
1911cf9926bSpatrick // cstring literals, even those referenced directly by non-private symbols.
1921cf9926bSpatrick // ld64 is more conservative and does not do that. This was mostly done for
1931cf9926bSpatrick // implementation simplicity; if we find programs that need the more
1941cf9926bSpatrick // conservative behavior we can certainly implement that.
1951cf9926bSpatrick class CStringInputSection final : public InputSection {
1961cf9926bSpatrick public:
CStringInputSection(const Section & section,ArrayRef<uint8_t> data,uint32_t align,bool dedupLiterals)197*dfe94b16Srobert CStringInputSection(const Section §ion, ArrayRef<uint8_t> data,
198*dfe94b16Srobert uint32_t align, bool dedupLiterals)
199*dfe94b16Srobert : InputSection(CStringLiteralKind, section, data, align),
200*dfe94b16Srobert deduplicateLiterals(dedupLiterals) {}
201*dfe94b16Srobert
2021cf9926bSpatrick uint64_t getOffset(uint64_t off) const override;
isLive(uint64_t off)2031cf9926bSpatrick bool isLive(uint64_t off) const override { return getStringPiece(off).live; }
markLive(uint64_t off)2041cf9926bSpatrick void markLive(uint64_t off) override { getStringPiece(off).live = true; }
2051cf9926bSpatrick // Find the StringPiece that contains this offset.
2061cf9926bSpatrick StringPiece &getStringPiece(uint64_t off);
2071cf9926bSpatrick const StringPiece &getStringPiece(uint64_t off) const;
2081cf9926bSpatrick // Split at each null byte.
2091cf9926bSpatrick void splitIntoPieces();
2101cf9926bSpatrick
2111cf9926bSpatrick LLVM_ATTRIBUTE_ALWAYS_INLINE
getStringRef(size_t i)2121cf9926bSpatrick StringRef getStringRef(size_t i) const {
2131cf9926bSpatrick size_t begin = pieces[i].inSecOff;
214*dfe94b16Srobert // The endpoint should be *at* the null terminator, not after. This matches
215*dfe94b16Srobert // the behavior of StringRef(const char *Str).
2161cf9926bSpatrick size_t end =
217*dfe94b16Srobert ((pieces.size() - 1 == i) ? data.size() : pieces[i + 1].inSecOff) - 1;
2181cf9926bSpatrick return toStringRef(data.slice(begin, end - begin));
2191cf9926bSpatrick }
2201cf9926bSpatrick
2211cf9926bSpatrick // Returns i'th piece as a CachedHashStringRef. This function is very hot when
2221cf9926bSpatrick // string merging is enabled, so we want to inline.
2231cf9926bSpatrick LLVM_ATTRIBUTE_ALWAYS_INLINE
getCachedHashStringRef(size_t i)2241cf9926bSpatrick llvm::CachedHashStringRef getCachedHashStringRef(size_t i) const {
225*dfe94b16Srobert assert(deduplicateLiterals);
2261cf9926bSpatrick return {getStringRef(i), pieces[i].hash};
2271cf9926bSpatrick }
2281cf9926bSpatrick
classof(const InputSection * isec)2291cf9926bSpatrick static bool classof(const InputSection *isec) {
2301cf9926bSpatrick return isec->kind() == CStringLiteralKind;
2311cf9926bSpatrick }
2321cf9926bSpatrick
233*dfe94b16Srobert bool deduplicateLiterals = false;
2341cf9926bSpatrick std::vector<StringPiece> pieces;
2351cf9926bSpatrick };
2361cf9926bSpatrick
2371cf9926bSpatrick class WordLiteralInputSection final : public InputSection {
2381cf9926bSpatrick public:
239*dfe94b16Srobert WordLiteralInputSection(const Section §ion, ArrayRef<uint8_t> data,
240*dfe94b16Srobert uint32_t align);
2411cf9926bSpatrick uint64_t getOffset(uint64_t off) const override;
isLive(uint64_t off)2421cf9926bSpatrick bool isLive(uint64_t off) const override {
2431cf9926bSpatrick return live[off >> power2LiteralSize];
2441cf9926bSpatrick }
markLive(uint64_t off)245*dfe94b16Srobert void markLive(uint64_t off) override {
246*dfe94b16Srobert live[off >> power2LiteralSize] = true;
247*dfe94b16Srobert }
2481cf9926bSpatrick
classof(const InputSection * isec)2491cf9926bSpatrick static bool classof(const InputSection *isec) {
2501cf9926bSpatrick return isec->kind() == WordLiteralKind;
2511cf9926bSpatrick }
2521cf9926bSpatrick
2531cf9926bSpatrick private:
2541cf9926bSpatrick unsigned power2LiteralSize;
2551cf9926bSpatrick // The liveness of data[off] is tracked by live[off >> power2LiteralSize].
2561cf9926bSpatrick llvm::BitVector live;
2571cf9926bSpatrick };
2581cf9926bSpatrick
sectionType(uint32_t flags)2591cf9926bSpatrick inline uint8_t sectionType(uint32_t flags) {
2601cf9926bSpatrick return flags & llvm::MachO::SECTION_TYPE;
2611cf9926bSpatrick }
2621cf9926bSpatrick
isZeroFill(uint32_t flags)2631cf9926bSpatrick inline bool isZeroFill(uint32_t flags) {
2641cf9926bSpatrick return llvm::MachO::isVirtualSection(sectionType(flags));
2651cf9926bSpatrick }
2661cf9926bSpatrick
isThreadLocalVariables(uint32_t flags)2671cf9926bSpatrick inline bool isThreadLocalVariables(uint32_t flags) {
2681cf9926bSpatrick return sectionType(flags) == llvm::MachO::S_THREAD_LOCAL_VARIABLES;
2691cf9926bSpatrick }
2701cf9926bSpatrick
2711cf9926bSpatrick // These sections contain the data for initializing thread-local variables.
isThreadLocalData(uint32_t flags)2721cf9926bSpatrick inline bool isThreadLocalData(uint32_t flags) {
2731cf9926bSpatrick return sectionType(flags) == llvm::MachO::S_THREAD_LOCAL_REGULAR ||
2741cf9926bSpatrick sectionType(flags) == llvm::MachO::S_THREAD_LOCAL_ZEROFILL;
2751cf9926bSpatrick }
2761cf9926bSpatrick
isDebugSection(uint32_t flags)2771cf9926bSpatrick inline bool isDebugSection(uint32_t flags) {
2781cf9926bSpatrick return (flags & llvm::MachO::SECTION_ATTRIBUTES_USR) ==
2791cf9926bSpatrick llvm::MachO::S_ATTR_DEBUG;
2801cf9926bSpatrick }
2811cf9926bSpatrick
isWordLiteralSection(uint32_t flags)2821cf9926bSpatrick inline bool isWordLiteralSection(uint32_t flags) {
2831cf9926bSpatrick return sectionType(flags) == llvm::MachO::S_4BYTE_LITERALS ||
2841cf9926bSpatrick sectionType(flags) == llvm::MachO::S_8BYTE_LITERALS ||
2851cf9926bSpatrick sectionType(flags) == llvm::MachO::S_16BYTE_LITERALS;
2861cf9926bSpatrick }
2871cf9926bSpatrick
2881cf9926bSpatrick bool isCodeSection(const InputSection *);
2891cf9926bSpatrick bool isCfStringSection(const InputSection *);
290*dfe94b16Srobert bool isClassRefsSection(const InputSection *);
291*dfe94b16Srobert bool isSelRefsSection(const InputSection *);
292*dfe94b16Srobert bool isEhFrameSection(const InputSection *);
293*dfe94b16Srobert bool isGccExceptTabSection(const InputSection *);
2941cf9926bSpatrick
2951cf9926bSpatrick extern std::vector<ConcatInputSection *> inputSections;
2961cf9926bSpatrick
2971cf9926bSpatrick namespace section_names {
2981cf9926bSpatrick
2991cf9926bSpatrick constexpr const char authGot[] = "__auth_got";
3001cf9926bSpatrick constexpr const char authPtr[] = "__auth_ptr";
3011cf9926bSpatrick constexpr const char binding[] = "__binding";
3021cf9926bSpatrick constexpr const char bitcodeBundle[] = "__bundle";
3031cf9926bSpatrick constexpr const char cString[] = "__cstring";
3041cf9926bSpatrick constexpr const char cfString[] = "__cfstring";
305*dfe94b16Srobert constexpr const char cgProfile[] = "__cg_profile";
306*dfe94b16Srobert constexpr const char chainFixups[] = "__chainfixups";
3071cf9926bSpatrick constexpr const char codeSignature[] = "__code_signature";
3081cf9926bSpatrick constexpr const char common[] = "__common";
3091cf9926bSpatrick constexpr const char compactUnwind[] = "__compact_unwind";
3101cf9926bSpatrick constexpr const char data[] = "__data";
3111cf9926bSpatrick constexpr const char debugAbbrev[] = "__debug_abbrev";
3121cf9926bSpatrick constexpr const char debugInfo[] = "__debug_info";
313*dfe94b16Srobert constexpr const char debugLine[] = "__debug_line";
3141cf9926bSpatrick constexpr const char debugStr[] = "__debug_str";
315*dfe94b16Srobert constexpr const char debugStrOffs[] = "__debug_str_offs";
3161cf9926bSpatrick constexpr const char ehFrame[] = "__eh_frame";
317*dfe94b16Srobert constexpr const char gccExceptTab[] = "__gcc_except_tab";
3181cf9926bSpatrick constexpr const char export_[] = "__export";
3191cf9926bSpatrick constexpr const char dataInCode[] = "__data_in_code";
3201cf9926bSpatrick constexpr const char functionStarts[] = "__func_starts";
3211cf9926bSpatrick constexpr const char got[] = "__got";
3221cf9926bSpatrick constexpr const char header[] = "__mach_header";
3231cf9926bSpatrick constexpr const char indirectSymbolTable[] = "__ind_sym_tab";
324*dfe94b16Srobert constexpr const char initOffsets[] = "__init_offsets";
3251cf9926bSpatrick constexpr const char const_[] = "__const";
3261cf9926bSpatrick constexpr const char lazySymbolPtr[] = "__la_symbol_ptr";
3271cf9926bSpatrick constexpr const char lazyBinding[] = "__lazy_binding";
3281cf9926bSpatrick constexpr const char literals[] = "__literals";
3291cf9926bSpatrick constexpr const char moduleInitFunc[] = "__mod_init_func";
3301cf9926bSpatrick constexpr const char moduleTermFunc[] = "__mod_term_func";
3311cf9926bSpatrick constexpr const char nonLazySymbolPtr[] = "__nl_symbol_ptr";
3321cf9926bSpatrick constexpr const char objcCatList[] = "__objc_catlist";
3331cf9926bSpatrick constexpr const char objcClassList[] = "__objc_classlist";
334*dfe94b16Srobert constexpr const char objcClassRefs[] = "__objc_classrefs";
3351cf9926bSpatrick constexpr const char objcConst[] = "__objc_const";
336*dfe94b16Srobert constexpr const char objCImageInfo[] = "__objc_imageinfo";
337*dfe94b16Srobert constexpr const char objcStubs[] = "__objc_stubs";
338*dfe94b16Srobert constexpr const char objcSelrefs[] = "__objc_selrefs";
339*dfe94b16Srobert constexpr const char objcMethname[] = "__objc_methname";
3401cf9926bSpatrick constexpr const char objcNonLazyCatList[] = "__objc_nlcatlist";
3411cf9926bSpatrick constexpr const char objcNonLazyClassList[] = "__objc_nlclslist";
3421cf9926bSpatrick constexpr const char objcProtoList[] = "__objc_protolist";
3431cf9926bSpatrick constexpr const char pageZero[] = "__pagezero";
3441cf9926bSpatrick constexpr const char pointers[] = "__pointers";
3451cf9926bSpatrick constexpr const char rebase[] = "__rebase";
3461cf9926bSpatrick constexpr const char staticInit[] = "__StaticInit";
3471cf9926bSpatrick constexpr const char stringTable[] = "__string_table";
3481cf9926bSpatrick constexpr const char stubHelper[] = "__stub_helper";
3491cf9926bSpatrick constexpr const char stubs[] = "__stubs";
3501cf9926bSpatrick constexpr const char swift[] = "__swift";
3511cf9926bSpatrick constexpr const char symbolTable[] = "__symbol_table";
3521cf9926bSpatrick constexpr const char textCoalNt[] = "__textcoal_nt";
3531cf9926bSpatrick constexpr const char text[] = "__text";
3541cf9926bSpatrick constexpr const char threadPtrs[] = "__thread_ptrs";
3551cf9926bSpatrick constexpr const char threadVars[] = "__thread_vars";
3561cf9926bSpatrick constexpr const char unwindInfo[] = "__unwind_info";
3571cf9926bSpatrick constexpr const char weakBinding[] = "__weak_binding";
3581cf9926bSpatrick constexpr const char zeroFill[] = "__zerofill";
359*dfe94b16Srobert constexpr const char addrSig[] = "__llvm_addrsig";
3601cf9926bSpatrick
3611cf9926bSpatrick } // namespace section_names
362bb684c34Spatrick
363bb684c34Spatrick } // namespace macho
3641cf9926bSpatrick
3651cf9926bSpatrick std::string toString(const macho::InputSection *);
3661cf9926bSpatrick
367bb684c34Spatrick } // namespace lld
368bb684c34Spatrick
369bb684c34Spatrick #endif
370