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 3881ad6265SDimitry Andric Kind kind() const { return 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(); } 4281ad6265SDimitry Andric InputFile *getFile() const { return section.file; } 4381ad6265SDimitry Andric StringRef getName() const { return section.name; } 4481ad6265SDimitry Andric StringRef getSegName() const { return section.segname; } 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; 58fe6060f1SDimitry Andric // Whether the data at \p off in this InputSection is live. 59fe6060f1SDimitry Andric virtual bool isLive(uint64_t off) const = 0; 60fe6060f1SDimitry Andric virtual void markLive(uint64_t off) = 0; 61fe6060f1SDimitry Andric virtual InputSection *canonical() { return this; } 6204eeddc0SDimitry Andric virtual const InputSection *canonical() const { return this; } 635ffd83dbSDimitry Andric 6481ad6265SDimitry Andric protected: 6581ad6265SDimitry Andric InputSection(Kind kind, const Section §ion, ArrayRef<uint8_t> data, 6681ad6265SDimitry Andric uint32_t align) 6781ad6265SDimitry Andric : sectionKind(kind), align(align), data(data), section(section) {} 685ffd83dbSDimitry Andric 6981ad6265SDimitry Andric InputSection(const InputSection &rhs) 7081ad6265SDimitry Andric : sectionKind(rhs.sectionKind), align(rhs.align), data(rhs.data), 7181ad6265SDimitry Andric section(rhs.section) {} 7281ad6265SDimitry Andric 7381ad6265SDimitry Andric Kind sectionKind; 7481ad6265SDimitry Andric 7581ad6265SDimitry Andric public: 76fe6060f1SDimitry Andric // is address assigned? 770eae32dcSDimitry Andric bool isFinal = false; 7881ad6265SDimitry Andric // keep the address of the symbol(s) in this section unique in the final 7981ad6265SDimitry Andric // binary ? 8081ad6265SDimitry Andric bool keepUnique = false; 8181ad6265SDimitry Andric uint32_t align = 1; 825ffd83dbSDimitry Andric 8381ad6265SDimitry Andric OutputSection *parent = nullptr; 845ffd83dbSDimitry Andric ArrayRef<uint8_t> data; 855ffd83dbSDimitry Andric std::vector<Reloc> relocs; 8681ad6265SDimitry Andric ArrayRef<OptimizationHint> optimizationHints; 87349cc55cSDimitry Andric // The symbols that belong to this InputSection, sorted by value. With 88349cc55cSDimitry Andric // .subsections_via_symbols, there is typically only one element here. 89349cc55cSDimitry Andric llvm::TinyPtrVector<Defined *> symbols; 90fe6060f1SDimitry Andric 91fe6060f1SDimitry Andric protected: 9281ad6265SDimitry Andric const Section §ion; 93fe6060f1SDimitry Andric 9481ad6265SDimitry Andric const Defined *getContainingSymbol(uint64_t off) const; 95fe6060f1SDimitry Andric }; 96fe6060f1SDimitry Andric 97fe6060f1SDimitry Andric // ConcatInputSections are combined into (Concat)OutputSections through simple 98fe6060f1SDimitry Andric // concatenation, in contrast with literal sections which may have their 99fe6060f1SDimitry Andric // contents merged before output. 100fe6060f1SDimitry Andric class ConcatInputSection final : public InputSection { 101fe6060f1SDimitry Andric public: 10281ad6265SDimitry Andric ConcatInputSection(const Section §ion, ArrayRef<uint8_t> data, 10381ad6265SDimitry Andric uint32_t align = 1) 10481ad6265SDimitry Andric : InputSection(ConcatKind, section, data, align) {} 105349cc55cSDimitry Andric 106fe6060f1SDimitry Andric uint64_t getOffset(uint64_t off) const override { return outSecOff + off; } 107fe6060f1SDimitry Andric uint64_t getVA() const { return InputSection::getVA(0); } 108fe6060f1SDimitry Andric // ConcatInputSections are entirely live or dead, so the offset is irrelevant. 109fe6060f1SDimitry Andric bool isLive(uint64_t off) const override { return live; } 110fe6060f1SDimitry Andric void markLive(uint64_t off) override { live = true; } 111349cc55cSDimitry Andric bool isCoalescedWeak() const { return wasCoalesced && symbols.empty(); } 112fe6060f1SDimitry Andric bool shouldOmitFromOutput() const { return !live || isCoalescedWeak(); } 113fe6060f1SDimitry Andric void writeTo(uint8_t *buf); 114fe6060f1SDimitry Andric 115fe6060f1SDimitry Andric void foldIdentical(ConcatInputSection *redundant); 116349cc55cSDimitry Andric ConcatInputSection *canonical() override { 117fe6060f1SDimitry Andric return replacement ? replacement : this; 118fe6060f1SDimitry Andric } 11904eeddc0SDimitry Andric const InputSection *canonical() const override { 12004eeddc0SDimitry Andric return replacement ? replacement : this; 12104eeddc0SDimitry Andric } 122fe6060f1SDimitry Andric 123fe6060f1SDimitry Andric static bool classof(const InputSection *isec) { 124fe6060f1SDimitry Andric return isec->kind() == ConcatKind; 125fe6060f1SDimitry Andric } 126fe6060f1SDimitry Andric 127fe6060f1SDimitry Andric // Points to the surviving section after this one is folded by ICF 128349cc55cSDimitry Andric ConcatInputSection *replacement = nullptr; 129fe6060f1SDimitry Andric // Equivalence-class ID for ICF 13081ad6265SDimitry Andric uint32_t icfEqClass[2] = {0, 0}; 131fe6060f1SDimitry Andric 132fe6060f1SDimitry Andric // With subsections_via_symbols, most symbols have their own InputSection, 133fe6060f1SDimitry Andric // and for weak symbols (e.g. from inline functions), only the 134fe6060f1SDimitry Andric // InputSection from one translation unit will make it to the output, 135fe6060f1SDimitry Andric // while all copies in other translation units are coalesced into the 136fe6060f1SDimitry Andric // first and not copied to the output. 137fe6060f1SDimitry Andric bool wasCoalesced = false; 138fe6060f1SDimitry Andric bool live = !config->deadStrip; 1390eae32dcSDimitry Andric bool hasCallSites = false; 140fe6060f1SDimitry Andric // This variable has two usages. Initially, it represents the input order. 141fe6060f1SDimitry Andric // After assignAddresses is called, it represents the offset from the 142fe6060f1SDimitry Andric // beginning of the output section this section was assigned to. 143fe6060f1SDimitry Andric uint64_t outSecOff = 0; 144fe6060f1SDimitry Andric }; 145fe6060f1SDimitry Andric 14681ad6265SDimitry Andric // Initialize a fake InputSection that does not belong to any InputFile. 14781ad6265SDimitry Andric ConcatInputSection *makeSyntheticInputSection(StringRef segName, 14881ad6265SDimitry Andric StringRef sectName, 14981ad6265SDimitry Andric uint32_t flags = 0, 15081ad6265SDimitry Andric ArrayRef<uint8_t> data = {}, 15181ad6265SDimitry Andric uint32_t align = 1); 15281ad6265SDimitry Andric 153fe6060f1SDimitry Andric // Helper functions to make it easy to sprinkle asserts. 154fe6060f1SDimitry Andric 155fe6060f1SDimitry Andric inline bool shouldOmitFromOutput(InputSection *isec) { 156fe6060f1SDimitry Andric return isa<ConcatInputSection>(isec) && 157fe6060f1SDimitry Andric cast<ConcatInputSection>(isec)->shouldOmitFromOutput(); 158fe6060f1SDimitry Andric } 159fe6060f1SDimitry Andric 160fe6060f1SDimitry Andric inline bool isCoalescedWeak(InputSection *isec) { 161fe6060f1SDimitry Andric return isa<ConcatInputSection>(isec) && 162fe6060f1SDimitry Andric cast<ConcatInputSection>(isec)->isCoalescedWeak(); 163fe6060f1SDimitry Andric } 164fe6060f1SDimitry Andric 165fe6060f1SDimitry Andric // We allocate a lot of these and binary search on them, so they should be as 166fe6060f1SDimitry Andric // compact as possible. Hence the use of 31 rather than 64 bits for the hash. 167fe6060f1SDimitry Andric struct StringPiece { 168fe6060f1SDimitry Andric // Offset from the start of the containing input section. 169fe6060f1SDimitry Andric uint32_t inSecOff; 170fe6060f1SDimitry Andric uint32_t live : 1; 171fe6060f1SDimitry Andric // Only set if deduplicating literals 172fe6060f1SDimitry Andric uint32_t hash : 31; 173fe6060f1SDimitry Andric // Offset from the start of the containing output section. 174fe6060f1SDimitry Andric uint64_t outSecOff = 0; 175fe6060f1SDimitry Andric 176fe6060f1SDimitry Andric StringPiece(uint64_t off, uint32_t hash) 177fe6060f1SDimitry Andric : inSecOff(off), live(!config->deadStrip), hash(hash) {} 178fe6060f1SDimitry Andric }; 179fe6060f1SDimitry Andric 180fe6060f1SDimitry Andric static_assert(sizeof(StringPiece) == 16, "StringPiece is too big!"); 181fe6060f1SDimitry Andric 182fe6060f1SDimitry Andric // CStringInputSections are composed of multiple null-terminated string 183fe6060f1SDimitry Andric // literals, which we represent using StringPieces. These literals can be 184fe6060f1SDimitry Andric // deduplicated and tail-merged, so translating offsets between the input and 185fe6060f1SDimitry Andric // outputs sections is more complicated. 186fe6060f1SDimitry Andric // 187fe6060f1SDimitry Andric // NOTE: One significant difference between LLD and ld64 is that we merge all 188fe6060f1SDimitry Andric // cstring literals, even those referenced directly by non-private symbols. 189fe6060f1SDimitry Andric // ld64 is more conservative and does not do that. This was mostly done for 190fe6060f1SDimitry Andric // implementation simplicity; if we find programs that need the more 191fe6060f1SDimitry Andric // conservative behavior we can certainly implement that. 192fe6060f1SDimitry Andric class CStringInputSection final : public InputSection { 193fe6060f1SDimitry Andric public: 19481ad6265SDimitry Andric CStringInputSection(const Section §ion, ArrayRef<uint8_t> data, 19581ad6265SDimitry Andric uint32_t align) 19681ad6265SDimitry Andric : InputSection(CStringLiteralKind, section, data, align) {} 197fe6060f1SDimitry Andric uint64_t getOffset(uint64_t off) const override; 198fe6060f1SDimitry Andric bool isLive(uint64_t off) const override { return getStringPiece(off).live; } 199fe6060f1SDimitry Andric void markLive(uint64_t off) override { getStringPiece(off).live = true; } 200fe6060f1SDimitry Andric // Find the StringPiece that contains this offset. 201fe6060f1SDimitry Andric StringPiece &getStringPiece(uint64_t off); 202fe6060f1SDimitry Andric const StringPiece &getStringPiece(uint64_t off) const; 203fe6060f1SDimitry Andric // Split at each null byte. 204fe6060f1SDimitry Andric void splitIntoPieces(); 205fe6060f1SDimitry Andric 206fe6060f1SDimitry Andric LLVM_ATTRIBUTE_ALWAYS_INLINE 207fe6060f1SDimitry Andric StringRef getStringRef(size_t i) const { 208fe6060f1SDimitry Andric size_t begin = pieces[i].inSecOff; 209fe6060f1SDimitry Andric size_t end = 210fe6060f1SDimitry Andric (pieces.size() - 1 == i) ? data.size() : pieces[i + 1].inSecOff; 211fe6060f1SDimitry Andric return toStringRef(data.slice(begin, end - begin)); 212fe6060f1SDimitry Andric } 213fe6060f1SDimitry Andric 214fe6060f1SDimitry Andric // Returns i'th piece as a CachedHashStringRef. This function is very hot when 215fe6060f1SDimitry Andric // string merging is enabled, so we want to inline. 216fe6060f1SDimitry Andric LLVM_ATTRIBUTE_ALWAYS_INLINE 217fe6060f1SDimitry Andric llvm::CachedHashStringRef getCachedHashStringRef(size_t i) const { 218fe6060f1SDimitry Andric assert(config->dedupLiterals); 219fe6060f1SDimitry Andric return {getStringRef(i), pieces[i].hash}; 220fe6060f1SDimitry Andric } 221fe6060f1SDimitry Andric 222fe6060f1SDimitry Andric static bool classof(const InputSection *isec) { 223fe6060f1SDimitry Andric return isec->kind() == CStringLiteralKind; 224fe6060f1SDimitry Andric } 225fe6060f1SDimitry Andric 226fe6060f1SDimitry Andric std::vector<StringPiece> pieces; 227fe6060f1SDimitry Andric }; 228fe6060f1SDimitry Andric 229fe6060f1SDimitry Andric class WordLiteralInputSection final : public InputSection { 230fe6060f1SDimitry Andric public: 23181ad6265SDimitry Andric WordLiteralInputSection(const Section §ion, ArrayRef<uint8_t> data, 23281ad6265SDimitry Andric uint32_t align); 233fe6060f1SDimitry Andric uint64_t getOffset(uint64_t off) const override; 234fe6060f1SDimitry Andric bool isLive(uint64_t off) const override { 235fe6060f1SDimitry Andric return live[off >> power2LiteralSize]; 236fe6060f1SDimitry Andric } 23704eeddc0SDimitry Andric void markLive(uint64_t off) override { 23804eeddc0SDimitry Andric live[off >> power2LiteralSize] = true; 23904eeddc0SDimitry Andric } 240fe6060f1SDimitry Andric 241fe6060f1SDimitry Andric static bool classof(const InputSection *isec) { 242fe6060f1SDimitry Andric return isec->kind() == WordLiteralKind; 243fe6060f1SDimitry Andric } 244fe6060f1SDimitry Andric 245fe6060f1SDimitry Andric private: 246fe6060f1SDimitry Andric unsigned power2LiteralSize; 247fe6060f1SDimitry Andric // The liveness of data[off] is tracked by live[off >> power2LiteralSize]. 248fe6060f1SDimitry Andric llvm::BitVector live; 2495ffd83dbSDimitry Andric }; 2505ffd83dbSDimitry Andric 251e8d8bef9SDimitry Andric inline uint8_t sectionType(uint32_t flags) { 252e8d8bef9SDimitry Andric return flags & llvm::MachO::SECTION_TYPE; 253e8d8bef9SDimitry Andric } 254e8d8bef9SDimitry Andric 255e8d8bef9SDimitry Andric inline bool isZeroFill(uint32_t flags) { 256e8d8bef9SDimitry Andric return llvm::MachO::isVirtualSection(sectionType(flags)); 257e8d8bef9SDimitry Andric } 258e8d8bef9SDimitry Andric 259e8d8bef9SDimitry Andric inline bool isThreadLocalVariables(uint32_t flags) { 260e8d8bef9SDimitry Andric return sectionType(flags) == llvm::MachO::S_THREAD_LOCAL_VARIABLES; 261e8d8bef9SDimitry Andric } 262e8d8bef9SDimitry Andric 263e8d8bef9SDimitry Andric // These sections contain the data for initializing thread-local variables. 264e8d8bef9SDimitry Andric inline bool isThreadLocalData(uint32_t flags) { 265e8d8bef9SDimitry Andric return sectionType(flags) == llvm::MachO::S_THREAD_LOCAL_REGULAR || 266e8d8bef9SDimitry Andric sectionType(flags) == llvm::MachO::S_THREAD_LOCAL_ZEROFILL; 267e8d8bef9SDimitry Andric } 268e8d8bef9SDimitry Andric 269e8d8bef9SDimitry Andric inline bool isDebugSection(uint32_t flags) { 270e8d8bef9SDimitry Andric return (flags & llvm::MachO::SECTION_ATTRIBUTES_USR) == 271e8d8bef9SDimitry Andric llvm::MachO::S_ATTR_DEBUG; 272e8d8bef9SDimitry Andric } 273e8d8bef9SDimitry Andric 274fe6060f1SDimitry Andric inline bool isWordLiteralSection(uint32_t flags) { 275fe6060f1SDimitry Andric return sectionType(flags) == llvm::MachO::S_4BYTE_LITERALS || 276fe6060f1SDimitry Andric sectionType(flags) == llvm::MachO::S_8BYTE_LITERALS || 277fe6060f1SDimitry Andric sectionType(flags) == llvm::MachO::S_16BYTE_LITERALS; 278fe6060f1SDimitry Andric } 279e8d8bef9SDimitry Andric 280fe6060f1SDimitry Andric bool isCodeSection(const InputSection *); 281fe6060f1SDimitry Andric bool isCfStringSection(const InputSection *); 28281ad6265SDimitry Andric bool isClassRefsSection(const InputSection *); 28381ad6265SDimitry Andric bool isEhFrameSection(const InputSection *); 284*fcaf7f86SDimitry Andric bool isGccExceptTabSection(const InputSection *); 285fe6060f1SDimitry Andric 286fe6060f1SDimitry Andric extern std::vector<ConcatInputSection *> inputSections; 287fe6060f1SDimitry Andric 288fe6060f1SDimitry Andric namespace section_names { 289fe6060f1SDimitry Andric 290fe6060f1SDimitry Andric constexpr const char authGot[] = "__auth_got"; 291fe6060f1SDimitry Andric constexpr const char authPtr[] = "__auth_ptr"; 292fe6060f1SDimitry Andric constexpr const char binding[] = "__binding"; 293fe6060f1SDimitry Andric constexpr const char bitcodeBundle[] = "__bundle"; 294fe6060f1SDimitry Andric constexpr const char cString[] = "__cstring"; 295fe6060f1SDimitry Andric constexpr const char cfString[] = "__cfstring"; 29681ad6265SDimitry Andric constexpr const char cgProfile[] = "__cg_profile"; 297fe6060f1SDimitry Andric constexpr const char codeSignature[] = "__code_signature"; 298fe6060f1SDimitry Andric constexpr const char common[] = "__common"; 299fe6060f1SDimitry Andric constexpr const char compactUnwind[] = "__compact_unwind"; 300fe6060f1SDimitry Andric constexpr const char data[] = "__data"; 301fe6060f1SDimitry Andric constexpr const char debugAbbrev[] = "__debug_abbrev"; 302fe6060f1SDimitry Andric constexpr const char debugInfo[] = "__debug_info"; 30381ad6265SDimitry Andric constexpr const char debugLine[] = "__debug_line"; 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"; 32281ad6265SDimitry Andric constexpr const char objcClassRefs[] = "__objc_classrefs"; 323fe6060f1SDimitry Andric constexpr const char objcConst[] = "__objc_const"; 324*fcaf7f86SDimitry Andric constexpr const char objCImageInfo[] = "__objc_imageinfo"; 325fe6060f1SDimitry Andric constexpr const char objcNonLazyCatList[] = "__objc_nlcatlist"; 326fe6060f1SDimitry Andric constexpr const char objcNonLazyClassList[] = "__objc_nlclslist"; 327fe6060f1SDimitry Andric constexpr const char objcProtoList[] = "__objc_protolist"; 328fe6060f1SDimitry Andric constexpr const char pageZero[] = "__pagezero"; 329fe6060f1SDimitry Andric constexpr const char pointers[] = "__pointers"; 330fe6060f1SDimitry Andric constexpr const char rebase[] = "__rebase"; 331fe6060f1SDimitry Andric constexpr const char staticInit[] = "__StaticInit"; 332fe6060f1SDimitry Andric constexpr const char stringTable[] = "__string_table"; 333fe6060f1SDimitry Andric constexpr const char stubHelper[] = "__stub_helper"; 334fe6060f1SDimitry Andric constexpr const char stubs[] = "__stubs"; 335fe6060f1SDimitry Andric constexpr const char swift[] = "__swift"; 336fe6060f1SDimitry Andric constexpr const char symbolTable[] = "__symbol_table"; 337fe6060f1SDimitry Andric constexpr const char textCoalNt[] = "__textcoal_nt"; 338fe6060f1SDimitry Andric constexpr const char text[] = "__text"; 339fe6060f1SDimitry Andric constexpr const char threadPtrs[] = "__thread_ptrs"; 340fe6060f1SDimitry Andric constexpr const char threadVars[] = "__thread_vars"; 341fe6060f1SDimitry Andric constexpr const char unwindInfo[] = "__unwind_info"; 342fe6060f1SDimitry Andric constexpr const char weakBinding[] = "__weak_binding"; 343fe6060f1SDimitry Andric constexpr const char zeroFill[] = "__zerofill"; 34481ad6265SDimitry Andric constexpr const char addrSig[] = "__llvm_addrsig"; 345fe6060f1SDimitry Andric 346fe6060f1SDimitry Andric } // namespace section_names 3475ffd83dbSDimitry Andric 3485ffd83dbSDimitry Andric } // namespace macho 349e8d8bef9SDimitry Andric 350e8d8bef9SDimitry Andric std::string toString(const macho::InputSection *); 351e8d8bef9SDimitry Andric 3525ffd83dbSDimitry Andric } // namespace lld 3535ffd83dbSDimitry Andric 3545ffd83dbSDimitry Andric #endif 355