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 {
StringRefZStringRefZ255ffd83dbSDimitry Andric StringRefZ(const char *s) : data(s), size(-1) {}
StringRefZStringRefZ265ffd83dbSDimitry 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
~Symbol()44e8d8bef9SDimitry Andric virtual ~Symbol() {}
45e8d8bef9SDimitry Andric
kind()46fe6060f1SDimitry Andric Kind kind() const { return symbolKind; }
475ffd83dbSDimitry Andric
getName()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
isLive()54349cc55cSDimitry Andric bool isLive() const { return used; }
isLazy()5504eeddc0SDimitry Andric bool isLazy() const {
5604eeddc0SDimitry Andric return symbolKind == LazyArchiveKind || symbolKind == LazyObjectKind;
5704eeddc0SDimitry Andric }
585ffd83dbSDimitry Andric
getVA()59fe6060f1SDimitry Andric virtual uint64_t getVA() const { return 0; }
605ffd83dbSDimitry Andric
isWeakDef()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.
isWeakRef()6681ad6265SDimitry Andric virtual bool isWeakRef() const { return false; }
67e8d8bef9SDimitry Andric
isTlv()685f757f3fSDimitry Andric virtual bool isTlv() const { return false; }
69e8d8bef9SDimitry Andric
70e8d8bef9SDimitry Andric // Whether this symbol is in the GOT or TLVPointer sections.
isInGot()71e8d8bef9SDimitry Andric bool isInGot() const { return gotIndex != UINT32_MAX; }
72e8d8bef9SDimitry Andric
73e8d8bef9SDimitry Andric // Whether this symbol is in the StubsSection.
isInStubs()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;
resolveBranchVA()80fe6060f1SDimitry Andric uint64_t resolveBranchVA() const {
81fe6060f1SDimitry Andric assert(isa<Defined>(this) || isa<DylibSymbol>(this));
82fe6060f1SDimitry Andric return isInStubs() ? getStubVA() : getVA();
83fe6060f1SDimitry Andric }
resolveGotVA()84fe6060f1SDimitry Andric uint64_t resolveGotVA() const { return isInGot() ? getGotVA() : getVA(); }
resolveTlvVA()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
getFile()96fe6060f1SDimitry Andric InputFile *getFile() const { return file; }
97fe6060f1SDimitry Andric
985ffd83dbSDimitry Andric protected:
Symbol(Kind k,StringRefZ name,InputFile * file)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
isWeakDef()125e8d8bef9SDimitry Andric bool isWeakDef() const override { return weakDef; }
isExternalWeakDef()126e8d8bef9SDimitry Andric bool isExternalWeakDef() const {
127e8d8bef9SDimitry Andric return isWeakDef() && isExternal() && !privateExtern;
128e8d8bef9SDimitry Andric }
129349cc55cSDimitry Andric bool isTlv() const override;
130e8d8bef9SDimitry Andric
isExternal()131e8d8bef9SDimitry Andric bool isExternal() const { return external; }
isAbsolute()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
classof(const Symbol * s)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:
Undefined(StringRefZ name,InputFile * file,RefState refState,bool wasBitcodeSymbol)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
isWeakRef()216e8d8bef9SDimitry Andric bool isWeakRef() const override { return refState == RefState::Weak; }
2175ffd83dbSDimitry Andric
classof(const Symbol * s)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:
CommonSymbol(StringRefZ name,InputFile * file,uint64_t size,uint32_t align,bool isPrivateExtern)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
classof(const Symbol * s)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:
DylibSymbol(DylibFile * file,StringRefZ name,bool isWeakDef,RefState refState,bool isTlv)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;
isWeakDef()267e8d8bef9SDimitry Andric bool isWeakDef() const override { return weakDef; }
2684824e7fdSDimitry Andric
2694824e7fdSDimitry Andric // Symbols from weak libraries/frameworks are also weakly-referenced.
isWeakRef()2704824e7fdSDimitry Andric bool isWeakRef() const override {
2714824e7fdSDimitry Andric return refState == RefState::Weak ||
2724824e7fdSDimitry Andric (file && getFile()->umbrella->forceWeakImport);
2734824e7fdSDimitry Andric }
isReferenced()274e8d8bef9SDimitry Andric bool isReferenced() const { return refState != RefState::Unreferenced; }
isTlv()275e8d8bef9SDimitry Andric bool isTlv() const override { return tlv; }
isDynamicLookup()276fe6060f1SDimitry Andric bool isDynamicLookup() const { return file == nullptr; }
hasStubsHelper()277e8d8bef9SDimitry Andric bool hasStubsHelper() const { return stubsHelperIndex != UINT32_MAX; }
2785ffd83dbSDimitry Andric
getFile()279fe6060f1SDimitry Andric DylibFile *getFile() const {
280fe6060f1SDimitry Andric assert(!isDynamicLookup());
281fe6060f1SDimitry Andric return cast<DylibFile>(file);
282fe6060f1SDimitry Andric }
283fe6060f1SDimitry Andric
classof(const Symbol * s)2845ffd83dbSDimitry Andric static bool classof(const Symbol *s) { return s->kind() == DylibKind; }
2855ffd83dbSDimitry Andric
getRefState()286fe6060f1SDimitry Andric RefState getRefState() const { return refState; }
287fe6060f1SDimitry Andric
reference(RefState newState)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
unreference()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:
LazyArchive(ArchiveFile * file,const llvm::object::Archive::Symbol & sym)31204eeddc0SDimitry Andric LazyArchive(ArchiveFile *file, const llvm::object::Archive::Symbol &sym)
31304eeddc0SDimitry Andric : Symbol(LazyArchiveKind, sym.getName(), file), sym(sym) {}
314fe6060f1SDimitry Andric
getFile()315fe6060f1SDimitry Andric ArchiveFile *getFile() const { return cast<ArchiveFile>(file); }
316fe6060f1SDimitry Andric void fetchArchiveMember();
3175ffd83dbSDimitry Andric
classof(const Symbol * s)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:
LazyObject(InputFile & file,StringRef name)32804eeddc0SDimitry Andric LazyObject(InputFile &file, StringRef name)
32904eeddc0SDimitry Andric : Symbol(LazyObjectKind, name, &file) {
33004eeddc0SDimitry Andric isUsedInRegularObj = false;
33104eeddc0SDimitry Andric }
33204eeddc0SDimitry Andric
classof(const Symbol * s)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:
AliasSymbol(InputFile * file,StringRef name,StringRef aliasedName,bool isPrivateExtern)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
getAliasedName()346bdd1243dSDimitry Andric StringRef getAliasedName() const { return aliasedName; }
347bdd1243dSDimitry Andric
classof(const Symbol * s)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>
replaceSymbol(Symbol * s,ArgT &&...arg)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?
needsBinding(const Symbol * sym)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.
isPrivateLabel(StringRef name)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