]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lld/ELF/Symbols.h
Merge lldb trunk r321414 to contrib/llvm/tools/lldb.
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lld / ELF / Symbols.h
1 //===- Symbols.h ------------------------------------------------*- C++ -*-===//
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 // All symbols are handled as SymbolBodies regardless of their types.
11 // This file defines various types of SymbolBodies.
12 //
13 //===----------------------------------------------------------------------===//
14
15 #ifndef LLD_ELF_SYMBOLS_H
16 #define LLD_ELF_SYMBOLS_H
17
18 #include "InputSection.h"
19 #include "Strings.h"
20
21 #include "lld/Common/LLVM.h"
22 #include "llvm/Object/Archive.h"
23 #include "llvm/Object/ELF.h"
24
25 namespace lld {
26 namespace elf {
27
28 class ArchiveFile;
29 class BitcodeFile;
30 class BssSection;
31 class InputFile;
32 class LazyObjFile;
33 template <class ELFT> class ObjFile;
34 class OutputSection;
35 template <class ELFT> class SharedFile;
36
37 // The base class for real symbol classes.
38 class Symbol {
39 public:
40   enum Kind {
41     DefinedKind,
42     SharedKind,
43     UndefinedKind,
44     LazyArchiveKind,
45     LazyObjectKind,
46   };
47
48   Kind kind() const { return static_cast<Kind>(SymbolKind); }
49
50   // Symbol binding. This is not overwritten by replaceSymbol to track
51   // changes during resolution. In particular:
52   //  - An undefined weak is still weak when it resolves to a shared library.
53   //  - An undefined weak will not fetch archive members, but we have to
54   //    remember it is weak.
55   uint8_t Binding;
56
57   // Version definition index.
58   uint16_t VersionId;
59
60   // Symbol visibility. This is the computed minimum visibility of all
61   // observed non-DSO symbols.
62   unsigned Visibility : 2;
63
64   // True if the symbol was used for linking and thus need to be added to the
65   // output file's symbol table. This is true for all symbols except for
66   // unreferenced DSO symbols and bitcode symbols that are unreferenced except
67   // by other bitcode objects.
68   unsigned IsUsedInRegularObj : 1;
69
70   // If this flag is true and the symbol has protected or default visibility, it
71   // will appear in .dynsym. This flag is set by interposable DSO symbols in
72   // executables, by most symbols in DSOs and executables built with
73   // --export-dynamic, and by dynamic lists.
74   unsigned ExportDynamic : 1;
75
76   // False if LTO shouldn't inline whatever this symbol points to. If a symbol
77   // is overwritten after LTO, LTO shouldn't inline the symbol because it
78   // doesn't know the final contents of the symbol.
79   unsigned CanInline : 1;
80
81   // True if this symbol is specified by --trace-symbol option.
82   unsigned Traced : 1;
83
84   // This symbol version was found in a version script.
85   unsigned InVersionScript : 1;
86
87   // The file from which this symbol was created.
88   InputFile *File;
89
90   bool includeInDynsym() const;
91   uint8_t computeBinding() const;
92   bool isWeak() const { return Binding == llvm::ELF::STB_WEAK; }
93
94   bool isUndefined() const { return SymbolKind == UndefinedKind; }
95   bool isDefined() const { return SymbolKind == DefinedKind; }
96   bool isShared() const { return SymbolKind == SharedKind; }
97   bool isLocal() const { return Binding == llvm::ELF::STB_LOCAL; }
98
99   bool isLazy() const {
100     return SymbolKind == LazyArchiveKind || SymbolKind == LazyObjectKind;
101   }
102
103   // True is this is an undefined weak symbol. This only works once
104   // all input files have been added.
105   bool isUndefWeak() const {
106     // See comment on Lazy the details.
107     return isWeak() && (isUndefined() || isLazy());
108   }
109
110   StringRef getName() const { return Name; }
111   uint8_t getVisibility() const { return StOther & 0x3; }
112   void parseSymbolVersion();
113
114   bool isInGot() const { return GotIndex != -1U; }
115   bool isInPlt() const { return PltIndex != -1U; }
116
117   uint64_t getVA(int64_t Addend = 0) const;
118
119   uint64_t getGotOffset() const;
120   uint64_t getGotVA() const;
121   uint64_t getGotPltOffset() const;
122   uint64_t getGotPltVA() const;
123   uint64_t getPltVA() const;
124   uint64_t getSize() const;
125   OutputSection *getOutputSection() const;
126
127   uint32_t DynsymIndex = 0;
128   uint32_t GotIndex = -1;
129   uint32_t GotPltIndex = -1;
130   uint32_t PltIndex = -1;
131   uint32_t GlobalDynIndex = -1;
132
133 protected:
134   Symbol(Kind K, InputFile *File, StringRefZ Name, uint8_t Binding,
135          uint8_t StOther, uint8_t Type)
136       : Binding(Binding), File(File), SymbolKind(K), NeedsPltAddr(false),
137         IsInGlobalMipsGot(false), Is32BitMipsGot(false), IsInIplt(false),
138         IsInIgot(false), IsPreemptible(false), Used(!Config->GcSections),
139         Type(Type), StOther(StOther), Name(Name) {}
140
141   const unsigned SymbolKind : 8;
142
143 public:
144   // True the symbol should point to its PLT entry.
145   // For SharedSymbol only.
146   unsigned NeedsPltAddr : 1;
147   // True if this symbol has an entry in the global part of MIPS GOT.
148   unsigned IsInGlobalMipsGot : 1;
149
150   // True if this symbol is referenced by 32-bit GOT relocations.
151   unsigned Is32BitMipsGot : 1;
152
153   // True if this symbol is in the Iplt sub-section of the Plt.
154   unsigned IsInIplt : 1;
155
156   // True if this symbol is in the Igot sub-section of the .got.plt or .got.
157   unsigned IsInIgot : 1;
158
159   unsigned IsPreemptible : 1;
160
161   // True if an undefined or shared symbol is used from a live section.
162   unsigned Used : 1;
163
164   // The following fields have the same meaning as the ELF symbol attributes.
165   uint8_t Type;    // symbol type
166   uint8_t StOther; // st_other field value
167
168   // The Type field may also have this value. It means that we have not yet seen
169   // a non-Lazy symbol with this name, so we don't know what its type is. The
170   // Type field is normally set to this value for Lazy symbols unless we saw a
171   // weak undefined symbol first, in which case we need to remember the original
172   // symbol's type in order to check for TLS mismatches.
173   enum { UnknownType = 255 };
174
175   bool isSection() const { return Type == llvm::ELF::STT_SECTION; }
176   bool isTls() const { return Type == llvm::ELF::STT_TLS; }
177   bool isFunc() const { return Type == llvm::ELF::STT_FUNC; }
178   bool isGnuIFunc() const { return Type == llvm::ELF::STT_GNU_IFUNC; }
179   bool isObject() const { return Type == llvm::ELF::STT_OBJECT; }
180   bool isFile() const { return Type == llvm::ELF::STT_FILE; }
181
182 protected:
183   StringRefZ Name;
184 };
185
186 // Represents a symbol that is defined in the current output file.
187 class Defined : public Symbol {
188 public:
189   Defined(InputFile *File, StringRefZ Name, uint8_t Binding, uint8_t StOther,
190           uint8_t Type, uint64_t Value, uint64_t Size, SectionBase *Section)
191       : Symbol(DefinedKind, File, Name, Binding, StOther, Type), Value(Value),
192         Size(Size), Section(Section) {}
193
194   static bool classof(const Symbol *S) { return S->isDefined(); }
195
196   uint64_t Value;
197   uint64_t Size;
198   SectionBase *Section;
199 };
200
201 class Undefined : public Symbol {
202 public:
203   Undefined(InputFile *File, StringRefZ Name, uint8_t Binding, uint8_t StOther,
204             uint8_t Type)
205       : Symbol(UndefinedKind, File, Name, Binding, StOther, Type) {}
206
207   static bool classof(const Symbol *S) { return S->kind() == UndefinedKind; }
208 };
209
210 class SharedSymbol : public Symbol {
211 public:
212   static bool classof(const Symbol *S) { return S->kind() == SharedKind; }
213
214   SharedSymbol(InputFile &File, StringRef Name, uint8_t Binding,
215                uint8_t StOther, uint8_t Type, uint64_t Value, uint64_t Size,
216                uint32_t Alignment, uint32_t VerdefIndex)
217       : Symbol(SharedKind, &File, Name, Binding, StOther, Type), Value(Value),
218         Size(Size), VerdefIndex(VerdefIndex), Alignment(Alignment) {
219     // GNU ifunc is a mechanism to allow user-supplied functions to
220     // resolve PLT slot values at load-time. This is contrary to the
221     // regular symbol resolution scheme in which symbols are resolved just
222     // by name. Using this hook, you can program how symbols are solved
223     // for you program. For example, you can make "memcpy" to be resolved
224     // to a SSE-enabled version of memcpy only when a machine running the
225     // program supports the SSE instruction set.
226     //
227     // Naturally, such symbols should always be called through their PLT
228     // slots. What GNU ifunc symbols point to are resolver functions, and
229     // calling them directly doesn't make sense (unless you are writing a
230     // loader).
231     //
232     // For DSO symbols, we always call them through PLT slots anyway.
233     // So there's no difference between GNU ifunc and regular function
234     // symbols if they are in DSOs. So we can handle GNU_IFUNC as FUNC.
235     if (this->Type == llvm::ELF::STT_GNU_IFUNC)
236       this->Type = llvm::ELF::STT_FUNC;
237   }
238
239   template <class ELFT> SharedFile<ELFT> &getFile() const {
240     return *cast<SharedFile<ELFT>>(File);
241   }
242
243   // If not null, there is a copy relocation to this section.
244   InputSection *CopyRelSec = nullptr;
245
246   uint64_t Value; // st_value
247   uint64_t Size;  // st_size
248
249   // This field is a index to the symbol's version definition.
250   uint32_t VerdefIndex;
251
252   uint32_t Alignment;
253 };
254
255 // This represents a symbol that is not yet in the link, but we know where to
256 // find it if needed. If the resolver finds both Undefined and Lazy for the same
257 // name, it will ask the Lazy to load a file.
258 //
259 // A special complication is the handling of weak undefined symbols. They should
260 // not load a file, but we have to remember we have seen both the weak undefined
261 // and the lazy. We represent that with a lazy symbol with a weak binding. This
262 // means that code looking for undefined symbols normally also has to take lazy
263 // symbols into consideration.
264 class Lazy : public Symbol {
265 public:
266   static bool classof(const Symbol *S) { return S->isLazy(); }
267
268   // Returns an object file for this symbol, or a nullptr if the file
269   // was already returned.
270   InputFile *fetch();
271
272 protected:
273   Lazy(Kind K, InputFile &File, StringRef Name, uint8_t Type)
274       : Symbol(K, &File, Name, llvm::ELF::STB_GLOBAL, llvm::ELF::STV_DEFAULT,
275                Type) {}
276 };
277
278 // This class represents a symbol defined in an archive file. It is
279 // created from an archive file header, and it knows how to load an
280 // object file from an archive to replace itself with a defined
281 // symbol.
282 class LazyArchive : public Lazy {
283 public:
284   LazyArchive(InputFile &File, const llvm::object::Archive::Symbol S,
285               uint8_t Type)
286       : Lazy(LazyArchiveKind, File, S.getName(), Type), Sym(S) {}
287
288   static bool classof(const Symbol *S) { return S->kind() == LazyArchiveKind; }
289
290   ArchiveFile &getFile();
291   InputFile *fetch();
292
293 private:
294   const llvm::object::Archive::Symbol Sym;
295 };
296
297 // LazyObject symbols represents symbols in object files between
298 // --start-lib and --end-lib options.
299 class LazyObject : public Lazy {
300 public:
301   LazyObject(InputFile &File, StringRef Name, uint8_t Type)
302       : Lazy(LazyObjectKind, File, Name, Type) {}
303
304   static bool classof(const Symbol *S) { return S->kind() == LazyObjectKind; }
305
306   LazyObjFile &getFile();
307   InputFile *fetch();
308 };
309
310 // Some linker-generated symbols need to be created as
311 // Defined symbols.
312 struct ElfSym {
313   // __bss_start
314   static Defined *Bss;
315
316   // etext and _etext
317   static Defined *Etext1;
318   static Defined *Etext2;
319
320   // edata and _edata
321   static Defined *Edata1;
322   static Defined *Edata2;
323
324   // end and _end
325   static Defined *End1;
326   static Defined *End2;
327
328   // The _GLOBAL_OFFSET_TABLE_ symbol is defined by target convention to
329   // be at some offset from the base of the .got section, usually 0 or
330   // the end of the .got.
331   static Defined *GlobalOffsetTable;
332
333   // _gp, _gp_disp and __gnu_local_gp symbols. Only for MIPS.
334   static Defined *MipsGp;
335   static Defined *MipsGpDisp;
336   static Defined *MipsLocalGp;
337 };
338
339 // A buffer class that is large enough to hold any Symbol-derived
340 // object. We allocate memory using this class and instantiate a symbol
341 // using the placement new.
342 union SymbolUnion {
343   alignas(Defined) char A[sizeof(Defined)];
344   alignas(Undefined) char C[sizeof(Undefined)];
345   alignas(SharedSymbol) char D[sizeof(SharedSymbol)];
346   alignas(LazyArchive) char E[sizeof(LazyArchive)];
347   alignas(LazyObject) char F[sizeof(LazyObject)];
348 };
349
350 void printTraceSymbol(Symbol *Sym);
351
352 template <typename T, typename... ArgT>
353 void replaceSymbol(Symbol *S, ArgT &&... Arg) {
354   static_assert(sizeof(T) <= sizeof(SymbolUnion), "SymbolUnion too small");
355   static_assert(alignof(T) <= alignof(SymbolUnion),
356                 "SymbolUnion not aligned enough");
357   assert(static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr &&
358          "Not a Symbol");
359
360   Symbol Sym = *S;
361
362   new (S) T(std::forward<ArgT>(Arg)...);
363
364   S->VersionId = Sym.VersionId;
365   S->Visibility = Sym.Visibility;
366   S->IsUsedInRegularObj = Sym.IsUsedInRegularObj;
367   S->ExportDynamic = Sym.ExportDynamic;
368   S->CanInline = Sym.CanInline;
369   S->Traced = Sym.Traced;
370   S->InVersionScript = Sym.InVersionScript;
371
372   // Print out a log message if --trace-symbol was specified.
373   // This is for debugging.
374   if (S->Traced)
375     printTraceSymbol(S);
376 }
377 } // namespace elf
378
379 std::string toString(const elf::Symbol &B);
380 } // namespace lld
381
382 #endif