Rafael Espindola | beee25e | 2015-08-14 14:12:54 | [diff] [blame] | 1 | //===- Symbols.h ------------------------------------------------*- C++ -*-===// |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 2 | // |
Chandler Carruth | 2946cd7 | 2019-01-19 08:50:56 | [diff] [blame] | 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | |
| 9 | #ifndef LLD_COFF_SYMBOLS_H |
| 10 | #define LLD_COFF_SYMBOLS_H |
| 11 | |
| 12 | #include "Chunks.h" |
| 13 | #include "Config.h" |
Rui Ueyama | 3f85170 | 2017-10-02 21:00:41 | [diff] [blame] | 14 | #include "lld/Common/LLVM.h" |
Rui Ueyama | 2017d52 | 2017-11-28 20:39:17 | [diff] [blame] | 15 | #include "lld/Common/Memory.h" |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 16 | #include "llvm/ADT/ArrayRef.h" |
| 17 | #include "llvm/Object/Archive.h" |
| 18 | #include "llvm/Object/COFF.h" |
Rui Ueyama | c80c03d | 2015-07-05 21:54:42 | [diff] [blame] | 19 | #include <atomic> |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 20 | #include <memory> |
| 21 | #include <vector> |
| 22 | |
| 23 | namespace lld { |
| 24 | namespace coff { |
| 25 | |
| 26 | using llvm::object::Archive; |
| 27 | using llvm::object::COFFSymbolRef; |
Rui Ueyama | c9bfe32 | 2015-05-29 15:45:35 | [diff] [blame] | 28 | using llvm::object::coff_import_header; |
Rui Ueyama | c15139b | 2015-06-30 00:10:54 | [diff] [blame] | 29 | using llvm::object::coff_symbol_generic; |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 30 | |
| 31 | class ArchiveFile; |
| 32 | class InputFile; |
Rui Ueyama | e1b48e0 | 2017-07-26 23:05:24 | [diff] [blame] | 33 | class ObjFile; |
Peter Collingbourne | 79a5e6b | 2016-12-09 21:55:24 | [diff] [blame] | 34 | class SymbolTable; |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 35 | |
| 36 | // The base class for real symbol classes. |
Rui Ueyama | f52496e | 2017-11-03 21:21:47 | [diff] [blame] | 37 | class Symbol { |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 38 | public: |
| 39 | enum Kind { |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 40 | // The order of these is significant. We start with the regular defined |
Nico Weber | 1f3ab98 | 2019-01-14 19:05:21 | [diff] [blame] | 41 | // symbols as those are the most prevalent and the zero tag is the cheapest |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 42 | // to set. Among the defined kinds, the lower the kind is preferred over |
Nico Weber | c7bad57 | 2018-08-27 14:22:25 | [diff] [blame] | 43 | // the higher kind when testing whether one symbol should take precedence |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 44 | // over another. |
| 45 | DefinedRegularKind = 0, |
Rui Ueyama | efb7e1a | 2015-06-20 07:21:57 | [diff] [blame] | 46 | DefinedCommonKind, |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 47 | DefinedLocalImportKind, |
| 48 | DefinedImportThunkKind, |
| 49 | DefinedImportDataKind, |
| 50 | DefinedAbsoluteKind, |
Reid Kleckner | 502d4ce | 2017-06-26 15:39:52 | [diff] [blame] | 51 | DefinedSyntheticKind, |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 52 | |
Rui Ueyama | e251476 | 2015-06-15 19:06:53 | [diff] [blame] | 53 | UndefinedKind, |
Rui Ueyama | 8d3010a | 2015-06-30 19:35:21 | [diff] [blame] | 54 | LazyKind, |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 55 | |
| 56 | LastDefinedCOFFKind = DefinedCommonKind, |
Reid Kleckner | 502d4ce | 2017-06-26 15:39:52 | [diff] [blame] | 57 | LastDefinedKind = DefinedSyntheticKind, |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 58 | }; |
| 59 | |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 60 | Kind kind() const { return static_cast<Kind>(SymbolKind); } |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 61 | |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 62 | // Returns the symbol name. |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 63 | StringRef getName(); |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 64 | |
Martin Storsjo | eac1b05 | 2018-08-27 08:43:31 | [diff] [blame] | 65 | void replaceKeepingName(Symbol *Other, size_t Size); |
| 66 | |
Rui Ueyama | a45d45e | 2016-12-07 23:17:02 | [diff] [blame] | 67 | // Returns the file from which this symbol was created. |
| 68 | InputFile *getFile(); |
| 69 | |
Reid Kleckner | eacdf04 | 2017-07-27 18:25:59 | [diff] [blame] | 70 | // Indicates that this symbol will be included in the final image. Only valid |
| 71 | // after calling markLive. |
| 72 | bool isLive() const; |
| 73 | |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 74 | protected: |
Peter Collingbourne | 79a5e6b | 2016-12-09 21:55:24 | [diff] [blame] | 75 | friend SymbolTable; |
Rui Ueyama | f52496e | 2017-11-03 21:21:47 | [diff] [blame] | 76 | explicit Symbol(Kind K, StringRef N = "") |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 77 | : SymbolKind(K), IsExternal(true), IsCOMDAT(false), |
Peter Collingbourne | f874bd6 | 2017-11-21 01:14:14 | [diff] [blame] | 78 | WrittenToSymtab(false), PendingArchiveLoad(false), IsGCRoot(false), |
Reid Kleckner | a30920c | 2019-04-19 22:51:49 | [diff] [blame] | 79 | IsRuntimePseudoReloc(false), NameSize(N.size()), |
| 80 | NameData(N.empty() ? nullptr : N.data()) {} |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 81 | |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 82 | const unsigned SymbolKind : 8; |
| 83 | unsigned IsExternal : 1; |
| 84 | |
Rui Ueyama | 7e296ad | 2019-07-10 09:10:01 | [diff] [blame^] | 85 | public: |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 86 | // This bit is used by the \c DefinedRegular subclass. |
| 87 | unsigned IsCOMDAT : 1; |
| 88 | |
Peter Collingbourne | f874bd6 | 2017-11-21 01:14:14 | [diff] [blame] | 89 | // This bit is used by Writer::createSymbolAndStringTable() to prevent |
| 90 | // symbols from being written to the symbol table more than once. |
| 91 | unsigned WrittenToSymtab : 1; |
| 92 | |
Rui Ueyama | 616cd99 | 2017-10-31 16:10:24 | [diff] [blame] | 93 | // True if this symbol was referenced by a regular (non-bitcode) object. |
| 94 | unsigned IsUsedInRegularObj : 1; |
| 95 | |
| 96 | // True if we've seen both a lazy and an undefined symbol with this symbol |
| 97 | // name, which means that we have enqueued an archive member load and should |
| 98 | // not load any more archive members to resolve the same symbol. |
| 99 | unsigned PendingArchiveLoad : 1; |
| 100 | |
Reid Kleckner | 5883989 | 2017-11-13 18:38:53 | [diff] [blame] | 101 | /// True if we've already added this symbol to the list of GC roots. |
| 102 | unsigned IsGCRoot : 1; |
| 103 | |
Martin Storsjo | 2bfa125 | 2018-09-26 06:13:39 | [diff] [blame] | 104 | unsigned IsRuntimePseudoReloc : 1; |
| 105 | |
Peter Collingbourne | 9911128 | 2016-12-11 22:15:20 | [diff] [blame] | 106 | protected: |
Reid Kleckner | a30920c | 2019-04-19 22:51:49 | [diff] [blame] | 107 | // Symbol name length. Assume symbol lengths fit in a 32-bit integer. |
| 108 | uint32_t NameSize; |
| 109 | |
| 110 | const char *NameData; |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 111 | }; |
| 112 | |
| 113 | // The base class for any defined symbols, including absolute symbols, |
| 114 | // etc. |
Rui Ueyama | f52496e | 2017-11-03 21:21:47 | [diff] [blame] | 115 | class Defined : public Symbol { |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 116 | public: |
Rui Ueyama | f52496e | 2017-11-03 21:21:47 | [diff] [blame] | 117 | Defined(Kind K, StringRef N) : Symbol(K, N) {} |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 118 | |
Rui Ueyama | f52496e | 2017-11-03 21:21:47 | [diff] [blame] | 119 | static bool classof(const Symbol *S) { return S->kind() <= LastDefinedKind; } |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 120 | |
| 121 | // Returns the RVA (relative virtual address) of this symbol. The |
| 122 | // writer sets and uses RVAs. |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 123 | uint64_t getRVA(); |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 124 | |
Reid Kleckner | a1001b8 | 2017-06-28 17:06:35 | [diff] [blame] | 125 | // Returns the chunk containing this symbol. Absolute symbols and __ImageBase |
| 126 | // do not have chunks, so this may return null. |
| 127 | Chunk *getChunk(); |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 128 | }; |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 129 | |
Bob Haarman | cde5e5b | 2017-02-02 23:58:14 | [diff] [blame] | 130 | // Symbols defined via a COFF object file or bitcode file. For COFF files, this |
| 131 | // stores a coff_symbol_generic*, and names of internal symbols are lazily |
| 132 | // loaded through that. For bitcode files, Sym is nullptr and the name is stored |
Reid Kleckner | a30920c | 2019-04-19 22:51:49 | [diff] [blame] | 133 | // as a decomposed StringRef. |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 134 | class DefinedCOFF : public Defined { |
Rui Ueyama | f52496e | 2017-11-03 21:21:47 | [diff] [blame] | 135 | friend Symbol; |
| 136 | |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 137 | public: |
Bob Haarman | cde5e5b | 2017-02-02 23:58:14 | [diff] [blame] | 138 | DefinedCOFF(Kind K, InputFile *F, StringRef N, const coff_symbol_generic *S) |
| 139 | : Defined(K, N), File(F), Sym(S) {} |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 140 | |
Rui Ueyama | f52496e | 2017-11-03 21:21:47 | [diff] [blame] | 141 | static bool classof(const Symbol *S) { |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 142 | return S->kind() <= LastDefinedCOFFKind; |
| 143 | } |
| 144 | |
Bob Haarman | cde5e5b | 2017-02-02 23:58:14 | [diff] [blame] | 145 | InputFile *getFile() { return File; } |
Rui Ueyama | 65813ed | 2015-07-02 20:33:48 | [diff] [blame] | 146 | |
David Majnemer | 3a62d3d | 2015-07-09 17:43:50 | [diff] [blame] | 147 | COFFSymbolRef getCOFFSymbol(); |
| 148 | |
Bob Haarman | cde5e5b | 2017-02-02 23:58:14 | [diff] [blame] | 149 | InputFile *File; |
Rui Ueyama | a45d45e | 2016-12-07 23:17:02 | [diff] [blame] | 150 | |
| 151 | protected: |
Rui Ueyama | c15139b | 2015-06-30 00:10:54 | [diff] [blame] | 152 | const coff_symbol_generic *Sym; |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 153 | }; |
| 154 | |
| 155 | // Regular defined symbols read from object file symbol tables. |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 156 | class DefinedRegular : public DefinedCOFF { |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 157 | public: |
Bob Haarman | cde5e5b | 2017-02-02 23:58:14 | [diff] [blame] | 158 | DefinedRegular(InputFile *F, StringRef N, bool IsCOMDAT, |
| 159 | bool IsExternal = false, |
| 160 | const coff_symbol_generic *S = nullptr, |
| 161 | SectionChunk *C = nullptr) |
Bob Haarman | cd7197f | 2017-02-03 23:05:17 | [diff] [blame] | 162 | : DefinedCOFF(DefinedRegularKind, F, N, S), Data(C ? &C->Repl : nullptr) { |
Bob Haarman | cde5e5b | 2017-02-02 23:58:14 | [diff] [blame] | 163 | this->IsExternal = IsExternal; |
| 164 | this->IsCOMDAT = IsCOMDAT; |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 165 | } |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 166 | |
Rui Ueyama | f52496e | 2017-11-03 21:21:47 | [diff] [blame] | 167 | static bool classof(const Symbol *S) { |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 168 | return S->kind() == DefinedRegularKind; |
| 169 | } |
| 170 | |
Reid Kleckner | eacdf04 | 2017-07-27 18:25:59 | [diff] [blame] | 171 | uint64_t getRVA() const { return (*Data)->getRVA() + Sym->Value; } |
Reid Kleckner | eacdf04 | 2017-07-27 18:25:59 | [diff] [blame] | 172 | SectionChunk *getChunk() const { return *Data; } |
| 173 | uint32_t getValue() const { return Sym->Value; } |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 174 | |
Rui Ueyama | 9b921e5 | 2015-06-25 22:00:42 | [diff] [blame] | 175 | SectionChunk **Data; |
Rui Ueyama | efb7e1a | 2015-06-20 07:21:57 | [diff] [blame] | 176 | }; |
| 177 | |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 178 | class DefinedCommon : public DefinedCOFF { |
Rui Ueyama | efb7e1a | 2015-06-20 07:21:57 | [diff] [blame] | 179 | public: |
Bob Haarman | cde5e5b | 2017-02-02 23:58:14 | [diff] [blame] | 180 | DefinedCommon(InputFile *F, StringRef N, uint64_t Size, |
| 181 | const coff_symbol_generic *S = nullptr, |
| 182 | CommonChunk *C = nullptr) |
| 183 | : DefinedCOFF(DefinedCommonKind, F, N, S), Data(C), Size(Size) { |
| 184 | this->IsExternal = true; |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 185 | } |
Rui Ueyama | efb7e1a | 2015-06-20 07:21:57 | [diff] [blame] | 186 | |
Rui Ueyama | f52496e | 2017-11-03 21:21:47 | [diff] [blame] | 187 | static bool classof(const Symbol *S) { |
Rui Ueyama | efb7e1a | 2015-06-20 07:21:57 | [diff] [blame] | 188 | return S->kind() == DefinedCommonKind; |
| 189 | } |
| 190 | |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 191 | uint64_t getRVA() { return Data->getRVA(); } |
Martin Storsjo | d2752aa | 2017-08-14 19:07:27 | [diff] [blame] | 192 | CommonChunk *getChunk() { return Data; } |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 193 | |
| 194 | private: |
Peter Collingbourne | 79a5e6b | 2016-12-09 21:55:24 | [diff] [blame] | 195 | friend SymbolTable; |
Bob Haarman | cde5e5b | 2017-02-02 23:58:14 | [diff] [blame] | 196 | uint64_t getSize() const { return Size; } |
Rui Ueyama | fc510f4 | 2015-06-25 19:10:58 | [diff] [blame] | 197 | CommonChunk *Data; |
Bob Haarman | cde5e5b | 2017-02-02 23:58:14 | [diff] [blame] | 198 | uint64_t Size; |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 199 | }; |
| 200 | |
| 201 | // Absolute symbols. |
| 202 | class DefinedAbsolute : public Defined { |
| 203 | public: |
Rui Ueyama | ccde19d | 2015-06-26 03:09:23 | [diff] [blame] | 204 | DefinedAbsolute(StringRef N, COFFSymbolRef S) |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 205 | : Defined(DefinedAbsoluteKind, N), VA(S.getValue()) { |
| 206 | IsExternal = S.isExternal(); |
| 207 | } |
Rui Ueyama | ccde19d | 2015-06-26 03:09:23 | [diff] [blame] | 208 | |
| 209 | DefinedAbsolute(StringRef N, uint64_t V) |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 210 | : Defined(DefinedAbsoluteKind, N), VA(V) {} |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 211 | |
Rui Ueyama | f52496e | 2017-11-03 21:21:47 | [diff] [blame] | 212 | static bool classof(const Symbol *S) { |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 213 | return S->kind() == DefinedAbsoluteKind; |
| 214 | } |
| 215 | |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 216 | uint64_t getRVA() { return VA - Config->ImageBase; } |
Rui Ueyama | cd3f99b | 2015-07-24 23:51:14 | [diff] [blame] | 217 | void setVA(uint64_t V) { VA = V; } |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 218 | |
Rui Ueyama | b310747 | 2018-02-17 20:41:38 | [diff] [blame] | 219 | // Section index relocations against absolute symbols resolve to |
| 220 | // this 16 bit number, and it is the largest valid section index |
| 221 | // plus one. This variable keeps it. |
| 222 | static uint16_t NumOutputSections; |
Reid Kleckner | 8456411 | 2017-06-22 23:33:04 | [diff] [blame] | 223 | |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 224 | private: |
Rui Ueyama | ccde19d | 2015-06-26 03:09:23 | [diff] [blame] | 225 | uint64_t VA; |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 226 | }; |
| 227 | |
Reid Kleckner | 502d4ce | 2017-06-26 15:39:52 | [diff] [blame] | 228 | // This symbol is used for linker-synthesized symbols like __ImageBase and |
| 229 | // __safe_se_handler_table. |
| 230 | class DefinedSynthetic : public Defined { |
Rui Ueyama | 3cb895c | 2015-07-24 22:58:44 | [diff] [blame] | 231 | public: |
Reid Kleckner | 502d4ce | 2017-06-26 15:39:52 | [diff] [blame] | 232 | explicit DefinedSynthetic(StringRef Name, Chunk *C) |
| 233 | : Defined(DefinedSyntheticKind, Name), C(C) {} |
Rui Ueyama | 3cb895c | 2015-07-24 22:58:44 | [diff] [blame] | 234 | |
Rui Ueyama | f52496e | 2017-11-03 21:21:47 | [diff] [blame] | 235 | static bool classof(const Symbol *S) { |
Reid Kleckner | 502d4ce | 2017-06-26 15:39:52 | [diff] [blame] | 236 | return S->kind() == DefinedSyntheticKind; |
Rui Ueyama | 3cb895c | 2015-07-24 22:58:44 | [diff] [blame] | 237 | } |
| 238 | |
Reid Kleckner | 502d4ce | 2017-06-26 15:39:52 | [diff] [blame] | 239 | // A null chunk indicates that this is __ImageBase. Otherwise, this is some |
| 240 | // other synthesized chunk, like SEHTableChunk. |
Reid Kleckner | a1001b8 | 2017-06-28 17:06:35 | [diff] [blame] | 241 | uint32_t getRVA() { return C ? C->getRVA() : 0; } |
| 242 | Chunk *getChunk() { return C; } |
Rui Ueyama | 3cb895c | 2015-07-24 22:58:44 | [diff] [blame] | 243 | |
| 244 | private: |
Reid Kleckner | 502d4ce | 2017-06-26 15:39:52 | [diff] [blame] | 245 | Chunk *C; |
Rui Ueyama | 3cb895c | 2015-07-24 22:58:44 | [diff] [blame] | 246 | }; |
| 247 | |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 248 | // This class represents a symbol defined in an archive file. It is |
| 249 | // created from an archive file header, and it knows how to load an |
| 250 | // object file from an archive to replace itself with a defined |
| 251 | // symbol. If the resolver finds both Undefined and Lazy for |
| 252 | // the same name, it will ask the Lazy to load a file. |
Rui Ueyama | f52496e | 2017-11-03 21:21:47 | [diff] [blame] | 253 | class Lazy : public Symbol { |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 254 | public: |
| 255 | Lazy(ArchiveFile *F, const Archive::Symbol S) |
Rui Ueyama | f52496e | 2017-11-03 21:21:47 | [diff] [blame] | 256 | : Symbol(LazyKind, S.getName()), File(F), Sym(S) {} |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 257 | |
Rui Ueyama | f52496e | 2017-11-03 21:21:47 | [diff] [blame] | 258 | static bool classof(const Symbol *S) { return S->kind() == LazyKind; } |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 259 | |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 260 | ArchiveFile *File; |
Rui Ueyama | a45d45e | 2016-12-07 23:17:02 | [diff] [blame] | 261 | |
| 262 | private: |
Peter Collingbourne | 79a5e6b | 2016-12-09 21:55:24 | [diff] [blame] | 263 | friend SymbolTable; |
| 264 | |
| 265 | private: |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 266 | const Archive::Symbol Sym; |
| 267 | }; |
| 268 | |
| 269 | // Undefined symbols. |
Rui Ueyama | f52496e | 2017-11-03 21:21:47 | [diff] [blame] | 270 | class Undefined : public Symbol { |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 271 | public: |
Rui Ueyama | f52496e | 2017-11-03 21:21:47 | [diff] [blame] | 272 | explicit Undefined(StringRef N) : Symbol(UndefinedKind, N) {} |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 273 | |
Rui Ueyama | f52496e | 2017-11-03 21:21:47 | [diff] [blame] | 274 | static bool classof(const Symbol *S) { return S->kind() == UndefinedKind; } |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 275 | |
| 276 | // An undefined symbol can have a fallback symbol which gives an |
| 277 | // undefined symbol a second chance if it would remain undefined. |
| 278 | // If it remains undefined, it'll be replaced with whatever the |
| 279 | // Alias pointer points to. |
Rui Ueyama | f52496e | 2017-11-03 21:21:47 | [diff] [blame] | 280 | Symbol *WeakAlias = nullptr; |
Peter Collingbourne | 2612a32 | 2015-07-04 05:28:41 | [diff] [blame] | 281 | |
| 282 | // If this symbol is external weak, try to resolve it to a defined |
| 283 | // symbol by searching the chain of fallback symbols. Returns the symbol if |
| 284 | // successful, otherwise returns null. |
| 285 | Defined *getWeakAlias(); |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 286 | }; |
| 287 | |
| 288 | // Windows-specific classes. |
| 289 | |
Rui Ueyama | 7c4fcdd | 2015-05-29 15:49:09 | [diff] [blame] | 290 | // This class represents a symbol imported from a DLL. This has two |
| 291 | // names for internal use and external use. The former is used for |
| 292 | // name resolution, and the latter is used for the import descriptor |
| 293 | // table in an output. The former has "__imp_" prefix. |
| 294 | class DefinedImportData : public Defined { |
| 295 | public: |
Peter Collingbourne | 79a5e6b | 2016-12-09 21:55:24 | [diff] [blame] | 296 | DefinedImportData(StringRef N, ImportFile *F) |
Rui Ueyama | b6632d9 | 2017-05-22 06:01:37 | [diff] [blame] | 297 | : Defined(DefinedImportDataKind, N), File(F) { |
| 298 | } |
Rui Ueyama | 7c4fcdd | 2015-05-29 15:49:09 | [diff] [blame] | 299 | |
Rui Ueyama | f52496e | 2017-11-03 21:21:47 | [diff] [blame] | 300 | static bool classof(const Symbol *S) { |
Rui Ueyama | 7c4fcdd | 2015-05-29 15:49:09 | [diff] [blame] | 301 | return S->kind() == DefinedImportDataKind; |
| 302 | } |
| 303 | |
Peter Collingbourne | 79a5e6b | 2016-12-09 21:55:24 | [diff] [blame] | 304 | uint64_t getRVA() { return File->Location->getRVA(); } |
Reid Kleckner | a1001b8 | 2017-06-28 17:06:35 | [diff] [blame] | 305 | Chunk *getChunk() { return File->Location; } |
| 306 | void setLocation(Chunk *AddressTable) { File->Location = AddressTable; } |
| 307 | |
Peter Collingbourne | 79a5e6b | 2016-12-09 21:55:24 | [diff] [blame] | 308 | StringRef getDLLName() { return File->DLLName; } |
| 309 | StringRef getExternalName() { return File->ExternalName; } |
Peter Collingbourne | 79a5e6b | 2016-12-09 21:55:24 | [diff] [blame] | 310 | uint16_t getOrdinal() { return File->Hdr->OrdinalHint; } |
Rui Ueyama | 7c4fcdd | 2015-05-29 15:49:09 | [diff] [blame] | 311 | |
Peter Collingbourne | 79a5e6b | 2016-12-09 21:55:24 | [diff] [blame] | 312 | ImportFile *File; |
Rui Ueyama | 7c4fcdd | 2015-05-29 15:49:09 | [diff] [blame] | 313 | }; |
| 314 | |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 315 | // This class represents a symbol for a jump table entry which jumps |
| 316 | // to a function in a DLL. Linker are supposed to create such symbols |
| 317 | // without "__imp_" prefix for all function symbols exported from |
| 318 | // DLLs, so that you can call DLL functions as regular functions with |
| 319 | // a regular name. A function pointer is given as a DefinedImportData. |
| 320 | class DefinedImportThunk : public Defined { |
| 321 | public: |
Rui Ueyama | 5e706b3 | 2015-07-25 21:54:50 | [diff] [blame] | 322 | DefinedImportThunk(StringRef Name, DefinedImportData *S, uint16_t Machine); |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 323 | |
Rui Ueyama | f52496e | 2017-11-03 21:21:47 | [diff] [blame] | 324 | static bool classof(const Symbol *S) { |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 325 | return S->kind() == DefinedImportThunkKind; |
| 326 | } |
| 327 | |
Rui Ueyama | 28df042 | 2015-07-25 01:16:06 | [diff] [blame] | 328 | uint64_t getRVA() { return Data->getRVA(); } |
Peter Collingbourne | e50f485 | 2016-12-12 18:42:09 | [diff] [blame] | 329 | Chunk *getChunk() { return Data; } |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 330 | |
Rui Ueyama | 9aa82f7 | 2017-05-24 22:30:06 | [diff] [blame] | 331 | DefinedImportData *WrappedSym; |
| 332 | |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 333 | private: |
Peter Collingbourne | e50f485 | 2016-12-12 18:42:09 | [diff] [blame] | 334 | Chunk *Data; |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 335 | }; |
| 336 | |
Martin Storsjo | d9fd4a0 | 2018-08-07 06:42:53 | [diff] [blame] | 337 | // If you have a symbol "foo" in your object file, a symbol name |
| 338 | // "__imp_foo" becomes automatically available as a pointer to "foo". |
Rui Ueyama | 88e0f92 | 2015-06-25 03:31:47 | [diff] [blame] | 339 | // This class is for such automatically-created symbols. |
| 340 | // Yes, this is an odd feature. We didn't intend to implement that. |
| 341 | // This is here just for compatibility with MSVC. |
| 342 | class DefinedLocalImport : public Defined { |
| 343 | public: |
| 344 | DefinedLocalImport(StringRef N, Defined *S) |
Rui Ueyama | b6632d9 | 2017-05-22 06:01:37 | [diff] [blame] | 345 | : Defined(DefinedLocalImportKind, N), Data(make<LocalImportChunk>(S)) {} |
Rui Ueyama | 88e0f92 | 2015-06-25 03:31:47 | [diff] [blame] | 346 | |
Rui Ueyama | f52496e | 2017-11-03 21:21:47 | [diff] [blame] | 347 | static bool classof(const Symbol *S) { |
Rui Ueyama | 88e0f92 | 2015-06-25 03:31:47 | [diff] [blame] | 348 | return S->kind() == DefinedLocalImportKind; |
| 349 | } |
| 350 | |
Peter Collingbourne | 79a5e6b | 2016-12-09 21:55:24 | [diff] [blame] | 351 | uint64_t getRVA() { return Data->getRVA(); } |
Peter Collingbourne | e50f485 | 2016-12-12 18:42:09 | [diff] [blame] | 352 | Chunk *getChunk() { return Data; } |
Rui Ueyama | 88e0f92 | 2015-06-25 03:31:47 | [diff] [blame] | 353 | |
| 354 | private: |
Peter Collingbourne | e50f485 | 2016-12-12 18:42:09 | [diff] [blame] | 355 | LocalImportChunk *Data; |
Rui Ueyama | 88e0f92 | 2015-06-25 03:31:47 | [diff] [blame] | 356 | }; |
| 357 | |
Rui Ueyama | cb71c72 | 2015-07-13 22:01:27 | [diff] [blame] | 358 | inline uint64_t Defined::getRVA() { |
| 359 | switch (kind()) { |
| 360 | case DefinedAbsoluteKind: |
| 361 | return cast<DefinedAbsolute>(this)->getRVA(); |
Reid Kleckner | 502d4ce | 2017-06-26 15:39:52 | [diff] [blame] | 362 | case DefinedSyntheticKind: |
| 363 | return cast<DefinedSynthetic>(this)->getRVA(); |
Rui Ueyama | cb71c72 | 2015-07-13 22:01:27 | [diff] [blame] | 364 | case DefinedImportDataKind: |
| 365 | return cast<DefinedImportData>(this)->getRVA(); |
| 366 | case DefinedImportThunkKind: |
| 367 | return cast<DefinedImportThunk>(this)->getRVA(); |
| 368 | case DefinedLocalImportKind: |
| 369 | return cast<DefinedLocalImport>(this)->getRVA(); |
| 370 | case DefinedCommonKind: |
| 371 | return cast<DefinedCommon>(this)->getRVA(); |
| 372 | case DefinedRegularKind: |
| 373 | return cast<DefinedRegular>(this)->getRVA(); |
Rui Ueyama | cb71c72 | 2015-07-13 22:01:27 | [diff] [blame] | 374 | case LazyKind: |
| 375 | case UndefinedKind: |
| 376 | llvm_unreachable("Cannot get the address for an undefined symbol."); |
| 377 | } |
| 378 | llvm_unreachable("unknown symbol kind"); |
| 379 | } |
| 380 | |
Reid Kleckner | a1001b8 | 2017-06-28 17:06:35 | [diff] [blame] | 381 | inline Chunk *Defined::getChunk() { |
| 382 | switch (kind()) { |
| 383 | case DefinedRegularKind: |
| 384 | return cast<DefinedRegular>(this)->getChunk(); |
| 385 | case DefinedAbsoluteKind: |
| 386 | return nullptr; |
| 387 | case DefinedSyntheticKind: |
| 388 | return cast<DefinedSynthetic>(this)->getChunk(); |
| 389 | case DefinedImportDataKind: |
| 390 | return cast<DefinedImportData>(this)->getChunk(); |
| 391 | case DefinedImportThunkKind: |
| 392 | return cast<DefinedImportThunk>(this)->getChunk(); |
| 393 | case DefinedLocalImportKind: |
| 394 | return cast<DefinedLocalImport>(this)->getChunk(); |
| 395 | case DefinedCommonKind: |
| 396 | return cast<DefinedCommon>(this)->getChunk(); |
| 397 | case LazyKind: |
| 398 | case UndefinedKind: |
| 399 | llvm_unreachable("Cannot get the chunk of an undefined symbol."); |
| 400 | } |
| 401 | llvm_unreachable("unknown symbol kind"); |
| 402 | } |
| 403 | |
Rui Ueyama | f52496e | 2017-11-03 21:21:47 | [diff] [blame] | 404 | // A buffer class that is large enough to hold any Symbol-derived |
Rui Ueyama | 616cd99 | 2017-10-31 16:10:24 | [diff] [blame] | 405 | // object. We allocate memory using this class and instantiate a symbol |
| 406 | // using the placement new. |
| 407 | union SymbolUnion { |
Rui Ueyama | f78d097 | 2017-10-31 17:07:47 | [diff] [blame] | 408 | alignas(DefinedRegular) char A[sizeof(DefinedRegular)]; |
| 409 | alignas(DefinedCommon) char B[sizeof(DefinedCommon)]; |
| 410 | alignas(DefinedAbsolute) char C[sizeof(DefinedAbsolute)]; |
| 411 | alignas(DefinedSynthetic) char D[sizeof(DefinedSynthetic)]; |
| 412 | alignas(Lazy) char E[sizeof(Lazy)]; |
| 413 | alignas(Undefined) char F[sizeof(Undefined)]; |
| 414 | alignas(DefinedImportData) char G[sizeof(DefinedImportData)]; |
| 415 | alignas(DefinedImportThunk) char H[sizeof(DefinedImportThunk)]; |
| 416 | alignas(DefinedLocalImport) char I[sizeof(DefinedLocalImport)]; |
Peter Collingbourne | 79a5e6b | 2016-12-09 21:55:24 | [diff] [blame] | 417 | }; |
| 418 | |
| 419 | template <typename T, typename... ArgT> |
Rui Ueyama | f483da0 | 2017-11-03 22:48:47 | [diff] [blame] | 420 | void replaceSymbol(Symbol *S, ArgT &&... Arg) { |
Sam Clegg | 38f52b2 | 2018-02-13 17:32:31 | [diff] [blame] | 421 | static_assert(std::is_trivially_destructible<T>(), |
| 422 | "Symbol types must be trivially destructible"); |
Rui Ueyama | 616cd99 | 2017-10-31 16:10:24 | [diff] [blame] | 423 | static_assert(sizeof(T) <= sizeof(SymbolUnion), "Symbol too small"); |
| 424 | static_assert(alignof(T) <= alignof(SymbolUnion), |
| 425 | "SymbolUnion not aligned enough"); |
Rui Ueyama | 38781a5 | 2018-02-14 22:43:43 | [diff] [blame] | 426 | assert(static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr && |
| 427 | "Not a Symbol"); |
Rui Ueyama | 616cd99 | 2017-10-31 16:10:24 | [diff] [blame] | 428 | new (S) T(std::forward<ArgT>(Arg)...); |
Peter Collingbourne | 79a5e6b | 2016-12-09 21:55:24 | [diff] [blame] | 429 | } |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 430 | } // namespace coff |
Rui Ueyama | ce03926 | 2017-01-06 10:04:08 | [diff] [blame] | 431 | |
Rui Ueyama | f52496e | 2017-11-03 21:21:47 | [diff] [blame] | 432 | std::string toString(coff::Symbol &B); |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 433 | } // namespace lld |
| 434 | |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 435 | #endif |