15ffd83dbSDimitry Andric //===- Symbols.cpp --------------------------------------------------------===//
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 #include "Symbols.h"
105ffd83dbSDimitry Andric #include "InputFiles.h"
11e8d8bef9SDimitry Andric #include "SyntheticSections.h"
12bdd1243dSDimitry Andric #include "llvm/Demangle/Demangle.h"
135ffd83dbSDimitry Andric
145ffd83dbSDimitry Andric using namespace llvm;
155ffd83dbSDimitry Andric using namespace lld;
165ffd83dbSDimitry Andric using namespace lld::macho;
175ffd83dbSDimitry Andric
1881ad6265SDimitry Andric static_assert(sizeof(void *) != 8 || sizeof(Symbol) == 56,
19349cc55cSDimitry Andric "Try to minimize Symbol's size; we create many instances");
20349cc55cSDimitry Andric
21349cc55cSDimitry Andric // The Microsoft ABI doesn't support using parent class tail padding for child
22349cc55cSDimitry Andric // members, hence the _MSC_VER check.
23349cc55cSDimitry Andric #if !defined(_MSC_VER)
2481ad6265SDimitry Andric static_assert(sizeof(void *) != 8 || sizeof(Defined) == 88,
25349cc55cSDimitry Andric "Try to minimize Defined's size; we create many instances");
26349cc55cSDimitry Andric #endif
27349cc55cSDimitry Andric
28349cc55cSDimitry Andric static_assert(sizeof(SymbolUnion) == sizeof(Defined),
29349cc55cSDimitry Andric "Defined should be the largest Symbol kind");
30349cc55cSDimitry Andric
31bdd1243dSDimitry Andric // Returns a symbol name for an error message.
maybeDemangleSymbol(StringRef symName)32bdd1243dSDimitry Andric static std::string maybeDemangleSymbol(StringRef symName) {
33bdd1243dSDimitry Andric if (config->demangle) {
34bdd1243dSDimitry Andric symName.consume_front("_");
3506c3fb27SDimitry Andric return demangle(symName);
36bdd1243dSDimitry Andric }
37bdd1243dSDimitry Andric return symName.str();
38bdd1243dSDimitry Andric }
39bdd1243dSDimitry Andric
toString(const Symbol & sym)4004eeddc0SDimitry Andric std::string lld::toString(const Symbol &sym) {
41bdd1243dSDimitry Andric return maybeDemangleSymbol(sym.getName());
42e8d8bef9SDimitry Andric }
43e8d8bef9SDimitry Andric
toMachOString(const object::Archive::Symbol & b)44e8d8bef9SDimitry Andric std::string lld::toMachOString(const object::Archive::Symbol &b) {
45bdd1243dSDimitry Andric return maybeDemangleSymbol(b.getName());
46e8d8bef9SDimitry Andric }
47e8d8bef9SDimitry Andric
getStubVA() const48fe6060f1SDimitry Andric uint64_t Symbol::getStubVA() const { return in.stubs->getVA(stubsIndex); }
getLazyPtrVA() const49bdd1243dSDimitry Andric uint64_t Symbol::getLazyPtrVA() const {
50bdd1243dSDimitry Andric return in.lazyPointers->getVA(stubsIndex);
51bdd1243dSDimitry Andric }
getGotVA() const52fe6060f1SDimitry Andric uint64_t Symbol::getGotVA() const { return in.got->getVA(gotIndex); }
getTlvVA() const53fe6060f1SDimitry Andric uint64_t Symbol::getTlvVA() const { return in.tlvPointers->getVA(gotIndex); }
54fe6060f1SDimitry Andric
Defined(StringRefZ name,InputFile * file,InputSection * isec,uint64_t value,uint64_t size,bool isWeakDef,bool isExternal,bool isPrivateExtern,bool includeInSymtab,bool isReferencedDynamically,bool noDeadStrip,bool canOverrideWeakDef,bool isWeakDefCanBeHidden,bool interposable)55349cc55cSDimitry Andric Defined::Defined(StringRefZ name, InputFile *file, InputSection *isec,
56349cc55cSDimitry Andric uint64_t value, uint64_t size, bool isWeakDef, bool isExternal,
5706c3fb27SDimitry Andric bool isPrivateExtern, bool includeInSymtab,
58349cc55cSDimitry Andric bool isReferencedDynamically, bool noDeadStrip,
5981ad6265SDimitry Andric bool canOverrideWeakDef, bool isWeakDefCanBeHidden,
6081ad6265SDimitry Andric bool interposable)
61349cc55cSDimitry Andric : Symbol(DefinedKind, name, file), overridesWeakDef(canOverrideWeakDef),
6281ad6265SDimitry Andric privateExtern(isPrivateExtern), includeInSymtab(includeInSymtab),
6306c3fb27SDimitry Andric wasIdenticalCodeFolded(false),
64349cc55cSDimitry Andric referencedDynamically(isReferencedDynamically), noDeadStrip(noDeadStrip),
6581ad6265SDimitry Andric interposable(interposable), weakDefCanBeHidden(isWeakDefCanBeHidden),
66*0fca6ea1SDimitry Andric weakDef(isWeakDef), external(isExternal), originalIsec(isec),
67*0fca6ea1SDimitry Andric value(value), size(size) {
68349cc55cSDimitry Andric if (isec) {
69349cc55cSDimitry Andric isec->symbols.push_back(this);
70349cc55cSDimitry Andric // Maintain sorted order.
71349cc55cSDimitry Andric for (auto it = isec->symbols.rbegin(), rend = isec->symbols.rend();
72349cc55cSDimitry Andric it != rend; ++it) {
73349cc55cSDimitry Andric auto next = std::next(it);
74349cc55cSDimitry Andric if (next == rend)
75349cc55cSDimitry Andric break;
76349cc55cSDimitry Andric if ((*it)->value < (*next)->value)
77349cc55cSDimitry Andric std::swap(*next, *it);
78349cc55cSDimitry Andric else
79349cc55cSDimitry Andric break;
80349cc55cSDimitry Andric }
81349cc55cSDimitry Andric }
82fe6060f1SDimitry Andric }
83fe6060f1SDimitry Andric
isTlv() const84349cc55cSDimitry Andric bool Defined::isTlv() const {
85*0fca6ea1SDimitry Andric return !isAbsolute() && isThreadLocalVariables(originalIsec->getFlags());
86fe6060f1SDimitry Andric }
87fe6060f1SDimitry Andric
getVA() const88e8d8bef9SDimitry Andric uint64_t Defined::getVA() const {
89fe6060f1SDimitry Andric assert(isLive() && "this should only be called for live symbols");
90fe6060f1SDimitry Andric
91e8d8bef9SDimitry Andric if (isAbsolute())
92e8d8bef9SDimitry Andric return value;
93fe6060f1SDimitry Andric
94*0fca6ea1SDimitry Andric if (!isec()->isFinal) {
95fe6060f1SDimitry Andric // A target arch that does not use thunks ought never ask for
96fe6060f1SDimitry Andric // the address of a function that has not yet been finalized.
97fe6060f1SDimitry Andric assert(target->usesThunks());
98fe6060f1SDimitry Andric
99fe6060f1SDimitry Andric // ConcatOutputSection::finalize() can seek the address of a
100fe6060f1SDimitry Andric // function before its address is assigned. The thunking algorithm
101fe6060f1SDimitry Andric // knows that unfinalized functions will be out of range, so it is
102fe6060f1SDimitry Andric // expedient to return a contrived out-of-range address.
103fe6060f1SDimitry Andric return TargetInfo::outOfRangeVA;
104fe6060f1SDimitry Andric }
105*0fca6ea1SDimitry Andric return isec()->getVA(value);
106349cc55cSDimitry Andric }
107349cc55cSDimitry Andric
getObjectFile() const108bdd1243dSDimitry Andric ObjFile *Defined::getObjectFile() const {
109*0fca6ea1SDimitry Andric return originalIsec ? dyn_cast_or_null<ObjFile>(originalIsec->getFile())
110*0fca6ea1SDimitry Andric : nullptr;
111e8d8bef9SDimitry Andric }
112e8d8bef9SDimitry Andric
getSourceLocation()11381ad6265SDimitry Andric std::string Defined::getSourceLocation() {
114*0fca6ea1SDimitry Andric if (!originalIsec)
11581ad6265SDimitry Andric return {};
116*0fca6ea1SDimitry Andric return originalIsec->getSourceLocation(value);
117*0fca6ea1SDimitry Andric }
118*0fca6ea1SDimitry Andric
119*0fca6ea1SDimitry Andric // Get the canonical InputSection of the symbol.
isec() const120*0fca6ea1SDimitry Andric InputSection *Defined::isec() const {
121*0fca6ea1SDimitry Andric return originalIsec ? originalIsec->canonical() : nullptr;
122*0fca6ea1SDimitry Andric }
123*0fca6ea1SDimitry Andric
124*0fca6ea1SDimitry Andric // Get the canonical unwind entry of the symbol.
unwindEntry() const125*0fca6ea1SDimitry Andric ConcatInputSection *Defined::unwindEntry() const {
126*0fca6ea1SDimitry Andric return originalUnwindEntry ? originalUnwindEntry->canonical() : nullptr;
12781ad6265SDimitry Andric }
12881ad6265SDimitry Andric
getVA() const129fe6060f1SDimitry Andric uint64_t DylibSymbol::getVA() const {
130fe6060f1SDimitry Andric return isInStubs() ? getStubVA() : Symbol::getVA();
131e8d8bef9SDimitry Andric }
132e8d8bef9SDimitry Andric
fetchArchiveMember()13304eeddc0SDimitry Andric void LazyArchive::fetchArchiveMember() { getFile()->fetch(sym); }
134