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; } 565ffd83dbSDimitry Andric 575ffd83dbSDimitry Andric OutputSection *parent = nullptr; 585ffd83dbSDimitry Andric 595ffd83dbSDimitry Andric uint32_t align = 1; 60fe6060f1SDimitry Andric // is address assigned? 61*0eae32dcSDimitry Andric bool isFinal = false; 625ffd83dbSDimitry Andric 635ffd83dbSDimitry Andric ArrayRef<uint8_t> data; 645ffd83dbSDimitry Andric std::vector<Reloc> relocs; 65349cc55cSDimitry Andric // The symbols that belong to this InputSection, sorted by value. With 66349cc55cSDimitry Andric // .subsections_via_symbols, there is typically only one element here. 67349cc55cSDimitry Andric llvm::TinyPtrVector<Defined *> symbols; 68fe6060f1SDimitry Andric 69fe6060f1SDimitry Andric protected: 70fe6060f1SDimitry Andric // The fields in this struct are immutable. Since we create a lot of 71fe6060f1SDimitry Andric // InputSections with identical values for them (due to 72fe6060f1SDimitry Andric // .subsections_via_symbols), factoring them out into a shared struct reduces 73fe6060f1SDimitry Andric // memory consumption and makes copying cheaper. 74fe6060f1SDimitry Andric struct Shared { 75fe6060f1SDimitry Andric InputFile *file; 76fe6060f1SDimitry Andric StringRef name; 77fe6060f1SDimitry Andric StringRef segname; 78fe6060f1SDimitry Andric uint32_t flags; 79fe6060f1SDimitry Andric Kind sectionKind; 80fe6060f1SDimitry Andric Shared(InputFile *file, StringRef name, StringRef segname, uint32_t flags, 81fe6060f1SDimitry Andric Kind kind) 82fe6060f1SDimitry Andric : file(file), name(name), segname(segname), flags(flags), 83fe6060f1SDimitry Andric sectionKind(kind) {} 84fe6060f1SDimitry Andric }; 85fe6060f1SDimitry Andric 86fe6060f1SDimitry Andric InputSection(Kind kind, StringRef segname, StringRef name, InputFile *file, 87fe6060f1SDimitry Andric ArrayRef<uint8_t> data, uint32_t align, uint32_t flags) 88*0eae32dcSDimitry Andric : align(align), data(data), 89fe6060f1SDimitry Andric shared(make<Shared>(file, name, segname, flags, kind)) {} 90fe6060f1SDimitry Andric 91349cc55cSDimitry Andric InputSection(const InputSection &rhs) 92*0eae32dcSDimitry Andric : align(rhs.align), data(rhs.data), shared(rhs.shared) {} 93349cc55cSDimitry Andric 94fe6060f1SDimitry Andric const Shared *const shared; 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: 102fe6060f1SDimitry Andric ConcatInputSection(StringRef segname, StringRef name, InputFile *file, 103fe6060f1SDimitry Andric ArrayRef<uint8_t> data, uint32_t align = 1, 104fe6060f1SDimitry Andric uint32_t flags = 0) 105fe6060f1SDimitry Andric : InputSection(ConcatKind, segname, name, file, data, align, flags) {} 106fe6060f1SDimitry Andric 107349cc55cSDimitry Andric ConcatInputSection(StringRef segname, StringRef name) 108349cc55cSDimitry Andric : ConcatInputSection(segname, name, /*file=*/nullptr, 109349cc55cSDimitry Andric /*data=*/{}, 110349cc55cSDimitry Andric /*align=*/1, /*flags=*/0) {} 111349cc55cSDimitry Andric 112fe6060f1SDimitry Andric uint64_t getOffset(uint64_t off) const override { return outSecOff + off; } 113fe6060f1SDimitry Andric uint64_t getVA() const { return InputSection::getVA(0); } 114fe6060f1SDimitry Andric // ConcatInputSections are entirely live or dead, so the offset is irrelevant. 115fe6060f1SDimitry Andric bool isLive(uint64_t off) const override { return live; } 116fe6060f1SDimitry Andric void markLive(uint64_t off) override { live = true; } 117349cc55cSDimitry Andric bool isCoalescedWeak() const { return wasCoalesced && symbols.empty(); } 118fe6060f1SDimitry Andric bool shouldOmitFromOutput() const { return !live || isCoalescedWeak(); } 119fe6060f1SDimitry Andric bool isHashableForICF() const; 120fe6060f1SDimitry Andric void hashForICF(); 121fe6060f1SDimitry Andric void writeTo(uint8_t *buf); 122fe6060f1SDimitry Andric 123fe6060f1SDimitry Andric void foldIdentical(ConcatInputSection *redundant); 124349cc55cSDimitry Andric ConcatInputSection *canonical() override { 125fe6060f1SDimitry Andric return replacement ? replacement : this; 126fe6060f1SDimitry Andric } 127fe6060f1SDimitry Andric 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 135fe6060f1SDimitry Andric uint64_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; 144*0eae32dcSDimitry 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 151fe6060f1SDimitry Andric // Helper functions to make it easy to sprinkle asserts. 152fe6060f1SDimitry Andric 153fe6060f1SDimitry Andric inline bool shouldOmitFromOutput(InputSection *isec) { 154fe6060f1SDimitry Andric return isa<ConcatInputSection>(isec) && 155fe6060f1SDimitry Andric cast<ConcatInputSection>(isec)->shouldOmitFromOutput(); 156fe6060f1SDimitry Andric } 157fe6060f1SDimitry Andric 158fe6060f1SDimitry Andric inline bool isCoalescedWeak(InputSection *isec) { 159fe6060f1SDimitry Andric return isa<ConcatInputSection>(isec) && 160fe6060f1SDimitry Andric cast<ConcatInputSection>(isec)->isCoalescedWeak(); 161fe6060f1SDimitry Andric } 162fe6060f1SDimitry Andric 163fe6060f1SDimitry Andric // We allocate a lot of these and binary search on them, so they should be as 164fe6060f1SDimitry Andric // compact as possible. Hence the use of 31 rather than 64 bits for the hash. 165fe6060f1SDimitry Andric struct StringPiece { 166fe6060f1SDimitry Andric // Offset from the start of the containing input section. 167fe6060f1SDimitry Andric uint32_t inSecOff; 168fe6060f1SDimitry Andric uint32_t live : 1; 169fe6060f1SDimitry Andric // Only set if deduplicating literals 170fe6060f1SDimitry Andric uint32_t hash : 31; 171fe6060f1SDimitry Andric // Offset from the start of the containing output section. 172fe6060f1SDimitry Andric uint64_t outSecOff = 0; 173fe6060f1SDimitry Andric 174fe6060f1SDimitry Andric StringPiece(uint64_t off, uint32_t hash) 175fe6060f1SDimitry Andric : inSecOff(off), live(!config->deadStrip), hash(hash) {} 176fe6060f1SDimitry Andric }; 177fe6060f1SDimitry Andric 178fe6060f1SDimitry Andric static_assert(sizeof(StringPiece) == 16, "StringPiece is too big!"); 179fe6060f1SDimitry Andric 180fe6060f1SDimitry Andric // CStringInputSections are composed of multiple null-terminated string 181fe6060f1SDimitry Andric // literals, which we represent using StringPieces. These literals can be 182fe6060f1SDimitry Andric // deduplicated and tail-merged, so translating offsets between the input and 183fe6060f1SDimitry Andric // outputs sections is more complicated. 184fe6060f1SDimitry Andric // 185fe6060f1SDimitry Andric // NOTE: One significant difference between LLD and ld64 is that we merge all 186fe6060f1SDimitry Andric // cstring literals, even those referenced directly by non-private symbols. 187fe6060f1SDimitry Andric // ld64 is more conservative and does not do that. This was mostly done for 188fe6060f1SDimitry Andric // implementation simplicity; if we find programs that need the more 189fe6060f1SDimitry Andric // conservative behavior we can certainly implement that. 190fe6060f1SDimitry Andric class CStringInputSection final : public InputSection { 191fe6060f1SDimitry Andric public: 192fe6060f1SDimitry Andric CStringInputSection(StringRef segname, StringRef name, InputFile *file, 193fe6060f1SDimitry Andric ArrayRef<uint8_t> data, uint32_t align, uint32_t flags) 194fe6060f1SDimitry Andric : InputSection(CStringLiteralKind, segname, name, file, data, align, 195fe6060f1SDimitry Andric flags) {} 196fe6060f1SDimitry Andric uint64_t getOffset(uint64_t off) const override; 197fe6060f1SDimitry Andric bool isLive(uint64_t off) const override { return getStringPiece(off).live; } 198fe6060f1SDimitry Andric void markLive(uint64_t off) override { getStringPiece(off).live = true; } 199fe6060f1SDimitry Andric // Find the StringPiece that contains this offset. 200fe6060f1SDimitry Andric StringPiece &getStringPiece(uint64_t off); 201fe6060f1SDimitry Andric const StringPiece &getStringPiece(uint64_t off) const; 202fe6060f1SDimitry Andric // Split at each null byte. 203fe6060f1SDimitry Andric void splitIntoPieces(); 204fe6060f1SDimitry Andric 205fe6060f1SDimitry Andric LLVM_ATTRIBUTE_ALWAYS_INLINE 206fe6060f1SDimitry Andric StringRef getStringRef(size_t i) const { 207fe6060f1SDimitry Andric size_t begin = pieces[i].inSecOff; 208fe6060f1SDimitry Andric size_t end = 209fe6060f1SDimitry Andric (pieces.size() - 1 == i) ? data.size() : pieces[i + 1].inSecOff; 210fe6060f1SDimitry Andric return toStringRef(data.slice(begin, end - begin)); 211fe6060f1SDimitry Andric } 212fe6060f1SDimitry Andric 213fe6060f1SDimitry Andric // Returns i'th piece as a CachedHashStringRef. This function is very hot when 214fe6060f1SDimitry Andric // string merging is enabled, so we want to inline. 215fe6060f1SDimitry Andric LLVM_ATTRIBUTE_ALWAYS_INLINE 216fe6060f1SDimitry Andric llvm::CachedHashStringRef getCachedHashStringRef(size_t i) const { 217fe6060f1SDimitry Andric assert(config->dedupLiterals); 218fe6060f1SDimitry Andric return {getStringRef(i), pieces[i].hash}; 219fe6060f1SDimitry Andric } 220fe6060f1SDimitry Andric 221fe6060f1SDimitry Andric static bool classof(const InputSection *isec) { 222fe6060f1SDimitry Andric return isec->kind() == CStringLiteralKind; 223fe6060f1SDimitry Andric } 224fe6060f1SDimitry Andric 225fe6060f1SDimitry Andric std::vector<StringPiece> pieces; 226fe6060f1SDimitry Andric }; 227fe6060f1SDimitry Andric 228fe6060f1SDimitry Andric class WordLiteralInputSection final : public InputSection { 229fe6060f1SDimitry Andric public: 230fe6060f1SDimitry Andric WordLiteralInputSection(StringRef segname, StringRef name, InputFile *file, 231fe6060f1SDimitry Andric ArrayRef<uint8_t> data, uint32_t align, 232fe6060f1SDimitry Andric uint32_t flags); 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 } 237fe6060f1SDimitry Andric void markLive(uint64_t off) override { live[off >> power2LiteralSize] = 1; } 238fe6060f1SDimitry Andric 239fe6060f1SDimitry Andric static bool classof(const InputSection *isec) { 240fe6060f1SDimitry Andric return isec->kind() == WordLiteralKind; 241fe6060f1SDimitry Andric } 242fe6060f1SDimitry Andric 243fe6060f1SDimitry Andric private: 244fe6060f1SDimitry Andric unsigned power2LiteralSize; 245fe6060f1SDimitry Andric // The liveness of data[off] is tracked by live[off >> power2LiteralSize]. 246fe6060f1SDimitry Andric llvm::BitVector live; 2475ffd83dbSDimitry Andric }; 2485ffd83dbSDimitry Andric 249e8d8bef9SDimitry Andric inline uint8_t sectionType(uint32_t flags) { 250e8d8bef9SDimitry Andric return flags & llvm::MachO::SECTION_TYPE; 251e8d8bef9SDimitry Andric } 252e8d8bef9SDimitry Andric 253e8d8bef9SDimitry Andric inline bool isZeroFill(uint32_t flags) { 254e8d8bef9SDimitry Andric return llvm::MachO::isVirtualSection(sectionType(flags)); 255e8d8bef9SDimitry Andric } 256e8d8bef9SDimitry Andric 257e8d8bef9SDimitry Andric inline bool isThreadLocalVariables(uint32_t flags) { 258e8d8bef9SDimitry Andric return sectionType(flags) == llvm::MachO::S_THREAD_LOCAL_VARIABLES; 259e8d8bef9SDimitry Andric } 260e8d8bef9SDimitry Andric 261e8d8bef9SDimitry Andric // These sections contain the data for initializing thread-local variables. 262e8d8bef9SDimitry Andric inline bool isThreadLocalData(uint32_t flags) { 263e8d8bef9SDimitry Andric return sectionType(flags) == llvm::MachO::S_THREAD_LOCAL_REGULAR || 264e8d8bef9SDimitry Andric sectionType(flags) == llvm::MachO::S_THREAD_LOCAL_ZEROFILL; 265e8d8bef9SDimitry Andric } 266e8d8bef9SDimitry Andric 267e8d8bef9SDimitry Andric inline bool isDebugSection(uint32_t flags) { 268e8d8bef9SDimitry Andric return (flags & llvm::MachO::SECTION_ATTRIBUTES_USR) == 269e8d8bef9SDimitry Andric llvm::MachO::S_ATTR_DEBUG; 270e8d8bef9SDimitry Andric } 271e8d8bef9SDimitry Andric 272fe6060f1SDimitry Andric inline bool isWordLiteralSection(uint32_t flags) { 273fe6060f1SDimitry Andric return sectionType(flags) == llvm::MachO::S_4BYTE_LITERALS || 274fe6060f1SDimitry Andric sectionType(flags) == llvm::MachO::S_8BYTE_LITERALS || 275fe6060f1SDimitry Andric sectionType(flags) == llvm::MachO::S_16BYTE_LITERALS; 276fe6060f1SDimitry Andric } 277e8d8bef9SDimitry Andric 278fe6060f1SDimitry Andric bool isCodeSection(const InputSection *); 279fe6060f1SDimitry Andric 280fe6060f1SDimitry Andric bool isCfStringSection(const InputSection *); 281fe6060f1SDimitry Andric 282fe6060f1SDimitry Andric extern std::vector<ConcatInputSection *> inputSections; 283fe6060f1SDimitry Andric 284fe6060f1SDimitry Andric namespace section_names { 285fe6060f1SDimitry Andric 286fe6060f1SDimitry Andric constexpr const char authGot[] = "__auth_got"; 287fe6060f1SDimitry Andric constexpr const char authPtr[] = "__auth_ptr"; 288fe6060f1SDimitry Andric constexpr const char binding[] = "__binding"; 289fe6060f1SDimitry Andric constexpr const char bitcodeBundle[] = "__bundle"; 290fe6060f1SDimitry Andric constexpr const char cString[] = "__cstring"; 291fe6060f1SDimitry Andric constexpr const char cfString[] = "__cfstring"; 292fe6060f1SDimitry Andric constexpr const char codeSignature[] = "__code_signature"; 293fe6060f1SDimitry Andric constexpr const char common[] = "__common"; 294fe6060f1SDimitry Andric constexpr const char compactUnwind[] = "__compact_unwind"; 295fe6060f1SDimitry Andric constexpr const char data[] = "__data"; 296fe6060f1SDimitry Andric constexpr const char debugAbbrev[] = "__debug_abbrev"; 297fe6060f1SDimitry Andric constexpr const char debugInfo[] = "__debug_info"; 298fe6060f1SDimitry Andric constexpr const char debugStr[] = "__debug_str"; 299fe6060f1SDimitry Andric constexpr const char ehFrame[] = "__eh_frame"; 300349cc55cSDimitry Andric constexpr const char gccExceptTab[] = "__gcc_except_tab"; 301fe6060f1SDimitry Andric constexpr const char export_[] = "__export"; 302fe6060f1SDimitry Andric constexpr const char dataInCode[] = "__data_in_code"; 303fe6060f1SDimitry Andric constexpr const char functionStarts[] = "__func_starts"; 304fe6060f1SDimitry Andric constexpr const char got[] = "__got"; 305fe6060f1SDimitry Andric constexpr const char header[] = "__mach_header"; 306fe6060f1SDimitry Andric constexpr const char indirectSymbolTable[] = "__ind_sym_tab"; 307fe6060f1SDimitry Andric constexpr const char const_[] = "__const"; 308fe6060f1SDimitry Andric constexpr const char lazySymbolPtr[] = "__la_symbol_ptr"; 309fe6060f1SDimitry Andric constexpr const char lazyBinding[] = "__lazy_binding"; 310fe6060f1SDimitry Andric constexpr const char literals[] = "__literals"; 311fe6060f1SDimitry Andric constexpr const char moduleInitFunc[] = "__mod_init_func"; 312fe6060f1SDimitry Andric constexpr const char moduleTermFunc[] = "__mod_term_func"; 313fe6060f1SDimitry Andric constexpr const char nonLazySymbolPtr[] = "__nl_symbol_ptr"; 314fe6060f1SDimitry Andric constexpr const char objcCatList[] = "__objc_catlist"; 315fe6060f1SDimitry Andric constexpr const char objcClassList[] = "__objc_classlist"; 316fe6060f1SDimitry Andric constexpr const char objcConst[] = "__objc_const"; 317fe6060f1SDimitry Andric constexpr const char objcImageInfo[] = "__objc_imageinfo"; 318fe6060f1SDimitry Andric constexpr const char objcNonLazyCatList[] = "__objc_nlcatlist"; 319fe6060f1SDimitry Andric constexpr const char objcNonLazyClassList[] = "__objc_nlclslist"; 320fe6060f1SDimitry Andric constexpr const char objcProtoList[] = "__objc_protolist"; 321fe6060f1SDimitry Andric constexpr const char pageZero[] = "__pagezero"; 322fe6060f1SDimitry Andric constexpr const char pointers[] = "__pointers"; 323fe6060f1SDimitry Andric constexpr const char rebase[] = "__rebase"; 324fe6060f1SDimitry Andric constexpr const char staticInit[] = "__StaticInit"; 325fe6060f1SDimitry Andric constexpr const char stringTable[] = "__string_table"; 326fe6060f1SDimitry Andric constexpr const char stubHelper[] = "__stub_helper"; 327fe6060f1SDimitry Andric constexpr const char stubs[] = "__stubs"; 328fe6060f1SDimitry Andric constexpr const char swift[] = "__swift"; 329fe6060f1SDimitry Andric constexpr const char symbolTable[] = "__symbol_table"; 330fe6060f1SDimitry Andric constexpr const char textCoalNt[] = "__textcoal_nt"; 331fe6060f1SDimitry Andric constexpr const char text[] = "__text"; 332fe6060f1SDimitry Andric constexpr const char threadPtrs[] = "__thread_ptrs"; 333fe6060f1SDimitry Andric constexpr const char threadVars[] = "__thread_vars"; 334fe6060f1SDimitry Andric constexpr const char unwindInfo[] = "__unwind_info"; 335fe6060f1SDimitry Andric constexpr const char weakBinding[] = "__weak_binding"; 336fe6060f1SDimitry Andric constexpr const char zeroFill[] = "__zerofill"; 337fe6060f1SDimitry Andric 338fe6060f1SDimitry 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