xref: /freebsd/contrib/llvm-project/lld/MachO/Symbols.h (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
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"
15*bdd1243dSDimitry 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,
41*bdd1243dSDimitry 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 
61e8d8bef9SDimitry Andric   virtual bool isWeakDef() const { llvm_unreachable("cannot be weak def"); }
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 
68e8d8bef9SDimitry Andric   virtual bool isTlv() const { llvm_unreachable("cannot be TLV"); }
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;
77*bdd1243dSDimitry 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,
12181ad6265SDimitry Andric           bool includeInSymtab, bool isThumb, bool isReferencedDynamically,
12281ad6265SDimitry Andric           bool noDeadStrip, bool canOverrideWeakDef = false,
12381ad6265SDimitry Andric           bool isWeakDefCanBeHidden = false, 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; }
132e8d8bef9SDimitry Andric   bool isAbsolute() const { return isec == nullptr; }
133e8d8bef9SDimitry Andric 
134e8d8bef9SDimitry Andric   uint64_t getVA() const override;
135e8d8bef9SDimitry Andric 
136*bdd1243dSDimitry Andric   // Returns the object file that this symbol was defined in. This value differs
137*bdd1243dSDimitry Andric   // from `getFile()` if the symbol originated from a bitcode file.
138*bdd1243dSDimitry Andric   ObjFile *getObjectFile() const;
139*bdd1243dSDimitry Andric 
14081ad6265SDimitry Andric   std::string getSourceLocation();
14181ad6265SDimitry Andric 
142349cc55cSDimitry Andric   // Ensure this symbol's pointers to InputSections point to their canonical
143349cc55cSDimitry Andric   // copies.
144349cc55cSDimitry Andric   void canonicalize();
145349cc55cSDimitry Andric 
146e8d8bef9SDimitry Andric   static bool classof(const Symbol *s) { return s->kind() == DefinedKind; }
1475ffd83dbSDimitry Andric 
148349cc55cSDimitry Andric   // Place the bitfields first so that they can get placed in the tail padding
149349cc55cSDimitry Andric   // of the parent class, on platforms which support it.
150e8d8bef9SDimitry Andric   bool overridesWeakDef : 1;
151fe6060f1SDimitry Andric   // Whether this symbol should appear in the output binary's export trie.
152e8d8bef9SDimitry Andric   bool privateExtern : 1;
153fe6060f1SDimitry Andric   // Whether this symbol should appear in the output symbol table.
154fe6060f1SDimitry Andric   bool includeInSymtab : 1;
15581ad6265SDimitry Andric   // Whether this symbol was folded into a different symbol during ICF.
15681ad6265SDimitry Andric   bool wasIdenticalCodeFolded : 1;
157fe6060f1SDimitry Andric   // Only relevant when compiling for Thumb-supporting arm32 archs.
158fe6060f1SDimitry Andric   bool thumb : 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:
187349cc55cSDimitry Andric   InputSection *isec;
188349cc55cSDimitry Andric   // Contains the offset from the containing subsection. Note that this is
189349cc55cSDimitry Andric   // different from nlist::n_value, which is the absolute address of the symbol.
190349cc55cSDimitry Andric   uint64_t value;
191349cc55cSDimitry Andric   // size is only calculated for regular (non-bitcode) symbols.
192349cc55cSDimitry Andric   uint64_t size;
19381ad6265SDimitry Andric   // This can be a subsection of either __compact_unwind or __eh_frame.
194349cc55cSDimitry Andric   ConcatInputSection *unwindEntry = nullptr;
1955ffd83dbSDimitry Andric };
1965ffd83dbSDimitry Andric 
197e8d8bef9SDimitry Andric // This enum does double-duty: as a symbol property, it indicates whether & how
198e8d8bef9SDimitry Andric // a dylib symbol is referenced. As a DylibFile property, it indicates the kind
199e8d8bef9SDimitry Andric // of referenced symbols contained within the file. If there are both weak
200e8d8bef9SDimitry Andric // and strong references to the same file, we will count the file as
201e8d8bef9SDimitry Andric // strongly-referenced.
202e8d8bef9SDimitry Andric enum class RefState : uint8_t { Unreferenced = 0, Weak = 1, Strong = 2 };
203e8d8bef9SDimitry Andric 
2045ffd83dbSDimitry Andric class Undefined : public Symbol {
2055ffd83dbSDimitry Andric public:
206*bdd1243dSDimitry Andric   Undefined(StringRefZ name, InputFile *file, RefState refState,
207*bdd1243dSDimitry Andric             bool wasBitcodeSymbol)
208*bdd1243dSDimitry Andric       : Symbol(UndefinedKind, name, file), refState(refState),
209*bdd1243dSDimitry Andric         wasBitcodeSymbol(wasBitcodeSymbol) {
210e8d8bef9SDimitry Andric     assert(refState != RefState::Unreferenced);
211e8d8bef9SDimitry Andric   }
212e8d8bef9SDimitry Andric 
213e8d8bef9SDimitry Andric   bool isWeakRef() const override { return refState == RefState::Weak; }
2145ffd83dbSDimitry Andric 
2155ffd83dbSDimitry Andric   static bool classof(const Symbol *s) { return s->kind() == UndefinedKind; }
216e8d8bef9SDimitry Andric 
217e8d8bef9SDimitry Andric   RefState refState : 2;
218*bdd1243dSDimitry Andric   bool wasBitcodeSymbol;
219e8d8bef9SDimitry Andric };
220e8d8bef9SDimitry Andric 
221e8d8bef9SDimitry Andric // On Unix, it is traditionally allowed to write variable definitions without
222e8d8bef9SDimitry Andric // initialization expressions (such as "int foo;") to header files. These are
223e8d8bef9SDimitry Andric // called tentative definitions.
224e8d8bef9SDimitry Andric //
225e8d8bef9SDimitry Andric // Using tentative definitions is usually considered a bad practice; you should
226e8d8bef9SDimitry Andric // write only declarations (such as "extern int foo;") to header files.
227e8d8bef9SDimitry Andric // Nevertheless, the linker and the compiler have to do something to support
228e8d8bef9SDimitry Andric // bad code by allowing duplicate definitions for this particular case.
229e8d8bef9SDimitry Andric //
230e8d8bef9SDimitry Andric // The compiler creates common symbols when it sees tentative definitions.
231e8d8bef9SDimitry Andric // (You can suppress this behavior and let the compiler create a regular
232e8d8bef9SDimitry Andric // defined symbol by passing -fno-common. -fno-common is the default in clang
233e8d8bef9SDimitry Andric // as of LLVM 11.0.) When linking the final binary, if there are remaining
234e8d8bef9SDimitry Andric // common symbols after name resolution is complete, the linker converts them
235e8d8bef9SDimitry Andric // to regular defined symbols in a __common section.
236e8d8bef9SDimitry Andric class CommonSymbol : public Symbol {
237e8d8bef9SDimitry Andric public:
238e8d8bef9SDimitry Andric   CommonSymbol(StringRefZ name, InputFile *file, uint64_t size, uint32_t align,
239e8d8bef9SDimitry Andric                bool isPrivateExtern)
240fe6060f1SDimitry Andric       : Symbol(CommonKind, name, file), size(size),
241e8d8bef9SDimitry Andric         align(align != 1 ? align : llvm::PowerOf2Ceil(size)),
242e8d8bef9SDimitry Andric         privateExtern(isPrivateExtern) {
243e8d8bef9SDimitry Andric     // TODO: cap maximum alignment
244e8d8bef9SDimitry Andric   }
245e8d8bef9SDimitry Andric 
246e8d8bef9SDimitry Andric   static bool classof(const Symbol *s) { return s->kind() == CommonKind; }
247e8d8bef9SDimitry Andric 
248e8d8bef9SDimitry Andric   const uint64_t size;
249e8d8bef9SDimitry Andric   const uint32_t align;
250e8d8bef9SDimitry Andric   const bool privateExtern;
2515ffd83dbSDimitry Andric };
2525ffd83dbSDimitry Andric 
2535ffd83dbSDimitry Andric class DylibSymbol : public Symbol {
2545ffd83dbSDimitry Andric public:
255e8d8bef9SDimitry Andric   DylibSymbol(DylibFile *file, StringRefZ name, bool isWeakDef,
256e8d8bef9SDimitry Andric               RefState refState, bool isTlv)
257fe6060f1SDimitry Andric       : Symbol(DylibKind, name, file), refState(refState), weakDef(isWeakDef),
258fe6060f1SDimitry Andric         tlv(isTlv) {
259fe6060f1SDimitry Andric     if (file && refState > RefState::Unreferenced)
260fe6060f1SDimitry Andric       file->numReferencedSymbols++;
261fe6060f1SDimitry Andric   }
262e8d8bef9SDimitry Andric 
263fe6060f1SDimitry Andric   uint64_t getVA() const override;
264e8d8bef9SDimitry Andric   bool isWeakDef() const override { return weakDef; }
2654824e7fdSDimitry Andric 
2664824e7fdSDimitry Andric   // Symbols from weak libraries/frameworks are also weakly-referenced.
2674824e7fdSDimitry Andric   bool isWeakRef() const override {
2684824e7fdSDimitry Andric     return refState == RefState::Weak ||
2694824e7fdSDimitry Andric            (file && getFile()->umbrella->forceWeakImport);
2704824e7fdSDimitry Andric   }
271e8d8bef9SDimitry Andric   bool isReferenced() const { return refState != RefState::Unreferenced; }
272e8d8bef9SDimitry Andric   bool isTlv() const override { return tlv; }
273fe6060f1SDimitry Andric   bool isDynamicLookup() const { return file == nullptr; }
274e8d8bef9SDimitry Andric   bool hasStubsHelper() const { return stubsHelperIndex != UINT32_MAX; }
2755ffd83dbSDimitry Andric 
276fe6060f1SDimitry Andric   DylibFile *getFile() const {
277fe6060f1SDimitry Andric     assert(!isDynamicLookup());
278fe6060f1SDimitry Andric     return cast<DylibFile>(file);
279fe6060f1SDimitry Andric   }
280fe6060f1SDimitry Andric 
2815ffd83dbSDimitry Andric   static bool classof(const Symbol *s) { return s->kind() == DylibKind; }
2825ffd83dbSDimitry Andric 
283fe6060f1SDimitry Andric   RefState getRefState() const { return refState; }
284fe6060f1SDimitry Andric 
285fe6060f1SDimitry Andric   void reference(RefState newState) {
286fe6060f1SDimitry Andric     assert(newState > RefState::Unreferenced);
287fe6060f1SDimitry Andric     if (refState == RefState::Unreferenced && file)
288fe6060f1SDimitry Andric       getFile()->numReferencedSymbols++;
289fe6060f1SDimitry Andric     refState = std::max(refState, newState);
290fe6060f1SDimitry Andric   }
291fe6060f1SDimitry Andric 
292fe6060f1SDimitry Andric   void unreference() {
293fe6060f1SDimitry Andric     // dynamic_lookup symbols have no file.
294fe6060f1SDimitry Andric     if (refState > RefState::Unreferenced && file) {
295fe6060f1SDimitry Andric       assert(getFile()->numReferencedSymbols > 0);
296fe6060f1SDimitry Andric       getFile()->numReferencedSymbols--;
297fe6060f1SDimitry Andric     }
298fe6060f1SDimitry Andric   }
299e8d8bef9SDimitry Andric 
300e8d8bef9SDimitry Andric private:
301fe6060f1SDimitry Andric   RefState refState : 2;
302e8d8bef9SDimitry Andric   const bool weakDef : 1;
303e8d8bef9SDimitry Andric   const bool tlv : 1;
3045ffd83dbSDimitry Andric };
3055ffd83dbSDimitry Andric 
30604eeddc0SDimitry Andric class LazyArchive : public Symbol {
3075ffd83dbSDimitry Andric public:
30804eeddc0SDimitry Andric   LazyArchive(ArchiveFile *file, const llvm::object::Archive::Symbol &sym)
30904eeddc0SDimitry Andric       : Symbol(LazyArchiveKind, sym.getName(), file), sym(sym) {}
310fe6060f1SDimitry Andric 
311fe6060f1SDimitry Andric   ArchiveFile *getFile() const { return cast<ArchiveFile>(file); }
312fe6060f1SDimitry Andric   void fetchArchiveMember();
3135ffd83dbSDimitry Andric 
31404eeddc0SDimitry Andric   static bool classof(const Symbol *s) { return s->kind() == LazyArchiveKind; }
3155ffd83dbSDimitry Andric 
3165ffd83dbSDimitry Andric private:
3175ffd83dbSDimitry Andric   const llvm::object::Archive::Symbol sym;
3185ffd83dbSDimitry Andric };
3195ffd83dbSDimitry Andric 
32004eeddc0SDimitry Andric // A defined symbol in an ObjFile/BitcodeFile surrounded by --start-lib and
32104eeddc0SDimitry Andric // --end-lib.
32204eeddc0SDimitry Andric class LazyObject : public Symbol {
32304eeddc0SDimitry Andric public:
32404eeddc0SDimitry Andric   LazyObject(InputFile &file, StringRef name)
32504eeddc0SDimitry Andric       : Symbol(LazyObjectKind, name, &file) {
32604eeddc0SDimitry Andric     isUsedInRegularObj = false;
32704eeddc0SDimitry Andric   }
32804eeddc0SDimitry Andric 
32904eeddc0SDimitry Andric   static bool classof(const Symbol *s) { return s->kind() == LazyObjectKind; }
33004eeddc0SDimitry Andric };
33104eeddc0SDimitry Andric 
332*bdd1243dSDimitry Andric // Represents N_INDR symbols. Note that if we are given valid, linkable inputs,
333*bdd1243dSDimitry Andric // then all AliasSymbol instances will be converted into one of the other Symbol
334*bdd1243dSDimitry Andric // types after `createAliases()` runs.
335*bdd1243dSDimitry Andric class AliasSymbol final : public Symbol {
336*bdd1243dSDimitry Andric public:
337*bdd1243dSDimitry Andric   AliasSymbol(InputFile *file, StringRef name, StringRef aliasedName,
338*bdd1243dSDimitry Andric               bool isPrivateExtern)
339*bdd1243dSDimitry Andric       : Symbol(AliasKind, name, file), privateExtern(isPrivateExtern),
340*bdd1243dSDimitry Andric         aliasedName(aliasedName) {}
341*bdd1243dSDimitry Andric 
342*bdd1243dSDimitry Andric   StringRef getAliasedName() const { return aliasedName; }
343*bdd1243dSDimitry Andric 
344*bdd1243dSDimitry Andric   static bool classof(const Symbol *s) { return s->kind() == AliasKind; }
345*bdd1243dSDimitry Andric 
346*bdd1243dSDimitry Andric   const bool privateExtern;
347*bdd1243dSDimitry Andric 
348*bdd1243dSDimitry Andric private:
349*bdd1243dSDimitry Andric   StringRef aliasedName;
350*bdd1243dSDimitry Andric };
351*bdd1243dSDimitry Andric 
3525ffd83dbSDimitry Andric union SymbolUnion {
3535ffd83dbSDimitry Andric   alignas(Defined) char a[sizeof(Defined)];
3545ffd83dbSDimitry Andric   alignas(Undefined) char b[sizeof(Undefined)];
355e8d8bef9SDimitry Andric   alignas(CommonSymbol) char c[sizeof(CommonSymbol)];
356e8d8bef9SDimitry Andric   alignas(DylibSymbol) char d[sizeof(DylibSymbol)];
35704eeddc0SDimitry Andric   alignas(LazyArchive) char e[sizeof(LazyArchive)];
35804eeddc0SDimitry Andric   alignas(LazyObject) char f[sizeof(LazyObject)];
359*bdd1243dSDimitry Andric   alignas(AliasSymbol) char g[sizeof(AliasSymbol)];
3605ffd83dbSDimitry Andric };
3615ffd83dbSDimitry Andric 
3625ffd83dbSDimitry Andric template <typename T, typename... ArgT>
363e8d8bef9SDimitry Andric T *replaceSymbol(Symbol *s, ArgT &&...arg) {
3645ffd83dbSDimitry Andric   static_assert(sizeof(T) <= sizeof(SymbolUnion), "SymbolUnion too small");
3655ffd83dbSDimitry Andric   static_assert(alignof(T) <= alignof(SymbolUnion),
3665ffd83dbSDimitry Andric                 "SymbolUnion not aligned enough");
3675ffd83dbSDimitry Andric   assert(static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr &&
3685ffd83dbSDimitry Andric          "Not a Symbol");
3695ffd83dbSDimitry Andric 
370fe6060f1SDimitry Andric   bool isUsedInRegularObj = s->isUsedInRegularObj;
371fe6060f1SDimitry Andric   bool used = s->used;
372fe6060f1SDimitry Andric   T *sym = new (s) T(std::forward<ArgT>(arg)...);
373fe6060f1SDimitry Andric   sym->isUsedInRegularObj |= isUsedInRegularObj;
374fe6060f1SDimitry Andric   sym->used |= used;
375fe6060f1SDimitry Andric   return sym;
3765ffd83dbSDimitry Andric }
3775ffd83dbSDimitry Andric 
378*bdd1243dSDimitry Andric // Can a symbol's address only be resolved at runtime?
379*bdd1243dSDimitry Andric inline bool needsBinding(const Symbol *sym) {
380*bdd1243dSDimitry Andric   if (isa<DylibSymbol>(sym))
381*bdd1243dSDimitry Andric     return true;
382*bdd1243dSDimitry Andric   if (const auto *defined = dyn_cast<Defined>(sym))
383*bdd1243dSDimitry Andric     return defined->isExternalWeakDef() || defined->interposable;
384*bdd1243dSDimitry Andric   return false;
385*bdd1243dSDimitry Andric }
3865ffd83dbSDimitry Andric } // namespace macho
3875ffd83dbSDimitry Andric 
3885ffd83dbSDimitry Andric std::string toString(const macho::Symbol &);
389e8d8bef9SDimitry Andric std::string toMachOString(const llvm::object::Archive::Symbol &);
390e8d8bef9SDimitry Andric 
3915ffd83dbSDimitry Andric } // namespace lld
3925ffd83dbSDimitry Andric 
3935ffd83dbSDimitry Andric #endif
394