15ffd83dbSDimitry Andric //===- Symbols.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_SYMBOLS_H 105ffd83dbSDimitry Andric #define LLD_MACHO_SYMBOLS_H 115ffd83dbSDimitry Andric 12349cc55cSDimitry Andric #include "Config.h" 13fe6060f1SDimitry Andric #include "InputFiles.h" 145ffd83dbSDimitry Andric #include "Target.h" 15bdd1243dSDimitry Andric 165ffd83dbSDimitry Andric #include "llvm/Object/Archive.h" 17e8d8bef9SDimitry Andric #include "llvm/Support/MathExtras.h" 185ffd83dbSDimitry Andric 195ffd83dbSDimitry Andric namespace lld { 205ffd83dbSDimitry Andric namespace macho { 215ffd83dbSDimitry Andric 22e8d8bef9SDimitry Andric class MachHeaderSection; 235ffd83dbSDimitry Andric 245ffd83dbSDimitry Andric struct StringRefZ { 255ffd83dbSDimitry Andric StringRefZ(const char *s) : data(s), size(-1) {} 265ffd83dbSDimitry Andric StringRefZ(StringRef s) : data(s.data()), size(s.size()) {} 275ffd83dbSDimitry Andric 285ffd83dbSDimitry Andric const char *data; 295ffd83dbSDimitry Andric const uint32_t size; 305ffd83dbSDimitry Andric }; 315ffd83dbSDimitry Andric 325ffd83dbSDimitry Andric class Symbol { 335ffd83dbSDimitry Andric public: 345ffd83dbSDimitry Andric enum Kind { 355ffd83dbSDimitry Andric DefinedKind, 365ffd83dbSDimitry Andric UndefinedKind, 37e8d8bef9SDimitry Andric CommonKind, 385ffd83dbSDimitry Andric DylibKind, 3904eeddc0SDimitry Andric LazyArchiveKind, 4004eeddc0SDimitry Andric LazyObjectKind, 41bdd1243dSDimitry Andric AliasKind, 425ffd83dbSDimitry Andric }; 435ffd83dbSDimitry Andric 44e8d8bef9SDimitry Andric virtual ~Symbol() {} 45e8d8bef9SDimitry Andric 46fe6060f1SDimitry Andric Kind kind() const { return symbolKind; } 475ffd83dbSDimitry Andric 48e8d8bef9SDimitry Andric StringRef getName() const { 49e8d8bef9SDimitry Andric if (nameSize == (uint32_t)-1) 50e8d8bef9SDimitry Andric nameSize = strlen(nameData); 51e8d8bef9SDimitry Andric return {nameData, nameSize}; 52e8d8bef9SDimitry Andric } 535ffd83dbSDimitry Andric 54349cc55cSDimitry Andric bool isLive() const { return used; } 5504eeddc0SDimitry Andric bool isLazy() const { 5604eeddc0SDimitry Andric return symbolKind == LazyArchiveKind || symbolKind == LazyObjectKind; 5704eeddc0SDimitry Andric } 585ffd83dbSDimitry Andric 59fe6060f1SDimitry Andric virtual uint64_t getVA() const { return 0; } 605ffd83dbSDimitry Andric 615f757f3fSDimitry Andric virtual bool isWeakDef() const { return false; } 62e8d8bef9SDimitry Andric 63e8d8bef9SDimitry Andric // Only undefined or dylib symbols can be weak references. A weak reference 64e8d8bef9SDimitry Andric // need not be satisfied at runtime, e.g. due to the symbol not being 65e8d8bef9SDimitry Andric // available on a given target platform. 6681ad6265SDimitry Andric virtual bool isWeakRef() const { return false; } 67e8d8bef9SDimitry Andric 685f757f3fSDimitry Andric virtual bool isTlv() const { return false; } 69e8d8bef9SDimitry Andric 70e8d8bef9SDimitry Andric // Whether this symbol is in the GOT or TLVPointer sections. 71e8d8bef9SDimitry Andric bool isInGot() const { return gotIndex != UINT32_MAX; } 72e8d8bef9SDimitry Andric 73e8d8bef9SDimitry Andric // Whether this symbol is in the StubsSection. 74e8d8bef9SDimitry Andric bool isInStubs() const { return stubsIndex != UINT32_MAX; } 75e8d8bef9SDimitry Andric 76fe6060f1SDimitry Andric uint64_t getStubVA() const; 77bdd1243dSDimitry Andric uint64_t getLazyPtrVA() const; 78fe6060f1SDimitry Andric uint64_t getGotVA() const; 79fe6060f1SDimitry Andric uint64_t getTlvVA() const; 80fe6060f1SDimitry Andric uint64_t resolveBranchVA() const { 81fe6060f1SDimitry Andric assert(isa<Defined>(this) || isa<DylibSymbol>(this)); 82fe6060f1SDimitry Andric return isInStubs() ? getStubVA() : getVA(); 83fe6060f1SDimitry Andric } 84fe6060f1SDimitry Andric uint64_t resolveGotVA() const { return isInGot() ? getGotVA() : getVA(); } 85fe6060f1SDimitry Andric uint64_t resolveTlvVA() const { return isInGot() ? getTlvVA() : getVA(); } 86fe6060f1SDimitry Andric 87e8d8bef9SDimitry Andric // The index of this symbol in the GOT or the TLVPointer section, depending 88e8d8bef9SDimitry Andric // on whether it is a thread-local. A given symbol cannot be referenced by 89e8d8bef9SDimitry Andric // both these sections at once. 905ffd83dbSDimitry Andric uint32_t gotIndex = UINT32_MAX; 9181ad6265SDimitry Andric uint32_t lazyBindOffset = UINT32_MAX; 9281ad6265SDimitry Andric uint32_t stubsHelperIndex = UINT32_MAX; 93e8d8bef9SDimitry Andric uint32_t stubsIndex = UINT32_MAX; 94e8d8bef9SDimitry Andric uint32_t symtabIndex = UINT32_MAX; 95e8d8bef9SDimitry Andric 96fe6060f1SDimitry Andric InputFile *getFile() const { return file; } 97fe6060f1SDimitry Andric 985ffd83dbSDimitry Andric protected: 99fe6060f1SDimitry Andric Symbol(Kind k, StringRefZ name, InputFile *file) 100349cc55cSDimitry Andric : symbolKind(k), nameData(name.data), file(file), nameSize(name.size), 101fe6060f1SDimitry Andric isUsedInRegularObj(!file || isa<ObjFile>(file)), 102fe6060f1SDimitry Andric used(!config->deadStrip) {} 1035ffd83dbSDimitry Andric 1045ffd83dbSDimitry Andric Kind symbolKind; 105e8d8bef9SDimitry Andric const char *nameData; 106fe6060f1SDimitry Andric InputFile *file; 107349cc55cSDimitry Andric mutable uint32_t nameSize; 108fe6060f1SDimitry Andric 109fe6060f1SDimitry Andric public: 110fe6060f1SDimitry Andric // True if this symbol was referenced by a regular (non-bitcode) object. 111fe6060f1SDimitry Andric bool isUsedInRegularObj : 1; 112fe6060f1SDimitry Andric 11381ad6265SDimitry Andric // True if this symbol is used from a live section. 114fe6060f1SDimitry Andric bool used : 1; 1155ffd83dbSDimitry Andric }; 1165ffd83dbSDimitry Andric 1175ffd83dbSDimitry Andric class Defined : public Symbol { 1185ffd83dbSDimitry Andric public: 119fe6060f1SDimitry Andric Defined(StringRefZ name, InputFile *file, InputSection *isec, uint64_t value, 120fe6060f1SDimitry Andric uint64_t size, bool isWeakDef, bool isExternal, bool isPrivateExtern, 12106c3fb27SDimitry Andric bool includeInSymtab, bool isReferencedDynamically, bool noDeadStrip, 12206c3fb27SDimitry Andric bool canOverrideWeakDef = false, bool isWeakDefCanBeHidden = false, 12306c3fb27SDimitry Andric bool interposable = false); 124e8d8bef9SDimitry Andric 125e8d8bef9SDimitry Andric bool isWeakDef() const override { return weakDef; } 126e8d8bef9SDimitry Andric bool isExternalWeakDef() const { 127e8d8bef9SDimitry Andric return isWeakDef() && isExternal() && !privateExtern; 128e8d8bef9SDimitry Andric } 129349cc55cSDimitry Andric bool isTlv() const override; 130e8d8bef9SDimitry Andric 131e8d8bef9SDimitry Andric bool isExternal() const { return external; } 132*0fca6ea1SDimitry Andric bool isAbsolute() const { return originalIsec == nullptr; } 133e8d8bef9SDimitry Andric 134e8d8bef9SDimitry Andric uint64_t getVA() const override; 135e8d8bef9SDimitry Andric 136bdd1243dSDimitry Andric // Returns the object file that this symbol was defined in. This value differs 137bdd1243dSDimitry Andric // from `getFile()` if the symbol originated from a bitcode file. 138bdd1243dSDimitry Andric ObjFile *getObjectFile() const; 139bdd1243dSDimitry Andric 14081ad6265SDimitry Andric std::string getSourceLocation(); 14181ad6265SDimitry Andric 142*0fca6ea1SDimitry Andric // Get the canonical InputSection of the symbol. 143*0fca6ea1SDimitry Andric InputSection *isec() const; 144*0fca6ea1SDimitry Andric 145*0fca6ea1SDimitry Andric // Get the canonical unwind entry of the symbol. 146*0fca6ea1SDimitry Andric ConcatInputSection *unwindEntry() const; 147349cc55cSDimitry Andric 148e8d8bef9SDimitry Andric static bool classof(const Symbol *s) { return s->kind() == DefinedKind; } 1495ffd83dbSDimitry Andric 150349cc55cSDimitry Andric // Place the bitfields first so that they can get placed in the tail padding 151349cc55cSDimitry Andric // of the parent class, on platforms which support it. 152e8d8bef9SDimitry Andric bool overridesWeakDef : 1; 153fe6060f1SDimitry Andric // Whether this symbol should appear in the output binary's export trie. 154e8d8bef9SDimitry Andric bool privateExtern : 1; 155fe6060f1SDimitry Andric // Whether this symbol should appear in the output symbol table. 156fe6060f1SDimitry Andric bool includeInSymtab : 1; 15781ad6265SDimitry Andric // Whether this symbol was folded into a different symbol during ICF. 15881ad6265SDimitry Andric bool wasIdenticalCodeFolded : 1; 159fe6060f1SDimitry Andric // Symbols marked referencedDynamically won't be removed from the output's 160fe6060f1SDimitry Andric // symbol table by tools like strip. In theory, this could be set on arbitrary 161fe6060f1SDimitry Andric // symbols in input object files. In practice, it's used solely for the 162fe6060f1SDimitry Andric // synthetic __mh_execute_header symbol. 163fe6060f1SDimitry Andric // This is information for the static linker, and it's also written to the 164fe6060f1SDimitry Andric // output file's symbol table for tools running later (such as `strip`). 165fe6060f1SDimitry Andric bool referencedDynamically : 1; 166fe6060f1SDimitry Andric // Set on symbols that should not be removed by dead code stripping. 167fe6060f1SDimitry Andric // Set for example on `__attribute__((used))` globals, or on some Objective-C 168fe6060f1SDimitry Andric // metadata. This is information only for the static linker and not written 169fe6060f1SDimitry Andric // to the output. 170fe6060f1SDimitry Andric bool noDeadStrip : 1; 17181ad6265SDimitry Andric // Whether references to this symbol can be interposed at runtime to point to 17281ad6265SDimitry Andric // a different symbol definition (with the same name). For example, if both 17381ad6265SDimitry Andric // dylib A and B define an interposable symbol _foo, and we load A before B at 17481ad6265SDimitry Andric // runtime, then all references to _foo within dylib B will point to the 17581ad6265SDimitry Andric // definition in dylib A. 17681ad6265SDimitry Andric // 17781ad6265SDimitry Andric // Only extern symbols may be interposable. 17881ad6265SDimitry Andric bool interposable : 1; 179e8d8bef9SDimitry Andric 180349cc55cSDimitry Andric bool weakDefCanBeHidden : 1; 181349cc55cSDimitry Andric 182e8d8bef9SDimitry Andric private: 183e8d8bef9SDimitry Andric const bool weakDef : 1; 184e8d8bef9SDimitry Andric const bool external : 1; 185349cc55cSDimitry Andric 186349cc55cSDimitry Andric public: 187*0fca6ea1SDimitry Andric // The native InputSection of the symbol. The symbol may be moved to another 188*0fca6ea1SDimitry Andric // InputSection in which case originalIsec->canonical() will point to the new 189*0fca6ea1SDimitry Andric // InputSection 190*0fca6ea1SDimitry Andric InputSection *originalIsec; 191349cc55cSDimitry Andric // Contains the offset from the containing subsection. Note that this is 192349cc55cSDimitry Andric // different from nlist::n_value, which is the absolute address of the symbol. 193349cc55cSDimitry Andric uint64_t value; 194349cc55cSDimitry Andric // size is only calculated for regular (non-bitcode) symbols. 195349cc55cSDimitry Andric uint64_t size; 19681ad6265SDimitry Andric // This can be a subsection of either __compact_unwind or __eh_frame. 197*0fca6ea1SDimitry Andric ConcatInputSection *originalUnwindEntry = nullptr; 1985ffd83dbSDimitry Andric }; 1995ffd83dbSDimitry Andric 200e8d8bef9SDimitry Andric // This enum does double-duty: as a symbol property, it indicates whether & how 201e8d8bef9SDimitry Andric // a dylib symbol is referenced. As a DylibFile property, it indicates the kind 202e8d8bef9SDimitry Andric // of referenced symbols contained within the file. If there are both weak 203e8d8bef9SDimitry Andric // and strong references to the same file, we will count the file as 204e8d8bef9SDimitry Andric // strongly-referenced. 205e8d8bef9SDimitry Andric enum class RefState : uint8_t { Unreferenced = 0, Weak = 1, Strong = 2 }; 206e8d8bef9SDimitry Andric 2075ffd83dbSDimitry Andric class Undefined : public Symbol { 2085ffd83dbSDimitry Andric public: 209bdd1243dSDimitry Andric Undefined(StringRefZ name, InputFile *file, RefState refState, 210bdd1243dSDimitry Andric bool wasBitcodeSymbol) 211bdd1243dSDimitry Andric : Symbol(UndefinedKind, name, file), refState(refState), 212bdd1243dSDimitry Andric wasBitcodeSymbol(wasBitcodeSymbol) { 213e8d8bef9SDimitry Andric assert(refState != RefState::Unreferenced); 214e8d8bef9SDimitry Andric } 215e8d8bef9SDimitry Andric 216e8d8bef9SDimitry Andric bool isWeakRef() const override { return refState == RefState::Weak; } 2175ffd83dbSDimitry Andric 2185ffd83dbSDimitry Andric static bool classof(const Symbol *s) { return s->kind() == UndefinedKind; } 219e8d8bef9SDimitry Andric 220e8d8bef9SDimitry Andric RefState refState : 2; 221bdd1243dSDimitry Andric bool wasBitcodeSymbol; 222e8d8bef9SDimitry Andric }; 223e8d8bef9SDimitry Andric 224e8d8bef9SDimitry Andric // On Unix, it is traditionally allowed to write variable definitions without 225e8d8bef9SDimitry Andric // initialization expressions (such as "int foo;") to header files. These are 226e8d8bef9SDimitry Andric // called tentative definitions. 227e8d8bef9SDimitry Andric // 228e8d8bef9SDimitry Andric // Using tentative definitions is usually considered a bad practice; you should 229e8d8bef9SDimitry Andric // write only declarations (such as "extern int foo;") to header files. 230e8d8bef9SDimitry Andric // Nevertheless, the linker and the compiler have to do something to support 231e8d8bef9SDimitry Andric // bad code by allowing duplicate definitions for this particular case. 232e8d8bef9SDimitry Andric // 233e8d8bef9SDimitry Andric // The compiler creates common symbols when it sees tentative definitions. 234e8d8bef9SDimitry Andric // (You can suppress this behavior and let the compiler create a regular 235e8d8bef9SDimitry Andric // defined symbol by passing -fno-common. -fno-common is the default in clang 236e8d8bef9SDimitry Andric // as of LLVM 11.0.) When linking the final binary, if there are remaining 237e8d8bef9SDimitry Andric // common symbols after name resolution is complete, the linker converts them 238e8d8bef9SDimitry Andric // to regular defined symbols in a __common section. 239e8d8bef9SDimitry Andric class CommonSymbol : public Symbol { 240e8d8bef9SDimitry Andric public: 241e8d8bef9SDimitry Andric CommonSymbol(StringRefZ name, InputFile *file, uint64_t size, uint32_t align, 242e8d8bef9SDimitry Andric bool isPrivateExtern) 243fe6060f1SDimitry Andric : Symbol(CommonKind, name, file), size(size), 244e8d8bef9SDimitry Andric align(align != 1 ? align : llvm::PowerOf2Ceil(size)), 245e8d8bef9SDimitry Andric privateExtern(isPrivateExtern) { 246e8d8bef9SDimitry Andric // TODO: cap maximum alignment 247e8d8bef9SDimitry Andric } 248e8d8bef9SDimitry Andric 249e8d8bef9SDimitry Andric static bool classof(const Symbol *s) { return s->kind() == CommonKind; } 250e8d8bef9SDimitry Andric 251e8d8bef9SDimitry Andric const uint64_t size; 252e8d8bef9SDimitry Andric const uint32_t align; 253e8d8bef9SDimitry Andric const bool privateExtern; 2545ffd83dbSDimitry Andric }; 2555ffd83dbSDimitry Andric 2565ffd83dbSDimitry Andric class DylibSymbol : public Symbol { 2575ffd83dbSDimitry Andric public: 258e8d8bef9SDimitry Andric DylibSymbol(DylibFile *file, StringRefZ name, bool isWeakDef, 259e8d8bef9SDimitry Andric RefState refState, bool isTlv) 26006c3fb27SDimitry Andric : Symbol(DylibKind, name, file), shouldReexport(false), 26106c3fb27SDimitry Andric refState(refState), weakDef(isWeakDef), tlv(isTlv) { 262fe6060f1SDimitry Andric if (file && refState > RefState::Unreferenced) 263fe6060f1SDimitry Andric file->numReferencedSymbols++; 264fe6060f1SDimitry Andric } 265e8d8bef9SDimitry Andric 266fe6060f1SDimitry Andric uint64_t getVA() const override; 267e8d8bef9SDimitry Andric bool isWeakDef() const override { return weakDef; } 2684824e7fdSDimitry Andric 2694824e7fdSDimitry Andric // Symbols from weak libraries/frameworks are also weakly-referenced. 2704824e7fdSDimitry Andric bool isWeakRef() const override { 2714824e7fdSDimitry Andric return refState == RefState::Weak || 2724824e7fdSDimitry Andric (file && getFile()->umbrella->forceWeakImport); 2734824e7fdSDimitry Andric } 274e8d8bef9SDimitry Andric bool isReferenced() const { return refState != RefState::Unreferenced; } 275e8d8bef9SDimitry Andric bool isTlv() const override { return tlv; } 276fe6060f1SDimitry Andric bool isDynamicLookup() const { return file == nullptr; } 277e8d8bef9SDimitry Andric bool hasStubsHelper() const { return stubsHelperIndex != UINT32_MAX; } 2785ffd83dbSDimitry Andric 279fe6060f1SDimitry Andric DylibFile *getFile() const { 280fe6060f1SDimitry Andric assert(!isDynamicLookup()); 281fe6060f1SDimitry Andric return cast<DylibFile>(file); 282fe6060f1SDimitry Andric } 283fe6060f1SDimitry Andric 2845ffd83dbSDimitry Andric static bool classof(const Symbol *s) { return s->kind() == DylibKind; } 2855ffd83dbSDimitry Andric 286fe6060f1SDimitry Andric RefState getRefState() const { return refState; } 287fe6060f1SDimitry Andric 288fe6060f1SDimitry Andric void reference(RefState newState) { 289fe6060f1SDimitry Andric assert(newState > RefState::Unreferenced); 290fe6060f1SDimitry Andric if (refState == RefState::Unreferenced && file) 291fe6060f1SDimitry Andric getFile()->numReferencedSymbols++; 292fe6060f1SDimitry Andric refState = std::max(refState, newState); 293fe6060f1SDimitry Andric } 294fe6060f1SDimitry Andric 295fe6060f1SDimitry Andric void unreference() { 296fe6060f1SDimitry Andric // dynamic_lookup symbols have no file. 297fe6060f1SDimitry Andric if (refState > RefState::Unreferenced && file) { 298fe6060f1SDimitry Andric assert(getFile()->numReferencedSymbols > 0); 299fe6060f1SDimitry Andric getFile()->numReferencedSymbols--; 300fe6060f1SDimitry Andric } 301fe6060f1SDimitry Andric } 302e8d8bef9SDimitry Andric 30306c3fb27SDimitry Andric bool shouldReexport : 1; 304e8d8bef9SDimitry Andric private: 305fe6060f1SDimitry Andric RefState refState : 2; 306e8d8bef9SDimitry Andric const bool weakDef : 1; 307e8d8bef9SDimitry Andric const bool tlv : 1; 3085ffd83dbSDimitry Andric }; 3095ffd83dbSDimitry Andric 31004eeddc0SDimitry Andric class LazyArchive : public Symbol { 3115ffd83dbSDimitry Andric public: 31204eeddc0SDimitry Andric LazyArchive(ArchiveFile *file, const llvm::object::Archive::Symbol &sym) 31304eeddc0SDimitry Andric : Symbol(LazyArchiveKind, sym.getName(), file), sym(sym) {} 314fe6060f1SDimitry Andric 315fe6060f1SDimitry Andric ArchiveFile *getFile() const { return cast<ArchiveFile>(file); } 316fe6060f1SDimitry Andric void fetchArchiveMember(); 3175ffd83dbSDimitry Andric 31804eeddc0SDimitry Andric static bool classof(const Symbol *s) { return s->kind() == LazyArchiveKind; } 3195ffd83dbSDimitry Andric 3205ffd83dbSDimitry Andric private: 3215ffd83dbSDimitry Andric const llvm::object::Archive::Symbol sym; 3225ffd83dbSDimitry Andric }; 3235ffd83dbSDimitry Andric 32404eeddc0SDimitry Andric // A defined symbol in an ObjFile/BitcodeFile surrounded by --start-lib and 32504eeddc0SDimitry Andric // --end-lib. 32604eeddc0SDimitry Andric class LazyObject : public Symbol { 32704eeddc0SDimitry Andric public: 32804eeddc0SDimitry Andric LazyObject(InputFile &file, StringRef name) 32904eeddc0SDimitry Andric : Symbol(LazyObjectKind, name, &file) { 33004eeddc0SDimitry Andric isUsedInRegularObj = false; 33104eeddc0SDimitry Andric } 33204eeddc0SDimitry Andric 33304eeddc0SDimitry Andric static bool classof(const Symbol *s) { return s->kind() == LazyObjectKind; } 33404eeddc0SDimitry Andric }; 33504eeddc0SDimitry Andric 336bdd1243dSDimitry Andric // Represents N_INDR symbols. Note that if we are given valid, linkable inputs, 337bdd1243dSDimitry Andric // then all AliasSymbol instances will be converted into one of the other Symbol 338bdd1243dSDimitry Andric // types after `createAliases()` runs. 339bdd1243dSDimitry Andric class AliasSymbol final : public Symbol { 340bdd1243dSDimitry Andric public: 341bdd1243dSDimitry Andric AliasSymbol(InputFile *file, StringRef name, StringRef aliasedName, 342bdd1243dSDimitry Andric bool isPrivateExtern) 343bdd1243dSDimitry Andric : Symbol(AliasKind, name, file), privateExtern(isPrivateExtern), 344bdd1243dSDimitry Andric aliasedName(aliasedName) {} 345bdd1243dSDimitry Andric 346bdd1243dSDimitry Andric StringRef getAliasedName() const { return aliasedName; } 347bdd1243dSDimitry Andric 348bdd1243dSDimitry Andric static bool classof(const Symbol *s) { return s->kind() == AliasKind; } 349bdd1243dSDimitry Andric 350bdd1243dSDimitry Andric const bool privateExtern; 351bdd1243dSDimitry Andric 352bdd1243dSDimitry Andric private: 353bdd1243dSDimitry Andric StringRef aliasedName; 354bdd1243dSDimitry Andric }; 355bdd1243dSDimitry Andric 3565ffd83dbSDimitry Andric union SymbolUnion { 3575ffd83dbSDimitry Andric alignas(Defined) char a[sizeof(Defined)]; 3585ffd83dbSDimitry Andric alignas(Undefined) char b[sizeof(Undefined)]; 359e8d8bef9SDimitry Andric alignas(CommonSymbol) char c[sizeof(CommonSymbol)]; 360e8d8bef9SDimitry Andric alignas(DylibSymbol) char d[sizeof(DylibSymbol)]; 36104eeddc0SDimitry Andric alignas(LazyArchive) char e[sizeof(LazyArchive)]; 36204eeddc0SDimitry Andric alignas(LazyObject) char f[sizeof(LazyObject)]; 363bdd1243dSDimitry Andric alignas(AliasSymbol) char g[sizeof(AliasSymbol)]; 3645ffd83dbSDimitry Andric }; 3655ffd83dbSDimitry Andric 3665ffd83dbSDimitry Andric template <typename T, typename... ArgT> 367e8d8bef9SDimitry Andric T *replaceSymbol(Symbol *s, ArgT &&...arg) { 3685ffd83dbSDimitry Andric static_assert(sizeof(T) <= sizeof(SymbolUnion), "SymbolUnion too small"); 3695ffd83dbSDimitry Andric static_assert(alignof(T) <= alignof(SymbolUnion), 3705ffd83dbSDimitry Andric "SymbolUnion not aligned enough"); 3715ffd83dbSDimitry Andric assert(static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr && 3725ffd83dbSDimitry Andric "Not a Symbol"); 3735ffd83dbSDimitry Andric 374fe6060f1SDimitry Andric bool isUsedInRegularObj = s->isUsedInRegularObj; 375fe6060f1SDimitry Andric bool used = s->used; 376fe6060f1SDimitry Andric T *sym = new (s) T(std::forward<ArgT>(arg)...); 377fe6060f1SDimitry Andric sym->isUsedInRegularObj |= isUsedInRegularObj; 378fe6060f1SDimitry Andric sym->used |= used; 379fe6060f1SDimitry Andric return sym; 3805ffd83dbSDimitry Andric } 3815ffd83dbSDimitry Andric 382bdd1243dSDimitry Andric // Can a symbol's address only be resolved at runtime? 383bdd1243dSDimitry Andric inline bool needsBinding(const Symbol *sym) { 384bdd1243dSDimitry Andric if (isa<DylibSymbol>(sym)) 385bdd1243dSDimitry Andric return true; 386bdd1243dSDimitry Andric if (const auto *defined = dyn_cast<Defined>(sym)) 387bdd1243dSDimitry Andric return defined->isExternalWeakDef() || defined->interposable; 388bdd1243dSDimitry Andric return false; 389bdd1243dSDimitry Andric } 39006c3fb27SDimitry Andric 39106c3fb27SDimitry Andric // Symbols with `l` or `L` as a prefix are linker-private and never appear in 39206c3fb27SDimitry Andric // the output. 39306c3fb27SDimitry Andric inline bool isPrivateLabel(StringRef name) { 39406c3fb27SDimitry Andric return name.starts_with("l") || name.starts_with("L"); 39506c3fb27SDimitry Andric } 3965ffd83dbSDimitry Andric } // namespace macho 3975ffd83dbSDimitry Andric 3985ffd83dbSDimitry Andric std::string toString(const macho::Symbol &); 399e8d8bef9SDimitry Andric std::string toMachOString(const llvm::object::Archive::Symbol &); 400e8d8bef9SDimitry Andric 4015ffd83dbSDimitry Andric } // namespace lld 4025ffd83dbSDimitry Andric 4035ffd83dbSDimitry Andric #endif 404