xref: /openbsd-src/gnu/llvm/lld/MachO/Symbols.cpp (revision dfe94b169149f14cc1aee2cf6dad58a8d9a1860c)
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