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