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