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