xref: /freebsd/contrib/llvm-project/lld/MachO/Symbols.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
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.
32bdd1243dSDimitry Andric static std::string maybeDemangleSymbol(StringRef symName) {
33bdd1243dSDimitry Andric   if (config->demangle) {
34bdd1243dSDimitry Andric     symName.consume_front("_");
35*06c3fb27SDimitry Andric     return demangle(symName);
36bdd1243dSDimitry Andric   }
37bdd1243dSDimitry Andric   return symName.str();
38bdd1243dSDimitry Andric }
39bdd1243dSDimitry Andric 
4004eeddc0SDimitry Andric std::string lld::toString(const Symbol &sym) {
41bdd1243dSDimitry Andric   return maybeDemangleSymbol(sym.getName());
42e8d8bef9SDimitry Andric }
43e8d8bef9SDimitry Andric 
44e8d8bef9SDimitry Andric std::string lld::toMachOString(const object::Archive::Symbol &b) {
45bdd1243dSDimitry Andric   return maybeDemangleSymbol(b.getName());
46e8d8bef9SDimitry Andric }
47e8d8bef9SDimitry Andric 
48fe6060f1SDimitry Andric uint64_t Symbol::getStubVA() const { return in.stubs->getVA(stubsIndex); }
49bdd1243dSDimitry Andric uint64_t Symbol::getLazyPtrVA() const {
50bdd1243dSDimitry Andric   return in.lazyPointers->getVA(stubsIndex);
51bdd1243dSDimitry Andric }
52fe6060f1SDimitry Andric uint64_t Symbol::getGotVA() const { return in.got->getVA(gotIndex); }
53fe6060f1SDimitry Andric uint64_t Symbol::getTlvVA() const { return in.tlvPointers->getVA(gotIndex); }
54fe6060f1SDimitry Andric 
55349cc55cSDimitry Andric Defined::Defined(StringRefZ name, InputFile *file, InputSection *isec,
56349cc55cSDimitry Andric                  uint64_t value, uint64_t size, bool isWeakDef, bool isExternal,
57*06c3fb27SDimitry 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),
63*06c3fb27SDimitry Andric       wasIdenticalCodeFolded(false),
64349cc55cSDimitry Andric       referencedDynamically(isReferencedDynamically), noDeadStrip(noDeadStrip),
6581ad6265SDimitry Andric       interposable(interposable), weakDefCanBeHidden(isWeakDefCanBeHidden),
6681ad6265SDimitry Andric       weakDef(isWeakDef), external(isExternal), isec(isec), value(value),
6781ad6265SDimitry Andric       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 
84349cc55cSDimitry Andric bool Defined::isTlv() const {
85349cc55cSDimitry Andric   return !isAbsolute() && isThreadLocalVariables(isec->getFlags());
86fe6060f1SDimitry Andric }
87fe6060f1SDimitry Andric 
88e8d8bef9SDimitry 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 
94349cc55cSDimitry 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   }
105349cc55cSDimitry Andric   return isec->getVA(value);
106349cc55cSDimitry Andric }
107349cc55cSDimitry Andric 
108bdd1243dSDimitry Andric ObjFile *Defined::getObjectFile() const {
109bdd1243dSDimitry Andric   return isec ? dyn_cast_or_null<ObjFile>(isec->getFile()) : nullptr;
110bdd1243dSDimitry Andric }
111bdd1243dSDimitry Andric 
112349cc55cSDimitry Andric void Defined::canonicalize() {
113349cc55cSDimitry Andric   if (unwindEntry)
114349cc55cSDimitry Andric     unwindEntry = unwindEntry->canonical();
115349cc55cSDimitry Andric   if (isec)
116349cc55cSDimitry Andric     isec = isec->canonical();
117e8d8bef9SDimitry Andric }
118e8d8bef9SDimitry Andric 
11981ad6265SDimitry Andric std::string Defined::getSourceLocation() {
12081ad6265SDimitry Andric   if (!isec)
12181ad6265SDimitry Andric     return {};
12281ad6265SDimitry Andric   return isec->getSourceLocation(value);
12381ad6265SDimitry Andric }
12481ad6265SDimitry Andric 
125fe6060f1SDimitry Andric uint64_t DylibSymbol::getVA() const {
126fe6060f1SDimitry Andric   return isInStubs() ? getStubVA() : Symbol::getVA();
127e8d8bef9SDimitry Andric }
128e8d8bef9SDimitry Andric 
12904eeddc0SDimitry Andric void LazyArchive::fetchArchiveMember() { getFile()->fetch(sym); }
130