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