Coverage Report

Created: 2018-01-17 17:22

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/lld/COFF/Symbols.h
Line
Count
Source (jump to first uncovered line)
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
#ifndef LLD_COFF_SYMBOLS_H
11
#define LLD_COFF_SYMBOLS_H
12
13
#include "Chunks.h"
14
#include "Config.h"
15
#include "lld/Common/LLVM.h"
16
#include "lld/Common/Memory.h"
17
#include "llvm/ADT/ArrayRef.h"
18
#include "llvm/Object/Archive.h"
19
#include "llvm/Object/COFF.h"
20
#include <atomic>
21
#include <memory>
22
#include <vector>
23
24
namespace lld {
25
namespace coff {
26
27
using llvm::object::Archive;
28
using llvm::object::COFFSymbolRef;
29
using llvm::object::coff_import_header;
30
using llvm::object::coff_symbol_generic;
31
32
class ArchiveFile;
33
class InputFile;
34
class ObjFile;
35
class SymbolTable;
36
37
// The base class for real symbol classes.
38
class Symbol {
39
public:
40
  enum Kind {
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,
47
    DefinedCommonKind,
48
    DefinedLocalImportKind,
49
    DefinedImportThunkKind,
50
    DefinedImportDataKind,
51
    DefinedAbsoluteKind,
52
    DefinedSyntheticKind,
53
54
    UndefinedKind,
55
    LazyKind,
56
57
    LastDefinedCOFFKind = DefinedCommonKind,
58
    LastDefinedKind = DefinedSyntheticKind,
59
  };
60
61
0
  Kind kind() const { return static_cast<Kind>(SymbolKind); }
62
63
  // Returns true if this is an external symbol.
64
0
  bool isExternal() { return IsExternal; }
65
66
  // Returns the symbol name.
67
  StringRef getName();
68
69
  // Returns the file from which this symbol was created.
70
  InputFile *getFile();
71
72
  // Indicates that this symbol will be included in the final image. Only valid
73
  // after calling markLive.
74
  bool isLive() const;
75
76
protected:
77
  friend SymbolTable;
78
  explicit Symbol(Kind K, StringRef N = "")
79
      : SymbolKind(K), IsExternal(true), IsCOMDAT(false),
80
        WrittenToSymtab(false), PendingArchiveLoad(false), IsGCRoot(false),
81
0
        Name(N) {}
82
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
89
public:
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
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
102
  /// True if we've already added this symbol to the list of GC roots.
103
  unsigned IsGCRoot : 1;
104
105
protected:
106
  StringRef Name;
107
};
108
109
// The base class for any defined symbols, including absolute symbols,
110
// etc.
111
class Defined : public Symbol {
112
public:
113
0
  Defined(Kind K, StringRef N) : Symbol(K, N) {}
114
115
0
  static bool classof(const Symbol *S) { return S->kind() <= LastDefinedKind; }
116
117
  // Returns the RVA (relative virtual address) of this symbol. The
118
  // writer sets and uses RVAs.
119
  uint64_t getRVA();
120
121
  // Returns the chunk containing this symbol. Absolute symbols and __ImageBase
122
  // do not have chunks, so this may return null.
123
  Chunk *getChunk();
124
};
125
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.
130
class DefinedCOFF : public Defined {
131
  friend Symbol;
132
133
public:
134
  DefinedCOFF(Kind K, InputFile *F, StringRef N, const coff_symbol_generic *S)
135
0
      : Defined(K, N), File(F), Sym(S) {}
136
137
0
  static bool classof(const Symbol *S) {
138
0
    return S->kind() <= LastDefinedCOFFKind;
139
0
  }
140
141
0
  InputFile *getFile() { return File; }
142
143
  COFFSymbolRef getCOFFSymbol();
144
145
  InputFile *File;
146
147
protected:
148
  const coff_symbol_generic *Sym;
149
};
150
151
// Regular defined symbols read from object file symbol tables.
152
class DefinedRegular : public DefinedCOFF {
153
public:
154
  DefinedRegular(InputFile *F, StringRef N, bool IsCOMDAT,
155
                 bool IsExternal = false,
156
                 const coff_symbol_generic *S = nullptr,
157
                 SectionChunk *C = nullptr)
158
0
      : DefinedCOFF(DefinedRegularKind, F, N, S), Data(C ? &C->Repl : nullptr) {
159
0
    this->IsExternal = IsExternal;
160
0
    this->IsCOMDAT = IsCOMDAT;
161
0
  }
162
163
0
  static bool classof(const Symbol *S) {
164
0
    return S->kind() == DefinedRegularKind;
165
0
  }
166
167
0
  uint64_t getRVA() const { return (*Data)->getRVA() + Sym->Value; }
168
0
  bool isCOMDAT() const { return IsCOMDAT; }
169
0
  SectionChunk *getChunk() const { return *Data; }
170
0
  uint32_t getValue() const { return Sym->Value; }
171
172
  SectionChunk **Data;
173
};
174
175
class DefinedCommon : public DefinedCOFF {
176
public:
177
  DefinedCommon(InputFile *F, StringRef N, uint64_t Size,
178
                const coff_symbol_generic *S = nullptr,
179
                CommonChunk *C = nullptr)
180
0
      : DefinedCOFF(DefinedCommonKind, F, N, S), Data(C), Size(Size) {
181
0
    this->IsExternal = true;
182
0
  }
183
184
0
  static bool classof(const Symbol *S) {
185
0
    return S->kind() == DefinedCommonKind;
186
0
  }
187
188
0
  uint64_t getRVA() { return Data->getRVA(); }
189
0
  CommonChunk *getChunk() { return Data; }
190
191
private:
192
  friend SymbolTable;
193
0
  uint64_t getSize() const { return Size; }
194
  CommonChunk *Data;
195
  uint64_t Size;
196
};
197
198
// Absolute symbols.
199
class DefinedAbsolute : public Defined {
200
public:
201
  DefinedAbsolute(StringRef N, COFFSymbolRef S)
202
0
      : Defined(DefinedAbsoluteKind, N), VA(S.getValue()) {
203
0
    IsExternal = S.isExternal();
204
0
  }
205
206
  DefinedAbsolute(StringRef N, uint64_t V)
207
0
      : Defined(DefinedAbsoluteKind, N), VA(V) {}
208
209
0
  static bool classof(const Symbol *S) {
210
0
    return S->kind() == DefinedAbsoluteKind;
211
0
  }
212
213
0
  uint64_t getRVA() { return VA - Config->ImageBase; }
214
0
  void setVA(uint64_t V) { VA = V; }
215
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;
220
0
  uint16_t getSecIdx() { return OutputSectionIndex; }
221
222
private:
223
  uint64_t VA;
224
};
225
226
// This symbol is used for linker-synthesized symbols like __ImageBase and
227
// __safe_se_handler_table.
228
class DefinedSynthetic : public Defined {
229
public:
230
  explicit DefinedSynthetic(StringRef Name, Chunk *C)
231
0
      : Defined(DefinedSyntheticKind, Name), C(C) {}
232
233
0
  static bool classof(const Symbol *S) {
234
0
    return S->kind() == DefinedSyntheticKind;
235
0
  }
236
237
  // A null chunk indicates that this is __ImageBase. Otherwise, this is some
238
  // other synthesized chunk, like SEHTableChunk.
239
0
  uint32_t getRVA() { return C ? C->getRVA() : 0; }
240
0
  Chunk *getChunk() { return C; }
241
242
private:
243
  Chunk *C;
244
};
245
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.
251
class Lazy : public Symbol {
252
public:
253
  Lazy(ArchiveFile *F, const Archive::Symbol S)
254
0
      : Symbol(LazyKind, S.getName()), File(F), Sym(S) {}
255
256
0
  static bool classof(const Symbol *S) { return S->kind() == LazyKind; }
257
258
  ArchiveFile *File;
259
260
private:
261
  friend SymbolTable;
262
263
private:
264
  const Archive::Symbol Sym;
265
};
266
267
// Undefined symbols.
268
class Undefined : public Symbol {
269
public:
270
0
  explicit Undefined(StringRef N) : Symbol(UndefinedKind, N) {}
271
272
0
  static bool classof(const Symbol *S) { return S->kind() == UndefinedKind; }
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.
278
  Symbol *WeakAlias = nullptr;
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();
284
};
285
286
// Windows-specific classes.
287
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:
294
  DefinedImportData(StringRef N, ImportFile *F)
295
0
      : Defined(DefinedImportDataKind, N), File(F) {
296
0
  }
297
298
0
  static bool classof(const Symbol *S) {
299
0
    return S->kind() == DefinedImportDataKind;
300
0
  }
301
302
0
  uint64_t getRVA() { return File->Location->getRVA(); }
303
0
  Chunk *getChunk() { return File->Location; }
304
0
  void setLocation(Chunk *AddressTable) { File->Location = AddressTable; }
305
306
0
  StringRef getDLLName() { return File->DLLName; }
307
0
  StringRef getExternalName() { return File->ExternalName; }
308
0
  uint16_t getOrdinal() { return File->Hdr->OrdinalHint; }
309
310
  ImportFile *File;
311
};
312
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:
320
  DefinedImportThunk(StringRef Name, DefinedImportData *S, uint16_t Machine);
321
322
0
  static bool classof(const Symbol *S) {
323
0
    return S->kind() == DefinedImportThunkKind;
324
0
  }
325
326
0
  uint64_t getRVA() { return Data->getRVA(); }
327
0
  Chunk *getChunk() { return Data; }
328
329
  DefinedImportData *WrappedSym;
330
331
private:
332
  Chunk *Data;
333
};
334
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)
343
0
      : Defined(DefinedLocalImportKind, N), Data(make<LocalImportChunk>(S)) {}
