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