1bb684c34Spatrick //===- Symbols.cpp --------------------------------------------------------===//
2bb684c34Spatrick //
3bb684c34Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4bb684c34Spatrick // See https://llvm.org/LICENSE.txt for license information.
5bb684c34Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6bb684c34Spatrick //
7bb684c34Spatrick //===----------------------------------------------------------------------===//
8bb684c34Spatrick
9bb684c34Spatrick #include "Symbols.h"
10bb684c34Spatrick #include "InputFiles.h"
111cf9926bSpatrick #include "SyntheticSections.h"
12*dfe94b16Srobert #include "llvm/Demangle/Demangle.h"
13bb684c34Spatrick
14bb684c34Spatrick using namespace llvm;
15bb684c34Spatrick using namespace lld;
16bb684c34Spatrick using namespace lld::macho;
17bb684c34Spatrick
18*dfe94b16Srobert static_assert(sizeof(void *) != 8 || sizeof(Symbol) == 56,
19*dfe94b16Srobert "Try to minimize Symbol's size; we create many instances");
20*dfe94b16Srobert
21*dfe94b16Srobert // The Microsoft ABI doesn't support using parent class tail padding for child
22*dfe94b16Srobert // members, hence the _MSC_VER check.
23*dfe94b16Srobert #if !defined(_MSC_VER)
24*dfe94b16Srobert static_assert(sizeof(void *) != 8 || sizeof(Defined) == 88,
25*dfe94b16Srobert "Try to minimize Defined's size; we create many instances");
26*dfe94b16Srobert #endif
27*dfe94b16Srobert
28*dfe94b16Srobert static_assert(sizeof(SymbolUnion) == sizeof(Defined),
29*dfe94b16Srobert "Defined should be the largest Symbol kind");
30*dfe94b16Srobert
31*dfe94b16Srobert // Returns a symbol name for an error message.
maybeDemangleSymbol(StringRef symName)32*dfe94b16Srobert static std::string maybeDemangleSymbol(StringRef symName) {
33*dfe94b16Srobert if (config->demangle) {
34*dfe94b16Srobert symName.consume_front("_");
35*dfe94b16Srobert return demangle(symName.str());
36*dfe94b16Srobert }
37*dfe94b16Srobert return symName.str();
38bb684c34Spatrick }
391cf9926bSpatrick
toString(const Symbol & sym)40*dfe94b16Srobert std::string lld::toString(const Symbol &sym) {
41*dfe94b16Srobert return maybeDemangleSymbol(sym.getName());
42*dfe94b16Srobert }
431cf9926bSpatrick
toMachOString(const object::Archive::Symbol & b)441cf9926bSpatrick std::string lld::toMachOString(const object::Archive::Symbol &b) {
45*dfe94b16Srobert return maybeDemangleSymbol(b.getName());
461cf9926bSpatrick }
471cf9926bSpatrick
getStubVA() const481cf9926bSpatrick uint64_t Symbol::getStubVA() const { return in.stubs->getVA(stubsIndex); }
getLazyPtrVA() const49*dfe94b16Srobert uint64_t Symbol::getLazyPtrVA() const {
50*dfe94b16Srobert return in.lazyPointers->getVA(stubsIndex);
51*dfe94b16Srobert }
getGotVA() const521cf9926bSpatrick uint64_t Symbol::getGotVA() const { return in.got->getVA(gotIndex); }
getTlvVA() const531cf9926bSpatrick uint64_t Symbol::getTlvVA() const { return in.tlvPointers->getVA(gotIndex); }
541cf9926bSpatrick
Defined(StringRefZ name,InputFile * file,InputSection * isec,uint64_t value,uint64_t size,bool isWeakDef,bool isExternal,bool isPrivateExtern,bool includeInSymtab,bool isThumb,bool isReferencedDynamically,bool noDeadStrip,bool canOverrideWeakDef,bool isWeakDefCanBeHidden,bool interposable)55*dfe94b16Srobert Defined::Defined(StringRefZ name, InputFile *file, InputSection *isec,
56*dfe94b16Srobert uint64_t value, uint64_t size, bool isWeakDef, bool isExternal,
57*dfe94b16Srobert bool isPrivateExtern, bool includeInSymtab, bool isThumb,
58*dfe94b16Srobert bool isReferencedDynamically, bool noDeadStrip,
59*dfe94b16Srobert bool canOverrideWeakDef, bool isWeakDefCanBeHidden,
60*dfe94b16Srobert bool interposable)
61*dfe94b16Srobert : Symbol(DefinedKind, name, file), overridesWeakDef(canOverrideWeakDef),
62*dfe94b16Srobert privateExtern(isPrivateExtern), includeInSymtab(includeInSymtab),
63*dfe94b16Srobert wasIdenticalCodeFolded(false), thumb(isThumb),
64*dfe94b16Srobert referencedDynamically(isReferencedDynamically), noDeadStrip(noDeadStrip),
65*dfe94b16Srobert interposable(interposable), weakDefCanBeHidden(isWeakDefCanBeHidden),
66*dfe94b16Srobert weakDef(isWeakDef), external(isExternal), isec(isec), value(value),
67*dfe94b16Srobert size(size) {
68*dfe94b16Srobert if (isec) {
69*dfe94b16Srobert isec->symbols.push_back(this);
70*dfe94b16Srobert // Maintain sorted order.
71*dfe94b16Srobert for (auto it = isec->symbols.rbegin(), rend = isec->symbols.rend();
72*dfe94b16Srobert it != rend; ++it) {
73*dfe94b16Srobert auto next = std::next(it);
74*dfe94b16Srobert if (next == rend)
75*dfe94b16Srobert break;
76*dfe94b16Srobert if ((*it)->value < (*next)->value)
77*dfe94b16Srobert std::swap(*next, *it);
78*dfe94b16Srobert else
79*dfe94b16Srobert break;
80*dfe94b16Srobert }
81*dfe94b16Srobert }
821cf9926bSpatrick }
831cf9926bSpatrick
isTlv() const84*dfe94b16Srobert bool Defined::isTlv() const {
85*dfe94b16Srobert return !isAbsolute() && isThreadLocalVariables(isec->getFlags());
861cf9926bSpatrick }
871cf9926bSpatrick
getVA() const881cf9926bSpatrick uint64_t Defined::getVA() const {
891cf9926bSpatrick assert(isLive() && "this should only be called for live symbols");
901cf9926bSpatrick
911cf9926bSpatrick if (isAbsolute())
921cf9926bSpatrick return value;
931cf9926bSpatrick
94*dfe94b16Srobert if (!isec->isFinal) {
951cf9926bSpatrick // A target arch that does not use thunks ought never ask for
961cf9926bSpatrick // the address of a function that has not yet been finalized.
971cf9926bSpatrick assert(target->usesThunks());
981cf9926bSpatrick
991cf9926bSpatrick // ConcatOutputSection::finalize() can seek the address of a
1001cf9926bSpatrick // function before its address is assigned. The thunking algorithm
1011cf9926bSpatrick // knows that unfinalized functions will be out of range, so it is
1021cf9926bSpatrick // expedient to return a contrived out-of-range address.
1031cf9926bSpatrick return TargetInfo::outOfRangeVA;
1041cf9926bSpatrick }
105*dfe94b16Srobert return isec->getVA(value);
106*dfe94b16Srobert }
107*dfe94b16Srobert
getObjectFile() const108*dfe94b16Srobert ObjFile *Defined::getObjectFile() const {
109*dfe94b16Srobert return isec ? dyn_cast_or_null<ObjFile>(isec->getFile()) : nullptr;
110*dfe94b16Srobert }
111*dfe94b16Srobert
canonicalize()112*dfe94b16Srobert void Defined::canonicalize() {
113*dfe94b16Srobert if (unwindEntry)
114*dfe94b16Srobert unwindEntry = unwindEntry->canonical();
115*dfe94b16Srobert if (isec)
116*dfe94b16Srobert isec = isec->canonical();
117*dfe94b16Srobert }
118*dfe94b16Srobert
getSourceLocation()119*dfe94b16Srobert std::string Defined::getSourceLocation() {
120*dfe94b16Srobert if (!isec)
121*dfe94b16Srobert return {};
122*dfe94b16Srobert return isec->getSourceLocation(value);
1231cf9926bSpatrick }
1241cf9926bSpatrick
getVA() const1251cf9926bSpatrick uint64_t DylibSymbol::getVA() const {
1261cf9926bSpatrick return isInStubs() ? getStubVA() : Symbol::getVA();
1271cf9926bSpatrick }
1281cf9926bSpatrick
fetchArchiveMember()129*dfe94b16Srobert void LazyArchive::fetchArchiveMember() { getFile()->fetch(sym); }
130