xref: /llvm-project-15.0.7/lld/ELF/Symbols.cpp (revision b7760210)
1 //===- Symbols.cpp --------------------------------------------------------===//
2 //
3 //                             The LLVM Linker
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #include "Symbols.h"
11 #include "Error.h"
12 #include "InputFiles.h"
13 #include "InputSection.h"
14 #include "OutputSections.h"
15 #include "Strings.h"
16 #include "SyntheticSections.h"
17 #include "Target.h"
18 #include "Writer.h"
19 
20 #include "llvm/ADT/STLExtras.h"
21 #include "llvm/Support/Path.h"
22 #include <cstring>
23 
24 using namespace llvm;
25 using namespace llvm::object;
26 using namespace llvm::ELF;
27 
28 using namespace lld;
29 using namespace lld::elf;
30 
31 template <class ELFT>
32 static typename ELFT::uint getSymVA(const SymbolBody &Body, int64_t &Addend) {
33   typedef typename ELFT::uint uintX_t;
34 
35   switch (Body.kind()) {
36   case SymbolBody::DefinedSyntheticKind: {
37     auto &D = cast<DefinedSynthetic>(Body);
38     const OutputSectionBase *Sec = D.Section;
39     if (!Sec)
40       return D.Value;
41     if (D.Value == uintX_t(-1))
42       return Sec->Addr + Sec->Size;
43     return Sec->Addr + D.Value;
44   }
45   case SymbolBody::DefinedRegularKind: {
46     auto &D = cast<DefinedRegular<ELFT>>(Body);
47     InputSectionBase *IS = D.Section;
48 
49     // According to the ELF spec reference to a local symbol from outside
50     // the group are not allowed. Unfortunately .eh_frame breaks that rule
51     // and must be treated specially. For now we just replace the symbol with
52     // 0.
53     if (IS == &InputSection::Discarded)
54       return 0;
55 
56     // This is an absolute symbol.
57     if (!IS)
58       return D.Value;
59 
60     uintX_t Offset = D.Value;
61     if (D.isSection()) {
62       Offset += Addend;
63       Addend = 0;
64     }
65     const OutputSectionBase *OutSec = IS->getOutputSection<ELFT>();
66     uintX_t VA = (OutSec ? OutSec->Addr : 0) + IS->getOffset<ELFT>(Offset);
67     if (D.isTls() && !Config->Relocatable) {
68       if (!Out<ELFT>::TlsPhdr)
69         fatal(toString(D.File) +
70               " has a STT_TLS symbol but doesn't have a PT_TLS section");
71       return VA - Out<ELFT>::TlsPhdr->p_vaddr;
72     }
73     return VA;
74   }
75   case SymbolBody::DefinedCommonKind:
76     if (!Config->DefineCommon)
77       return 0;
78     return In<ELFT>::Common->OutSec->Addr + In<ELFT>::Common->OutSecOff +
79            cast<DefinedCommon>(Body).Offset;
80   case SymbolBody::SharedKind: {
81     auto &SS = cast<SharedSymbol<ELFT>>(Body);
82     if (SS.NeedsCopy)
83       return SS.Section->OutSec->Addr + SS.Section->OutSecOff;
84     if (SS.NeedsPltAddr)
85       return Body.getPltVA<ELFT>();
86     return 0;
87   }
88   case SymbolBody::UndefinedKind:
89     return 0;
90   case SymbolBody::LazyArchiveKind:
91   case SymbolBody::LazyObjectKind:
92     assert(Body.symbol()->IsUsedInRegularObj && "lazy symbol reached writer");
93     return 0;
94   }
95   llvm_unreachable("invalid symbol kind");
96 }
97 
98 SymbolBody::SymbolBody(Kind K, StringRefZ Name, bool IsLocal, uint8_t StOther,
99                        uint8_t Type)
100     : SymbolKind(K), NeedsCopy(false), NeedsPltAddr(false), IsLocal(IsLocal),
101       IsInGlobalMipsGot(false), Is32BitMipsGot(false), IsInIplt(false),
102       IsInIgot(false), Type(Type), StOther(StOther), Name(Name) {}
103 
104 // Returns true if a symbol can be replaced at load-time by a symbol
105 // with the same name defined in other ELF executable or DSO.
106 bool SymbolBody::isPreemptible() const {
107   if (isLocal())
108     return false;
109 
110   // Shared symbols resolve to the definition in the DSO. The exceptions are
111   // symbols with copy relocations (which resolve to .bss) or preempt plt
112   // entries (which resolve to that plt entry).
113   if (isShared())
114     return !NeedsCopy && !NeedsPltAddr;
115 
116   // That's all that can be preempted in a non-DSO.
117   if (!Config->Shared)
118     return false;
119 
120   // Only symbols that appear in dynsym can be preempted.
121   if (!symbol()->includeInDynsym())
122     return false;
123 
124   // Only default visibility symbols can be preempted.
125   if (symbol()->Visibility != STV_DEFAULT)
126     return false;
127 
128   // -Bsymbolic means that definitions are not preempted.
129   if (Config->Bsymbolic || (Config->BsymbolicFunctions && isFunc()))
130     return !isDefined();
131   return true;
132 }
133 
134 template <class ELFT>
135 typename ELFT::uint SymbolBody::getVA(int64_t Addend) const {
136   typename ELFT::uint OutVA = getSymVA<ELFT>(*this, Addend);
137   return OutVA + Addend;
138 }
139 
140 template <class ELFT> typename ELFT::uint SymbolBody::getGotVA() const {
141   return In<ELFT>::Got->getVA() + getGotOffset<ELFT>();
142 }
143 
144 template <class ELFT> typename ELFT::uint SymbolBody::getGotOffset() const {
145   return GotIndex * Target->GotEntrySize;
146 }
147 
148 template <class ELFT> typename ELFT::uint SymbolBody::getGotPltVA() const {
149   if (this->IsInIgot)
150     return In<ELFT>::IgotPlt->getVA() + getGotPltOffset<ELFT>();
151   return In<ELFT>::GotPlt->getVA() + getGotPltOffset<ELFT>();
152 }
153 
154 template <class ELFT> typename ELFT::uint SymbolBody::getGotPltOffset() const {
155   return GotPltIndex * Target->GotPltEntrySize;
156 }
157 
158 template <class ELFT> typename ELFT::uint SymbolBody::getPltVA() const {
159   if (this->IsInIplt)
160     return In<ELFT>::Iplt->getVA() + PltIndex * Target->PltEntrySize;
161   return In<ELFT>::Plt->getVA() + Target->PltHeaderSize +
162          PltIndex * Target->PltEntrySize;
163 }
164 
165 template <class ELFT> typename ELFT::uint SymbolBody::getSize() const {
166   if (const auto *C = dyn_cast<DefinedCommon>(this))
167     return C->Size;
168   if (const auto *DR = dyn_cast<DefinedRegular<ELFT>>(this))
169     return DR->Size;
170   if (const auto *S = dyn_cast<SharedSymbol<ELFT>>(this))
171     return S->Sym.st_size;
172   return 0;
173 }
174 
175 // If a symbol name contains '@', the characters after that is
176 // a symbol version name. This function parses that.
177 void SymbolBody::parseSymbolVersion() {
178   StringRef S = getName();
179   size_t Pos = S.find('@');
180   if (Pos == 0 || Pos == StringRef::npos)
181     return;
182   StringRef Verstr = S.substr(Pos + 1);
183   if (Verstr.empty())
184     return;
185 
186   // Truncate the symbol name so that it doesn't include the version string.
187   Name = {S.data(), Pos};
188 
189   // If this is not in this DSO, it is not a definition.
190   if (!isInCurrentDSO())
191     return;
192 
193   // '@@' in a symbol name means the default version.
194   // It is usually the most recent one.
195   bool IsDefault = (Verstr[0] == '@');
196   if (IsDefault)
197     Verstr = Verstr.substr(1);
198 
199   for (VersionDefinition &Ver : Config->VersionDefinitions) {
200     if (Ver.Name != Verstr)
201       continue;
202 
203     if (IsDefault)
204       symbol()->VersionId = Ver.Id;
205     else
206       symbol()->VersionId = Ver.Id | VERSYM_HIDDEN;
207     return;
208   }
209 
210   // It is an error if the specified version is not defined.
211   error(toString(File) + ": symbol " + S + " has undefined version " + Verstr);
212 }
213 
214 Defined::Defined(Kind K, StringRefZ Name, bool IsLocal, uint8_t StOther,
215                  uint8_t Type)
216     : SymbolBody(K, Name, IsLocal, StOther, Type) {}
217 
218 template <class ELFT> bool DefinedRegular<ELFT>::isMipsPIC() const {
219   if (!Section || !isFunc())
220     return false;
221   return (this->StOther & STO_MIPS_MIPS16) == STO_MIPS_PIC ||
222          (Section->getFile<ELFT>()->getObj().getHeader()->e_flags &
223           EF_MIPS_PIC);
224 }
225 
226 Undefined::Undefined(StringRefZ Name, bool IsLocal, uint8_t StOther,
227                      uint8_t Type, InputFile *File)
228     : SymbolBody(SymbolBody::UndefinedKind, Name, IsLocal, StOther, Type) {
229   this->File = File;
230 }
231 
232 DefinedCommon::DefinedCommon(StringRef Name, uint64_t Size, uint64_t Alignment,
233                              uint8_t StOther, uint8_t Type, InputFile *File)
234     : Defined(SymbolBody::DefinedCommonKind, Name, /*IsLocal=*/false, StOther,
235               Type),
236       Alignment(Alignment), Size(Size) {
237   this->File = File;
238 }
239 
240 InputFile *Lazy::fetch() {
241   if (auto *S = dyn_cast<LazyArchive>(this))
242     return S->fetch();
243   return cast<LazyObject>(this)->fetch();
244 }
245 
246 LazyArchive::LazyArchive(ArchiveFile &File,
247                          const llvm::object::Archive::Symbol S, uint8_t Type)
248     : Lazy(LazyArchiveKind, S.getName(), Type), Sym(S) {
249   this->File = &File;
250 }
251 
252 LazyObject::LazyObject(StringRef Name, LazyObjectFile &File, uint8_t Type)
253     : Lazy(LazyObjectKind, Name, Type) {
254   this->File = &File;
255 }
256 
257 InputFile *LazyArchive::fetch() {
258   std::pair<MemoryBufferRef, uint64_t> MBInfo = file()->getMember(&Sym);
259 
260   // getMember returns an empty buffer if the member was already
261   // read from the library.
262   if (MBInfo.first.getBuffer().empty())
263     return nullptr;
264   return createObjectFile(MBInfo.first, file()->getName(), MBInfo.second);
265 }
266 
267 InputFile *LazyObject::fetch() {
268   MemoryBufferRef MBRef = file()->getBuffer();
269   if (MBRef.getBuffer().empty())
270     return nullptr;
271   return createObjectFile(MBRef);
272 }
273 
274 uint8_t Symbol::computeBinding() const {
275   if (Config->Relocatable)
276     return Binding;
277   if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED)
278     return STB_LOCAL;
279   const SymbolBody *Body = body();
280   if (VersionId == VER_NDX_LOCAL && Body->isInCurrentDSO())
281     return STB_LOCAL;
282   if (Config->NoGnuUnique && Binding == STB_GNU_UNIQUE)
283     return STB_GLOBAL;
284   return Binding;
285 }
286 
287 bool Symbol::includeInDynsym() const {
288   if (computeBinding() == STB_LOCAL)
289     return false;
290   return ExportDynamic || body()->isShared() ||
291          (body()->isUndefined() && Config->Shared);
292 }
293 
294 // Print out a log message for --trace-symbol.
295 void elf::printTraceSymbol(Symbol *Sym) {
296   SymbolBody *B = Sym->body();
297   std::string S;
298   if (B->isUndefined())
299     S = ": reference to ";
300   else if (B->isCommon())
301     S = ": common definition of ";
302   else
303     S = ": definition of ";
304 
305   message(toString(B->File) + S + B->getName());
306 }
307 
308 // Returns a symbol for an error message.
309 std::string lld::toString(const SymbolBody &B) {
310   if (Config->Demangle)
311     if (Optional<std::string> S = demangle(B.getName()))
312       return *S;
313   return B.getName();
314 }
315 
316 template uint32_t SymbolBody::template getVA<ELF32LE>(int64_t) const;
317 template uint32_t SymbolBody::template getVA<ELF32BE>(int64_t) const;
318 template uint64_t SymbolBody::template getVA<ELF64LE>(int64_t) const;
319 template uint64_t SymbolBody::template getVA<ELF64BE>(int64_t) const;
320 
321 template uint32_t SymbolBody::template getGotVA<ELF32LE>() const;
322 template uint32_t SymbolBody::template getGotVA<ELF32BE>() const;
323 template uint64_t SymbolBody::template getGotVA<ELF64LE>() const;
324 template uint64_t SymbolBody::template getGotVA<ELF64BE>() const;
325 
326 template uint32_t SymbolBody::template getGotOffset<ELF32LE>() const;
327 template uint32_t SymbolBody::template getGotOffset<ELF32BE>() const;
328 template uint64_t SymbolBody::template getGotOffset<ELF64LE>() const;
329 template uint64_t SymbolBody::template getGotOffset<ELF64BE>() const;
330 
331 template uint32_t SymbolBody::template getGotPltVA<ELF32LE>() const;
332 template uint32_t SymbolBody::template getGotPltVA<ELF32BE>() const;
333 template uint64_t SymbolBody::template getGotPltVA<ELF64LE>() const;
334 template uint64_t SymbolBody::template getGotPltVA<ELF64BE>() const;
335 
336 template uint32_t SymbolBody::template getGotPltOffset<ELF32LE>() const;
337 template uint32_t SymbolBody::template getGotPltOffset<ELF32BE>() const;
338 template uint64_t SymbolBody::template getGotPltOffset<ELF64LE>() const;
339 template uint64_t SymbolBody::template getGotPltOffset<ELF64BE>() const;
340 
341 template uint32_t SymbolBody::template getPltVA<ELF32LE>() const;
342 template uint32_t SymbolBody::template getPltVA<ELF32BE>() const;
343 template uint64_t SymbolBody::template getPltVA<ELF64LE>() const;
344 template uint64_t SymbolBody::template getPltVA<ELF64BE>() const;
345 
346 template uint32_t SymbolBody::template getSize<ELF32LE>() const;
347 template uint32_t SymbolBody::template getSize<ELF32BE>() const;
348 template uint64_t SymbolBody::template getSize<ELF64LE>() const;
349 template uint64_t SymbolBody::template getSize<ELF64BE>() const;
350 
351 template class elf::SharedSymbol<ELF32LE>;
352 template class elf::SharedSymbol<ELF32BE>;
353 template class elf::SharedSymbol<ELF64LE>;
354 template class elf::SharedSymbol<ELF64BE>;
355 
356 template class elf::DefinedRegular<ELF32LE>;
357 template class elf::DefinedRegular<ELF32BE>;
358 template class elf::DefinedRegular<ELF64LE>;
359 template class elf::DefinedRegular<ELF64BE>;
360