File: | tools/lld/ELF/Symbols.h |
Warning: | line 221, column 7 Value stored to 'Type' is never read |
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/Core/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 InputFile; |
31 | class LazyObjectFile; |
32 | template <class ELFT> class ObjectFile; |
33 | class OutputSection; |
34 | template <class ELFT> class SharedFile; |
35 | |
36 | struct Symbol; |
37 | |
38 | // The base class for real symbol classes. |
39 | class SymbolBody { |
40 | public: |
41 | enum Kind { |
42 | DefinedFirst, |
43 | DefinedRegularKind = DefinedFirst, |
44 | SharedKind, |
45 | DefinedCommonKind, |
46 | DefinedLast = DefinedCommonKind, |
47 | UndefinedKind, |
48 | LazyArchiveKind, |
49 | LazyObjectKind, |
50 | }; |
51 | |
52 | SymbolBody(Kind K) : SymbolKind(K) {} |
53 | |
54 | Symbol *symbol(); |
55 | const Symbol *symbol() const { |
56 | return const_cast<SymbolBody *>(this)->symbol(); |
57 | } |
58 | |
59 | Kind kind() const { return static_cast<Kind>(SymbolKind); } |
60 | |
61 | bool isUndefined() const { return SymbolKind == UndefinedKind; } |
62 | bool isDefined() const { return SymbolKind <= DefinedLast; } |
63 | bool isCommon() const { return SymbolKind == DefinedCommonKind; } |
64 | bool isLazy() const { |
65 | return SymbolKind == LazyArchiveKind || SymbolKind == LazyObjectKind; |
66 | } |
67 | bool isShared() const { return SymbolKind == SharedKind; } |
68 | bool isInCurrentDSO() const { return !isUndefined() && !isShared(); } |
69 | bool isLocal() const { return IsLocal; } |
70 | bool isPreemptible() const; |
71 | StringRef getName() const { return Name; } |
72 | void setName(StringRef S) { Name = S; } |
73 | uint8_t getVisibility() const { return StOther & 0x3; } |
74 | void parseSymbolVersion(); |
75 | |
76 | bool isInGot() const { return GotIndex != -1U; } |
77 | bool isInPlt() const { return PltIndex != -1U; } |
78 | |
79 | uint64_t getVA(int64_t Addend = 0) const; |
80 | |
81 | uint64_t getGotOffset() const; |
82 | uint64_t getGotVA() const; |
83 | uint64_t getGotPltOffset() const; |
84 | uint64_t getGotPltVA() const; |
85 | uint64_t getPltVA() const; |
86 | template <class ELFT> typename ELFT::uint getSize() const; |
87 | OutputSection *getOutputSection() const; |
88 | |
89 | // The file from which this symbol was created. |
90 | InputFile *File = nullptr; |
91 | |
92 | uint32_t DynsymIndex = 0; |
93 | uint32_t GotIndex = -1; |
94 | uint32_t GotPltIndex = -1; |
95 | uint32_t PltIndex = -1; |
96 | uint32_t GlobalDynIndex = -1; |
97 | |
98 | protected: |
99 | SymbolBody(Kind K, StringRefZ Name, bool IsLocal, uint8_t StOther, |
100 | uint8_t Type); |
101 | |
102 | const unsigned SymbolKind : 8; |
103 | |
104 | public: |
105 | // True if the linker has to generate a copy relocation. |
106 | // For SharedSymbol only. |
107 | unsigned NeedsCopy : 1; |
108 | |
109 | // True the symbol should point to its PLT entry. |
110 | // For SharedSymbol only. |
111 | unsigned NeedsPltAddr : 1; |
112 | |
113 | // True if this is a local symbol. |
114 | unsigned IsLocal : 1; |
115 | |
116 | // True if this symbol has an entry in the global part of MIPS GOT. |
117 | unsigned IsInGlobalMipsGot : 1; |
118 | |
119 | // True if this symbol is referenced by 32-bit GOT relocations. |
120 | unsigned Is32BitMipsGot : 1; |
121 | |
122 | // True if this symbol is in the Iplt sub-section of the Plt. |
123 | unsigned IsInIplt : 1; |
124 | |
125 | // True if this symbol is in the Igot sub-section of the .got.plt or .got. |
126 | unsigned IsInIgot : 1; |
127 | |
128 | // The following fields have the same meaning as the ELF symbol attributes. |
129 | uint8_t Type; // symbol type |
130 | uint8_t StOther; // st_other field value |
131 | |
132 | // The Type field may also have this value. It means that we have not yet seen |
133 | // a non-Lazy symbol with this name, so we don't know what its type is. The |
134 | // Type field is normally set to this value for Lazy symbols unless we saw a |
135 | // weak undefined symbol first, in which case we need to remember the original |
136 | // symbol's type in order to check for TLS mismatches. |
137 | enum { UnknownType = 255 }; |
138 | |
139 | bool isSection() const { return Type == llvm::ELF::STT_SECTION; } |
140 | bool isTls() const { return Type == llvm::ELF::STT_TLS; } |
141 | bool isFunc() const { return Type == llvm::ELF::STT_FUNC; } |
142 | bool isGnuIFunc() const { return Type == llvm::ELF::STT_GNU_IFUNC; } |
143 | bool isObject() const { return Type == llvm::ELF::STT_OBJECT; } |
144 | bool isFile() const { return Type == llvm::ELF::STT_FILE; } |
145 | |
146 | protected: |
147 | StringRefZ Name; |
148 | }; |
149 | |
150 | // The base class for any defined symbols. |
151 | class Defined : public SymbolBody { |
152 | public: |
153 | Defined(Kind K, StringRefZ Name, bool IsLocal, uint8_t StOther, uint8_t Type); |
154 | static bool classof(const SymbolBody *S) { return S->isDefined(); } |
155 | }; |
156 | |
157 | class DefinedCommon : public Defined { |
158 | public: |
159 | DefinedCommon(StringRef N, uint64_t Size, uint32_t Alignment, uint8_t StOther, |
160 | uint8_t Type, InputFile *File); |
161 | |
162 | static bool classof(const SymbolBody *S) { |
163 | return S->kind() == SymbolBody::DefinedCommonKind; |
164 | } |
165 | |
166 | // The output offset of this common symbol in the output bss. Computed by the |
167 | // writer. |
168 | uint64_t Offset; |
169 | |
170 | // The maximum alignment we have seen for this symbol. |
171 | uint32_t Alignment; |
172 | |
173 | uint64_t Size; |
174 | }; |
175 | |
176 | // Regular defined symbols read from object file symbol tables. |
177 | class DefinedRegular : public Defined { |
178 | public: |
179 | DefinedRegular(StringRefZ Name, bool IsLocal, uint8_t StOther, uint8_t Type, |
180 | uint64_t Value, uint64_t Size, SectionBase *Section, |
181 | InputFile *File) |
182 | : Defined(SymbolBody::DefinedRegularKind, Name, IsLocal, StOther, Type), |
183 | Value(Value), Size(Size), Section(Section) { |
184 | this->File = File; |
185 | } |
186 | |
187 | // Return true if the symbol is a PIC function. |
188 | template <class ELFT> bool isMipsPIC() const; |
189 | |
190 | static bool classof(const SymbolBody *S) { |
191 | return S->kind() == SymbolBody::DefinedRegularKind; |
192 | } |
193 | |
194 | uint64_t Value; |
195 | uint64_t Size; |
196 | SectionBase *Section; |
197 | }; |
198 | |
199 | class Undefined : public SymbolBody { |
200 | public: |
201 | Undefined(StringRefZ Name, bool IsLocal, uint8_t StOther, uint8_t Type, |
202 | InputFile *F); |
203 | |
204 | static bool classof(const SymbolBody *S) { |
205 | return S->kind() == UndefinedKind; |
206 | } |
207 | }; |
208 | |
209 | class SharedSymbol : public Defined { |
210 | public: |
211 | static bool classof(const SymbolBody *S) { |
212 | return S->kind() == SymbolBody::SharedKind; |
213 | } |
214 | |
215 | SharedSymbol(InputFile *File, StringRef Name, uint8_t StOther, uint8_t Type, |
216 | const void *ElfSym, const void *Verdef) |
217 | : Defined(SymbolBody::SharedKind, Name, /*IsLocal=*/false, StOther, Type), |
218 | Verdef(Verdef), ElfSym(ElfSym) { |
219 | // IFuncs defined in DSOs are treated as functions by the static linker. |
220 | if (isGnuIFunc()) |
221 | Type = llvm::ELF::STT_FUNC; |
Value stored to 'Type' is never read | |
222 | this->File = File; |
223 | } |
224 | |
225 | template <class ELFT> uint64_t getShndx() const { |
226 | return getSym<ELFT>().st_shndx; |
227 | } |
228 | |
229 | template <class ELFT> uint64_t getValue() const { |
230 | return getSym<ELFT>().st_value; |
231 | } |
232 | |
233 | template <class ELFT> uint64_t getSize() const { |
234 | return getSym<ELFT>().st_size; |
235 | } |
236 | |
237 | template <class ELFT> uint32_t getAlignment() const; |
238 | |
239 | // This field is a pointer to the symbol's version definition. |
240 | const void *Verdef; |
241 | |
242 | // CopyRelSec and CopyRelSecOff are significant only when NeedsCopy is true. |
243 | InputSection *CopyRelSec; |
244 | uint64_t CopyRelSecOff; |
245 | |
246 | private: |
247 | template <class ELFT> const typename ELFT::Sym &getSym() const { |
248 | return *(const typename ELFT::Sym *)ElfSym; |
249 | } |
250 | |
251 | const void *ElfSym; |
252 | }; |
253 | |
254 | // This class represents a symbol defined in an archive file. It is |
255 | // created from an archive file header, and it knows how to load an |
256 | // object file from an archive to replace itself with a defined |
257 | // symbol. If the resolver finds both Undefined and Lazy for |
258 | // the same name, it will ask the Lazy to load a file. |
259 | class Lazy : public SymbolBody { |
260 | public: |
261 | static bool classof(const SymbolBody *S) { return S->isLazy(); } |
262 | |
263 | // Returns an object file for this symbol, or a nullptr if the file |
264 | // was already returned. |
265 | InputFile *fetch(); |
266 | |
267 | protected: |
268 | Lazy(SymbolBody::Kind K, StringRef Name, uint8_t Type) |
269 | : SymbolBody(K, Name, /*IsLocal=*/false, llvm::ELF::STV_DEFAULT, Type) {} |
270 | }; |
271 | |
272 | // LazyArchive symbols represents symbols in archive files. |
273 | class LazyArchive : public Lazy { |
274 | public: |
275 | LazyArchive(ArchiveFile &File, const llvm::object::Archive::Symbol S, |
276 | uint8_t Type); |
277 | |
278 | static bool classof(const SymbolBody *S) { |
279 | return S->kind() == LazyArchiveKind; |
280 | } |
281 | |
282 | ArchiveFile *file() { return (ArchiveFile *)this->File; } |
283 | InputFile *fetch(); |
284 | |
285 | private: |
286 | const llvm::object::Archive::Symbol Sym; |
287 | }; |
288 | |
289 | // LazyObject symbols represents symbols in object files between |
290 | // --start-lib and --end-lib options. |
291 | class LazyObject : public Lazy { |
292 | public: |
293 | LazyObject(StringRef Name, LazyObjectFile &File, uint8_t Type); |
294 | |
295 | static bool classof(const SymbolBody *S) { |
296 | return S->kind() == LazyObjectKind; |
297 | } |
298 | |
299 | LazyObjectFile *file() { return (LazyObjectFile *)this->File; } |
300 | InputFile *fetch(); |
301 | }; |
302 | |
303 | // Some linker-generated symbols need to be created as |
304 | // DefinedRegular symbols. |
305 | struct ElfSym { |
306 | // __bss_start |
307 | static DefinedRegular *Bss; |
308 | |
309 | // etext and _etext |
310 | static DefinedRegular *Etext1; |
311 | static DefinedRegular *Etext2; |
312 | |
313 | // edata and _edata |
314 | static DefinedRegular *Edata1; |
315 | static DefinedRegular *Edata2; |
316 | |
317 | // end and _end |
318 | static DefinedRegular *End1; |
319 | static DefinedRegular *End2; |
320 | |
321 | // The _GLOBAL_OFFSET_TABLE_ symbol is defined by target convention to |
322 | // be at some offset from the base of the .got section, usually 0 or |
323 | // the end of the .got. |
324 | static DefinedRegular *GlobalOffsetTable; |
325 | |
326 | // _gp, _gp_disp and __gnu_local_gp symbols. Only for MIPS. |
327 | static DefinedRegular *MipsGp; |
328 | static DefinedRegular *MipsGpDisp; |
329 | static DefinedRegular *MipsLocalGp; |
330 | }; |
331 | |
332 | // A real symbol object, SymbolBody, is usually stored within a Symbol. There's |
333 | // always one Symbol for each symbol name. The resolver updates the SymbolBody |
334 | // stored in the Body field of this object as it resolves symbols. Symbol also |
335 | // holds computed properties of symbol names. |
336 | struct Symbol { |
337 | // Symbol binding. This is on the Symbol to track changes during resolution. |
338 | // In particular: |
339 | // An undefined weak is still weak when it resolves to a shared library. |
340 | // An undefined weak will not fetch archive members, but we have to remember |
341 | // it is weak. |
342 | uint8_t Binding; |
343 | |
344 | // Version definition index. |
345 | uint16_t VersionId; |
346 | |
347 | // Symbol visibility. This is the computed minimum visibility of all |
348 | // observed non-DSO symbols. |
349 | unsigned Visibility : 2; |
350 | |
351 | // True if the symbol was used for linking and thus need to be added to the |
352 | // output file's symbol table. This is true for all symbols except for |
353 | // unreferenced DSO symbols and bitcode symbols that are unreferenced except |
354 | // by other bitcode objects. |
355 | unsigned IsUsedInRegularObj : 1; |
356 | |
357 | // If this flag is true and the symbol has protected or default visibility, it |
358 | // will appear in .dynsym. This flag is set by interposable DSO symbols in |
359 | // executables, by most symbols in DSOs and executables built with |
360 | // --export-dynamic, and by dynamic lists. |
361 | unsigned ExportDynamic : 1; |
362 | |
363 | // True if this symbol is specified by --trace-symbol option. |
364 | unsigned Traced : 1; |
365 | |
366 | // This symbol version was found in a version script. |
367 | unsigned InVersionScript : 1; |
368 | |
369 | bool includeInDynsym() const; |
370 | uint8_t computeBinding() const; |
371 | bool isWeak() const { return Binding == llvm::ELF::STB_WEAK; } |
372 | |
373 | // This field is used to store the Symbol's SymbolBody. This instantiation of |
374 | // AlignedCharArrayUnion gives us a struct with a char array field that is |
375 | // large and aligned enough to store any derived class of SymbolBody. |
376 | llvm::AlignedCharArrayUnion<DefinedCommon, DefinedRegular, Undefined, |
377 | SharedSymbol, LazyArchive, LazyObject> |
378 | Body; |
379 | |
380 | SymbolBody *body() { return reinterpret_cast<SymbolBody *>(Body.buffer); } |
381 | const SymbolBody *body() const { return const_cast<Symbol *>(this)->body(); } |
382 | }; |
383 | |
384 | void printTraceSymbol(Symbol *Sym); |
385 | |
386 | template <typename T, typename... ArgT> |
387 | void replaceBody(Symbol *S, ArgT &&... Arg) { |
388 | static_assert(sizeof(T) <= sizeof(S->Body), "Body too small"); |
389 | static_assert(alignof(T) <= alignof(decltype(S->Body)), |
390 | "Body not aligned enough"); |
391 | assert(static_cast<SymbolBody *>(static_cast<T *>(nullptr)) == nullptr &&((static_cast<SymbolBody *>(static_cast<T *>(nullptr )) == nullptr && "Not a SymbolBody") ? static_cast< void> (0) : __assert_fail ("static_cast<SymbolBody *>(static_cast<T *>(nullptr)) == nullptr && \"Not a SymbolBody\"" , "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn306458/tools/lld/ELF/Symbols.h" , 392, __PRETTY_FUNCTION__)) |
392 | "Not a SymbolBody")((static_cast<SymbolBody *>(static_cast<T *>(nullptr )) == nullptr && "Not a SymbolBody") ? static_cast< void> (0) : __assert_fail ("static_cast<SymbolBody *>(static_cast<T *>(nullptr)) == nullptr && \"Not a SymbolBody\"" , "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn306458/tools/lld/ELF/Symbols.h" , 392, __PRETTY_FUNCTION__)); |
393 | |
394 | new (S->Body.buffer) T(std::forward<ArgT>(Arg)...); |
395 | |
396 | // Print out a log message if --trace-symbol was specified. |
397 | // This is for debugging. |
398 | if (S->Traced) |
399 | printTraceSymbol(S); |
400 | } |
401 | |
402 | inline Symbol *SymbolBody::symbol() { |
403 | assert(!isLocal())((!isLocal()) ? static_cast<void> (0) : __assert_fail ( "!isLocal()", "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn306458/tools/lld/ELF/Symbols.h" , 403, __PRETTY_FUNCTION__)); |
404 | return reinterpret_cast<Symbol *>(reinterpret_cast<char *>(this) - |
405 | offsetof(Symbol, Body)__builtin_offsetof(Symbol, Body)); |
406 | } |
407 | } // namespace elf |
408 | |
409 | std::string toString(const elf::SymbolBody &B); |
410 | } // namespace lld |
411 | |
412 | #endif |