344
345
0
  static bool classof(const Symbol *S) {
346
0
    return S->kind() == DefinedLocalImportKind;
347
0
  }
348
349
0
  uint64_t getRVA() { return Data->getRVA(); }
350
0
  Chunk *getChunk() { return Data; }
351
352
private:
353
  LocalImportChunk *Data;
354
};
355
356
0
inline uint64_t Defined::getRVA() {
357
0
  switch (kind()) {
358
0
  case DefinedAbsoluteKind:
359
0
    return cast<DefinedAbsolute>(this)->getRVA();
360
0
  case DefinedSyntheticKind:
361
0
    return cast<DefinedSynthetic>(this)->getRVA();
362
0
  case DefinedImportDataKind:
363
0
    return cast<DefinedImportData>(this)->getRVA();
364
0
  case DefinedImportThunkKind:
365
0
    return cast<DefinedImportThunk>(this)->getRVA();
366
0
  case DefinedLocalImportKind:
367
0
    return cast<DefinedLocalImport>(this)->getRVA();
368
0
  case DefinedCommonKind:
369
0
    return cast<DefinedCommon>(this)->getRVA();
370
0
  case DefinedRegularKind:
371
0
    return cast<DefinedRegular>(this)->getRVA();
372
0
  case LazyKind:
373
0
  case UndefinedKind:
374
0
    llvm_unreachable("Cannot get the address for an undefined symbol.");
375
0
  }
376
0
  llvm_unreachable("unknown symbol kind");
377
0
}
378
379
0
inline Chunk *Defined::getChunk() {
380
0
  switch (kind()) {
381
0
  case DefinedRegularKind:
382
0
    return cast<DefinedRegular>(this)->getChunk();
383
0
  case DefinedAbsoluteKind:
384
0
    return nullptr;
385
0
  case DefinedSyntheticKind:
386
0
    return cast<DefinedSynthetic>(this)->getChunk();
387
0
  case DefinedImportDataKind:
388
0
    return cast<DefinedImportData>(this)->getChunk();
389
0
  case DefinedImportThunkKind:
390
0
    return cast<DefinedImportThunk>(this)->getChunk();
391
0
  case DefinedLocalImportKind:
392
0
    return cast<DefinedLocalImport>(this)->getChunk();
393
0
  case DefinedCommonKind:
394
0
    return cast<DefinedCommon>(this)->getChunk();
395
0
  case LazyKind:
396
0
  case UndefinedKind:
397
0
    llvm_unreachable("Cannot get the chunk of an undefined symbol.");
398
0
  }
399
0
  llvm_unreachable("unknown symbol kind");
400
0
}
401
402
// A buffer class that is large enough to hold any Symbol-derived
403
// object. We allocate memory using this class and instantiate a symbol
404
// using the placement new.
405
union SymbolUnion {
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)];
415
};
416
417
template <typename T, typename... ArgT>
418
0
void replaceSymbol(Symbol *S, ArgT &&... Arg) {
419
0
  static_assert(sizeof(T) <= sizeof(SymbolUnion), "Symbol too small");
420
0
  static_assert(alignof(T) <= alignof(SymbolUnion),
421
0
                "SymbolUnion not aligned enough");
422
0
  assert(static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr &&
423
0
         "Not a Symbol");
424
0
  new (S) T(std::forward<ArgT>(Arg)...);
425
0
}
Unexecuted instantiation: void lld::coff::replaceSymbol<lld::coff::Undefined, llvm::StringRef>(lld::coff::Symbol*, llvm::StringRef&&)
Unexecuted instantiation: void lld::coff::replaceSymbol<lld::coff::DefinedLocalImport, llvm::StringRef&, lld::coff::Defined*&>(lld::coff::Symbol*, llvm::StringRef&&&, lld::coff::Defined*&&&)
Unexecuted instantiation: void lld::coff::replaceSymbol<lld::coff::DefinedAbsolute, llvm::StringRef&, int>(lld::coff::Symbol*, llvm::StringRef&&&, int&&)
Unexecuted instantiation: void lld::coff::replaceSymbol<lld::coff::Undefined, llvm::StringRef&>(lld::coff::Symbol*, llvm::StringRef&&&)
Unexecuted instantiation: void lld::coff::replaceSymbol<lld::coff::Lazy, lld::coff::ArchiveFile*&, llvm::object::Archive::Symbol const&>(lld::coff::Symbol*, lld::coff::ArchiveFile*&&&, llvm::object::Archive::Symbol const&&&)
Unexecuted instantiation: void lld::coff::replaceSymbol<lld::coff::DefinedAbsolute, llvm::StringRef&, llvm::object::COFFSymbolRef&>(lld::coff::Symbol*, llvm::StringRef&&&, llvm::object::COFFSymbolRef&&&)
Unexecuted instantiation: void lld::coff::replaceSymbol<lld::coff::DefinedAbsolute, llvm::StringRef&, unsigned long long&>(lld::coff::Symbol*, llvm::StringRef&&&, unsigned long long&&&)
Unexecuted instantiation: void lld::coff::replaceSymbol<lld::coff::DefinedSynthetic, llvm::StringRef&, lld::coff::Chunk*&>(lld::coff::Symbol*, llvm::StringRef&&&, lld::coff::Chunk*&&&)
Unexecuted instantiation: void lld::coff::replaceSymbol<lld::coff::DefinedRegular, lld::coff::InputFile*&, llvm::StringRef&, bool, bool, llvm::object::coff_symbol_generic const*&, lld::coff::SectionChunk*&>(lld::coff::Symbol*, lld::coff::InputFile*&&&, llvm::StringRef&&&, bool&&, bool&&, llvm::object::coff_symbol_generic const*&&&, lld::coff::SectionChunk*&&&)
Unexecuted instantiation: void lld::coff::replaceSymbol<lld::coff::DefinedRegular, lld::coff::InputFile*&, llvm::StringRef&, bool, bool, llvm::object::coff_symbol_generic const*&, std::nullptr_t>(lld::coff::Symbol*, lld::coff::InputFile*&&&, llvm::StringRef&&&, bool&&, bool&&, llvm::object::coff_symbol_generic const*&&&, std::nullptr_t&&)
Unexecuted instantiation: void lld::coff::replaceSymbol<lld::coff::DefinedCommon, lld::coff::InputFile*&, llvm::StringRef&, unsigned long long&, llvm::object::coff_symbol_generic const*&, lld::coff::CommonChunk*&>(lld::coff::Symbol*, lld::coff::InputFile*&&&, llvm::StringRef&&&, unsigned long long&&&, llvm::object::coff_symbol_generic const*&&&, lld::coff::CommonChunk*&&&)
Unexecuted instantiation: void lld::coff::replaceSymbol<lld::coff::DefinedImportData, llvm::StringRef&, lld::coff::ImportFile*&>(lld::coff::Symbol*, llvm::StringRef&&&, lld::coff::ImportFile*&&&)
Unexecuted instantiation: void lld::coff::replaceSymbol<lld::coff::DefinedImportThunk, llvm::StringRef&, lld::coff::DefinedImportData*&, unsigned short&>(lld::coff::Symbol*, llvm::StringRef&&&, lld::coff::DefinedImportData*&&&, unsigned short&&&)
Unexecuted instantiation: void lld::coff::replaceSymbol<lld::coff::DefinedSynthetic, llvm::StringRef, lld::coff::SEHTableChunk*&>(lld::coff::Symbol*, llvm::StringRef&&, lld::coff::SEHTableChunk*&&&)
426
} // namespace coff
427
428
std::string toString(coff::Symbol &B);
429
} // namespace lld
430
431
#endif