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 | 9381eb1 | 2016-12-18 14:06:06 | [diff] [blame] | 15 | #include "Memory.h" |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 16 | #include "lld/Core/LLVM.h" |
| 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; |
Peter Collingbourne | f7b27d1 | 2015-06-30 00:47:52 | [diff] [blame] | 33 | class BitcodeFile; |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 34 | class InputFile; |
| 35 | class ObjectFile; |
Peter Collingbourne | 79a5e6b | 2016-12-09 21:55:24 | [diff] [blame] | 36 | struct Symbol; |
| 37 | class SymbolTable; |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 38 | |
| 39 | // The base class for real symbol classes. |
| 40 | class SymbolBody { |
| 41 | public: |
| 42 | enum Kind { |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 43 | // The order of these is significant. We start with the regular defined |
| 44 | // symbols as those are the most prevelant and the zero tag is the cheapest |
| 45 | // to set. Among the defined kinds, the lower the kind is preferred over |
| 46 | // the higher kind when testing wether one symbol should take precedence |
| 47 | // over another. |
| 48 | DefinedRegularKind = 0, |
Rui Ueyama | efb7e1a | 2015-06-20 07:21:57 | [diff] [blame] | 49 | DefinedCommonKind, |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 50 | DefinedLocalImportKind, |
| 51 | DefinedImportThunkKind, |
| 52 | DefinedImportDataKind, |
| 53 | DefinedAbsoluteKind, |
Rui Ueyama | 3cb895c | 2015-07-24 22:58:44 | [diff] [blame] | 54 | DefinedRelativeKind, |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 55 | DefinedBitcodeKind, |
| 56 | |
Rui Ueyama | e251476 | 2015-06-15 19:06:53 | [diff] [blame] | 57 | UndefinedKind, |
Rui Ueyama | 8d3010a | 2015-06-30 19:35:21 | [diff] [blame] | 58 | LazyKind, |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 59 | |
| 60 | LastDefinedCOFFKind = DefinedCommonKind, |
| 61 | LastDefinedKind = DefinedBitcodeKind, |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 62 | }; |
| 63 | |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 64 | Kind kind() const { return static_cast<Kind>(SymbolKind); } |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 65 | |
| 66 | // Returns true if this is an external symbol. |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 67 | bool isExternal() { return IsExternal; } |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 68 | |
| 69 | // Returns the symbol name. |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 70 | StringRef getName(); |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 71 | |
Rui Ueyama | a45d45e | 2016-12-07 23:17:02 | [diff] [blame] | 72 | // Returns the file from which this symbol was created. |
| 73 | InputFile *getFile(); |
| 74 | |
Peter Collingbourne | 79a5e6b | 2016-12-09 21:55:24 | [diff] [blame] | 75 | Symbol *symbol(); |
| 76 | const Symbol *symbol() const { |
| 77 | return const_cast<SymbolBody *>(this)->symbol(); |
| 78 | } |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 79 | |
| 80 | protected: |
Peter Collingbourne | 79a5e6b | 2016-12-09 21:55:24 | [diff] [blame] | 81 | friend SymbolTable; |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 82 | explicit SymbolBody(Kind K, StringRef N = "") |
| 83 | : SymbolKind(K), IsExternal(true), IsCOMDAT(false), |
Peter Collingbourne | 9911128 | 2016-12-11 22:15:20 | [diff] [blame] | 84 | IsReplaceable(false), WrittenToSymtab(false), Name(N) {} |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 85 | |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 86 | const unsigned SymbolKind : 8; |
| 87 | unsigned IsExternal : 1; |
| 88 | |
| 89 | // This bit is used by the \c DefinedRegular subclass. |
| 90 | unsigned IsCOMDAT : 1; |
| 91 | |
| 92 | // This bit is used by the \c DefinedBitcode subclass. |
| 93 | unsigned IsReplaceable : 1; |
| 94 | |
Peter Collingbourne | 9911128 | 2016-12-11 22:15:20 | [diff] [blame] | 95 | public: |
| 96 | // This bit is used by Writer::createSymbolAndStringTable(). |
| 97 | unsigned WrittenToSymtab : 1; |
| 98 | |
| 99 | protected: |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 100 | StringRef Name; |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 101 | }; |
| 102 | |
| 103 | // The base class for any defined symbols, including absolute symbols, |
| 104 | // etc. |
| 105 | class Defined : public SymbolBody { |
| 106 | public: |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 107 | Defined(Kind K, StringRef N = "") : SymbolBody(K, N) {} |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 108 | |
| 109 | static bool classof(const SymbolBody *S) { |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 110 | return S->kind() <= LastDefinedKind; |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 111 | } |
| 112 | |
| 113 | // Returns the RVA (relative virtual address) of this symbol. The |
| 114 | // writer sets and uses RVAs. |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 115 | uint64_t getRVA(); |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 116 | |
Rui Ueyama | eb26e1d | 2015-07-29 16:30:45 | [diff] [blame] | 117 | // Returns the RVA relative to the beginning of the output section. |
| 118 | // Used to implement SECREL relocation type. |
| 119 | uint64_t getSecrel(); |
| 120 | |
| 121 | // Returns the output section index. |
| 122 | // Used to implement SECTION relocation type. |
| 123 | uint64_t getSectionIndex(); |
Rui Ueyama | 8bc43a1 | 2015-07-29 19:25:00 | [diff] [blame] | 124 | |
| 125 | // Returns true if this symbol points to an executable (e.g. .text) section. |
| 126 | // Used to implement ARM relocations. |
| 127 | bool isExecutable(); |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 128 | }; |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 129 | |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 130 | // Symbols defined via a COFF object file. |
| 131 | class DefinedCOFF : public Defined { |
| 132 | friend SymbolBody; |
| 133 | public: |
| 134 | DefinedCOFF(Kind K, ObjectFile *F, COFFSymbolRef S) |
Rui Ueyama | c15139b | 2015-06-30 00:10:54 | [diff] [blame] | 135 | : Defined(K), File(F), Sym(S.getGeneric()) {} |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 136 | |
| 137 | static bool classof(const SymbolBody *S) { |
| 138 | return S->kind() <= LastDefinedCOFFKind; |
| 139 | } |
| 140 | |
Rui Ueyama | a45d45e | 2016-12-07 23:17:02 | [diff] [blame] | 141 | ObjectFile *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 | |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 145 | ObjectFile *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: |
Rui Ueyama | 68633f1 | 2015-06-25 23:22:00 | [diff] [blame] | 154 | DefinedRegular(ObjectFile *F, COFFSymbolRef S, SectionChunk *C) |
Rui Ueyama | de88072 | 2015-09-25 16:20:24 | [diff] [blame] | 155 | : DefinedCOFF(DefinedRegularKind, F, S), Data(&C->Repl) { |
Rui Ueyama | c15139b | 2015-06-30 00:10:54 | [diff] [blame] | 156 | IsExternal = S.isExternal(); |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 157 | IsCOMDAT = C->isCOMDAT(); |
| 158 | } |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 159 | |
| 160 | static bool classof(const SymbolBody *S) { |
| 161 | return S->kind() == DefinedRegularKind; |
| 162 | } |
| 163 | |
Rui Ueyama | c15139b | 2015-06-30 00:10:54 | [diff] [blame] | 164 | uint64_t getRVA() { return (*Data)->getRVA() + Sym->Value; } |
Rui Ueyama | 9b921e5 | 2015-06-25 22:00:42 | [diff] [blame] | 165 | bool isCOMDAT() { return IsCOMDAT; } |
Chandler Carruth | 59013c3 | 2015-06-29 21:12:49 | [diff] [blame] | 166 | SectionChunk *getChunk() { return *Data; } |
Rui Ueyama | c15139b | 2015-06-30 00:10:54 | [diff] [blame] | 167 | uint32_t getValue() { return Sym->Value; } |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 168 | |
Rui Ueyama | efb7e1a | 2015-06-20 07:21:57 | [diff] [blame] | 169 | private: |
Rui Ueyama | 9b921e5 | 2015-06-25 22:00:42 | [diff] [blame] | 170 | SectionChunk **Data; |
Rui Ueyama | efb7e1a | 2015-06-20 07:21:57 | [diff] [blame] | 171 | }; |
| 172 | |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 173 | class DefinedCommon : public DefinedCOFF { |
Rui Ueyama | efb7e1a | 2015-06-20 07:21:57 | [diff] [blame] | 174 | public: |
Rui Ueyama | 68633f1 | 2015-06-25 23:22:00 | [diff] [blame] | 175 | DefinedCommon(ObjectFile *F, COFFSymbolRef S, CommonChunk *C) |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 176 | : DefinedCOFF(DefinedCommonKind, F, S), Data(C) { |
Rui Ueyama | c15139b | 2015-06-30 00:10:54 | [diff] [blame] | 177 | IsExternal = S.isExternal(); |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 178 | } |
Rui Ueyama | efb7e1a | 2015-06-20 07:21:57 | [diff] [blame] | 179 | |
| 180 | static bool classof(const SymbolBody *S) { |
| 181 | return S->kind() == DefinedCommonKind; |
| 182 | } |
| 183 | |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 184 | uint64_t getRVA() { return Data->getRVA(); } |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 185 | |
| 186 | private: |
Peter Collingbourne | 79a5e6b | 2016-12-09 21:55:24 | [diff] [blame] | 187 | friend SymbolTable; |
Rui Ueyama | c15139b | 2015-06-30 00:10:54 | [diff] [blame] | 188 | uint64_t getSize() { return Sym->Value; } |
Rui Ueyama | fc510f4 | 2015-06-25 19:10:58 | [diff] [blame] | 189 | CommonChunk *Data; |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 190 | }; |
| 191 | |
| 192 | // Absolute symbols. |
| 193 | class DefinedAbsolute : public Defined { |
| 194 | public: |
Rui Ueyama | ccde19d | 2015-06-26 03:09:23 | [diff] [blame] | 195 | DefinedAbsolute(StringRef N, COFFSymbolRef S) |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 196 | : Defined(DefinedAbsoluteKind, N), VA(S.getValue()) { |
| 197 | IsExternal = S.isExternal(); |
| 198 | } |
Rui Ueyama | ccde19d | 2015-06-26 03:09:23 | [diff] [blame] | 199 | |
| 200 | DefinedAbsolute(StringRef N, uint64_t V) |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 201 | : Defined(DefinedAbsoluteKind, N), VA(V) {} |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 202 | |
| 203 | static bool classof(const SymbolBody *S) { |
| 204 | return S->kind() == DefinedAbsoluteKind; |
| 205 | } |
| 206 | |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 207 | uint64_t getRVA() { return VA - Config->ImageBase; } |
Rui Ueyama | cd3f99b | 2015-07-24 23:51:14 | [diff] [blame] | 208 | void setVA(uint64_t V) { VA = V; } |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 209 | |
| 210 | private: |
Rui Ueyama | ccde19d | 2015-06-26 03:09:23 | [diff] [blame] | 211 | uint64_t VA; |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 212 | }; |
| 213 | |
Rui Ueyama | 3cb895c | 2015-07-24 22:58:44 | [diff] [blame] | 214 | // This is a kind of absolute symbol but relative to the image base. |
| 215 | // Unlike absolute symbols, relocations referring this kind of symbols |
| 216 | // are subject of the base relocation. This type is used rarely -- |
| 217 | // mainly for __ImageBase. |
| 218 | class DefinedRelative : public Defined { |
| 219 | public: |
| 220 | explicit DefinedRelative(StringRef Name, uint64_t V = 0) |
| 221 | : Defined(DefinedRelativeKind, Name), RVA(V) {} |
| 222 | |
| 223 | static bool classof(const SymbolBody *S) { |
| 224 | return S->kind() == DefinedRelativeKind; |
| 225 | } |
| 226 | |
| 227 | uint64_t getRVA() { return RVA; } |
| 228 | void setRVA(uint64_t V) { RVA = V; } |
| 229 | |
| 230 | private: |
| 231 | uint64_t RVA; |
| 232 | }; |
| 233 | |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 234 | // This class represents a symbol defined in an archive file. It is |
| 235 | // created from an archive file header, and it knows how to load an |
| 236 | // object file from an archive to replace itself with a defined |
| 237 | // symbol. If the resolver finds both Undefined and Lazy for |
| 238 | // the same name, it will ask the Lazy to load a file. |
| 239 | class Lazy : public SymbolBody { |
| 240 | public: |
| 241 | Lazy(ArchiveFile *F, const Archive::Symbol S) |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 242 | : SymbolBody(LazyKind, S.getName()), File(F), Sym(S) {} |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 243 | |
| 244 | static bool classof(const SymbolBody *S) { return S->kind() == LazyKind; } |
| 245 | |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 246 | ArchiveFile *File; |
Rui Ueyama | a45d45e | 2016-12-07 23:17:02 | [diff] [blame] | 247 | |
| 248 | private: |
Peter Collingbourne | 79a5e6b | 2016-12-09 21:55:24 | [diff] [blame] | 249 | friend SymbolTable; |
| 250 | |
| 251 | private: |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 252 | const Archive::Symbol Sym; |
| 253 | }; |
| 254 | |
| 255 | // Undefined symbols. |
| 256 | class Undefined : public SymbolBody { |
| 257 | public: |
Rui Ueyama | 4897596 | 2015-07-01 22:32:23 | [diff] [blame] | 258 | explicit Undefined(StringRef N) : SymbolBody(UndefinedKind, N) {} |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 259 | |
| 260 | static bool classof(const SymbolBody *S) { |
| 261 | return S->kind() == UndefinedKind; |
| 262 | } |
| 263 | |
| 264 | // An undefined symbol can have a fallback symbol which gives an |
| 265 | // undefined symbol a second chance if it would remain undefined. |
| 266 | // If it remains undefined, it'll be replaced with whatever the |
| 267 | // Alias pointer points to. |
Peter Collingbourne | da2f094 | 2015-07-03 22:03:36 | [diff] [blame] | 268 | SymbolBody *WeakAlias = nullptr; |
Peter Collingbourne | 2612a32 | 2015-07-04 05:28:41 | [diff] [blame] | 269 | |
| 270 | // If this symbol is external weak, try to resolve it to a defined |
| 271 | // symbol by searching the chain of fallback symbols. Returns the symbol if |
| 272 | // successful, otherwise returns null. |
| 273 | Defined *getWeakAlias(); |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 274 | }; |
| 275 | |
| 276 | // Windows-specific classes. |
| 277 | |
Rui Ueyama | 7c4fcdd | 2015-05-29 15:49:09 | [diff] [blame] | 278 | // This class represents a symbol imported from a DLL. This has two |
| 279 | // names for internal use and external use. The former is used for |
| 280 | // name resolution, and the latter is used for the import descriptor |
| 281 | // table in an output. The former has "__imp_" prefix. |
| 282 | class DefinedImportData : public Defined { |
| 283 | public: |
Peter Collingbourne | 79a5e6b | 2016-12-09 21:55:24 | [diff] [blame] | 284 | DefinedImportData(StringRef N, ImportFile *F) |
| 285 | : Defined(DefinedImportDataKind, N), File(F) { |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 286 | } |
Rui Ueyama | 7c4fcdd | 2015-05-29 15:49:09 | [diff] [blame] | 287 | |
| 288 | static bool classof(const SymbolBody *S) { |
| 289 | return S->kind() == DefinedImportDataKind; |
| 290 | } |
| 291 | |
Peter Collingbourne | 79a5e6b | 2016-12-09 21:55:24 | [diff] [blame] | 292 | uint64_t getRVA() { return File->Location->getRVA(); } |
| 293 | StringRef getDLLName() { return File->DLLName; } |
| 294 | StringRef getExternalName() { return File->ExternalName; } |
| 295 | void setLocation(Chunk *AddressTable) { File->Location = AddressTable; } |
| 296 | uint16_t getOrdinal() { return File->Hdr->OrdinalHint; } |
Rui Ueyama | 7c4fcdd | 2015-05-29 15:49:09 | [diff] [blame] | 297 | |
| 298 | private: |
Peter Collingbourne | 79a5e6b | 2016-12-09 21:55:24 | [diff] [blame] | 299 | ImportFile *File; |
Rui Ueyama | 7c4fcdd | 2015-05-29 15:49:09 | [diff] [blame] | 300 | }; |
| 301 | |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 302 | // This class represents a symbol for a jump table entry which jumps |
| 303 | // to a function in a DLL. Linker are supposed to create such symbols |
| 304 | // without "__imp_" prefix for all function symbols exported from |
| 305 | // DLLs, so that you can call DLL functions as regular functions with |
| 306 | // a regular name. A function pointer is given as a DefinedImportData. |
| 307 | class DefinedImportThunk : public Defined { |
| 308 | public: |
Rui Ueyama | 5e706b3 | 2015-07-25 21:54:50 | [diff] [blame] | 309 | DefinedImportThunk(StringRef Name, DefinedImportData *S, uint16_t Machine); |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 310 | |
| 311 | static bool classof(const SymbolBody *S) { |
| 312 | return S->kind() == DefinedImportThunkKind; |
| 313 | } |
| 314 | |
Rui Ueyama | 28df042 | 2015-07-25 01:16:06 | [diff] [blame] | 315 | uint64_t getRVA() { return Data->getRVA(); } |
Peter Collingbourne | e50f485 | 2016-12-12 18:42:09 | [diff] [blame] | 316 | Chunk *getChunk() { return Data; } |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 317 | |
| 318 | private: |
Peter Collingbourne | e50f485 | 2016-12-12 18:42:09 | [diff] [blame] | 319 | Chunk *Data; |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 320 | }; |
| 321 | |
Rui Ueyama | 88e0f92 | 2015-06-25 03:31:47 | [diff] [blame] | 322 | // If you have a symbol "__imp_foo" in your object file, a symbol name |
| 323 | // "foo" becomes automatically available as a pointer to "__imp_foo". |
| 324 | // This class is for such automatically-created symbols. |
| 325 | // Yes, this is an odd feature. We didn't intend to implement that. |
| 326 | // This is here just for compatibility with MSVC. |
| 327 | class DefinedLocalImport : public Defined { |
| 328 | public: |
| 329 | DefinedLocalImport(StringRef N, Defined *S) |
Peter Collingbourne | e50f485 | 2016-12-12 18:42:09 | [diff] [blame] | 330 | : Defined(DefinedLocalImportKind, N), Data(make<LocalImportChunk>(S)) {} |
Rui Ueyama | 88e0f92 | 2015-06-25 03:31:47 | [diff] [blame] | 331 | |
| 332 | static bool classof(const SymbolBody *S) { |
| 333 | return S->kind() == DefinedLocalImportKind; |
| 334 | } |
| 335 | |
Peter Collingbourne | 79a5e6b | 2016-12-09 21:55:24 | [diff] [blame] | 336 | uint64_t getRVA() { return Data->getRVA(); } |
Peter Collingbourne | e50f485 | 2016-12-12 18:42:09 | [diff] [blame] | 337 | Chunk *getChunk() { return Data; } |
Rui Ueyama | 88e0f92 | 2015-06-25 03:31:47 | [diff] [blame] | 338 | |
| 339 | private: |
Peter Collingbourne | e50f485 | 2016-12-12 18:42:09 | [diff] [blame] | 340 | LocalImportChunk *Data; |
Rui Ueyama | 88e0f92 | 2015-06-25 03:31:47 | [diff] [blame] | 341 | }; |
| 342 | |
Peter Collingbourne | 60c1616 | 2015-06-01 20:10:10 | [diff] [blame] | 343 | class DefinedBitcode : public Defined { |
Peter Collingbourne | f7b27d1 | 2015-06-30 00:47:52 | [diff] [blame] | 344 | friend SymbolBody; |
Peter Collingbourne | 60c1616 | 2015-06-01 20:10:10 | [diff] [blame] | 345 | public: |
Peter Collingbourne | f7b27d1 | 2015-06-30 00:47:52 | [diff] [blame] | 346 | DefinedBitcode(BitcodeFile *F, StringRef N, bool IsReplaceable) |
| 347 | : Defined(DefinedBitcodeKind, N), File(F) { |
Peter Collingbourne | 79a5e6b | 2016-12-09 21:55:24 | [diff] [blame] | 348 | // IsReplaceable tracks whether the bitcode symbol may be replaced with some |
| 349 | // other (defined, common or bitcode) symbol. This is the case for common, |
| 350 | // comdat and weak external symbols. We try to replace bitcode symbols with |
| 351 | // "real" symbols (see SymbolTable::add{Regular,Bitcode}), and resolve the |
| 352 | // result against the real symbol from the combined LTO object. |
Chandler Carruth | 64c17c7 | 2015-06-29 21:35:48 | [diff] [blame] | 353 | this->IsReplaceable = IsReplaceable; |
| 354 | } |
Peter Collingbourne | 60c1616 | 2015-06-01 20:10:10 | [diff] [blame] | 355 | |
| 356 | static bool classof(const SymbolBody *S) { |
| 357 | return S->kind() == DefinedBitcodeKind; |
| 358 | } |
Peter Collingbourne | f7b27d1 | 2015-06-30 00:47:52 | [diff] [blame] | 359 | |
Peter Collingbourne | f7b27d1 | 2015-06-30 00:47:52 | [diff] [blame] | 360 | BitcodeFile *File; |
Peter Collingbourne | 60c1616 | 2015-06-01 20:10:10 | [diff] [blame] | 361 | }; |
| 362 | |
Rui Ueyama | cb71c72 | 2015-07-13 22:01:27 | [diff] [blame] | 363 | inline uint64_t Defined::getRVA() { |
| 364 | switch (kind()) { |
| 365 | case DefinedAbsoluteKind: |
| 366 | return cast<DefinedAbsolute>(this)->getRVA(); |
Rui Ueyama | 3cb895c | 2015-07-24 22:58:44 | [diff] [blame] | 367 | case DefinedRelativeKind: |
| 368 | return cast<DefinedRelative>(this)->getRVA(); |
Rui Ueyama | cb71c72 | 2015-07-13 22:01:27 | [diff] [blame] | 369 | case DefinedImportDataKind: |
| 370 | return cast<DefinedImportData>(this)->getRVA(); |
| 371 | case DefinedImportThunkKind: |
| 372 | return cast<DefinedImportThunk>(this)->getRVA(); |
| 373 | case DefinedLocalImportKind: |
| 374 | return cast<DefinedLocalImport>(this)->getRVA(); |
| 375 | case DefinedCommonKind: |
| 376 | return cast<DefinedCommon>(this)->getRVA(); |
| 377 | case DefinedRegularKind: |
| 378 | return cast<DefinedRegular>(this)->getRVA(); |
| 379 | case DefinedBitcodeKind: |
| 380 | llvm_unreachable("There is no address for a bitcode symbol."); |
| 381 | case LazyKind: |
| 382 | case UndefinedKind: |
| 383 | llvm_unreachable("Cannot get the address for an undefined symbol."); |
| 384 | } |
| 385 | llvm_unreachable("unknown symbol kind"); |
| 386 | } |
| 387 | |
Peter Collingbourne | 79a5e6b | 2016-12-09 21:55:24 | [diff] [blame] | 388 | // A real symbol object, SymbolBody, is usually stored within a Symbol. There's |
| 389 | // always one Symbol for each symbol name. The resolver updates the SymbolBody |
| 390 | // stored in the Body field of this object as it resolves symbols. Symbol also |
| 391 | // holds computed properties of symbol names. |
| 392 | struct Symbol { |
| 393 | // True if this symbol was referenced by a regular (non-bitcode) object. |
| 394 | unsigned IsUsedInRegularObj : 1; |
| 395 | |
Peter Collingbourne | 6ee0b4e | 2016-12-15 04:02:23 | [diff] [blame] | 396 | // True if we've seen both a lazy and an undefined symbol with this symbol |
| 397 | // name, which means that we have enqueued an archive member load and should |
| 398 | // not load any more archive members to resolve the same symbol. |
| 399 | unsigned PendingArchiveLoad : 1; |
| 400 | |
Peter Collingbourne | 79a5e6b | 2016-12-09 21:55:24 | [diff] [blame] | 401 | // This field is used to store the Symbol's SymbolBody. This instantiation of |
| 402 | // AlignedCharArrayUnion gives us a struct with a char array field that is |
| 403 | // large and aligned enough to store any derived class of SymbolBody. |
| 404 | llvm::AlignedCharArrayUnion<DefinedRegular, DefinedCommon, DefinedAbsolute, |
| 405 | DefinedRelative, Lazy, Undefined, |
| 406 | DefinedImportData, DefinedImportThunk, |
| 407 | DefinedLocalImport, DefinedBitcode> |
| 408 | Body; |
| 409 | |
| 410 | SymbolBody *body() { |
| 411 | return reinterpret_cast<SymbolBody *>(Body.buffer); |
| 412 | } |
| 413 | const SymbolBody *body() const { return const_cast<Symbol *>(this)->body(); } |
| 414 | }; |
| 415 | |
| 416 | template <typename T, typename... ArgT> |
| 417 | void replaceBody(Symbol *S, ArgT &&... Arg) { |
| 418 | static_assert(sizeof(T) <= sizeof(S->Body), "Body too small"); |
| 419 | static_assert(alignof(T) <= alignof(decltype(S->Body)), |
| 420 | "Body not aligned enough"); |
| 421 | assert(static_cast<SymbolBody *>(static_cast<T *>(nullptr)) == nullptr && |
| 422 | "Not a SymbolBody"); |
| 423 | new (S->Body.buffer) T(std::forward<ArgT>(Arg)...); |
| 424 | } |
| 425 | |
| 426 | inline Symbol *SymbolBody::symbol() { |
| 427 | assert(isExternal()); |
| 428 | return reinterpret_cast<Symbol *>(reinterpret_cast<char *>(this) - |
| 429 | offsetof(Symbol, Body)); |
| 430 | } |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 431 | } // namespace coff |
Rui Ueyama | ce03926 | 2017-01-06 10:04:08 | [diff] [blame^] | 432 | |
| 433 | std::string toString(coff::SymbolBody &B); |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 434 | } // namespace lld |
| 435 | |
Rui Ueyama | 411c6360 | 2015-05-28 19:09:30 | [diff] [blame] | 436 | #endif |