Coverage Report

Created: 2018-01-17 21:32

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/lld/COFF/SymbolTable.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- SymbolTable.cpp ----------------------------------------------------===//
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
#include "SymbolTable.h"
11
#include "Config.h"
12
#include "Driver.h"
13
#include "LTO.h"
14
#include "Symbols.h"
15
#include "lld/Common/ErrorHandler.h"
16
#include "lld/Common/Memory.h"
17
#include "lld/Common/Timer.h"
18
#include "llvm/IR/LLVMContext.h"
19
#include "llvm/Support/Debug.h"
20
#include "llvm/Support/raw_ostream.h"
21
#include <utility>
22
23
using namespace llvm;
24
25
namespace lld {
26
namespace coff {
27
28
static Timer LTOTimer("LTO", Timer::root());
29
30
SymbolTable *Symtab;
31
32
0
void SymbolTable::addFile(InputFile *File) {
33
0
  log("Reading " + toString(File));
34
0
  File->parse();
35
0
36
0
  MachineTypes MT = File->getMachineType();
37
0
  if (Config->Machine == IMAGE_FILE_MACHINE_UNKNOWN) {
38
0
    Config->Machine = MT;
39
0
  } else if (MT != IMAGE_FILE_MACHINE_UNKNOWN && Config->Machine != MT) {
40
0
    fatal(toString(File) + ": machine type " + machineToStr(MT) +
41
0
          " conflicts with " + machineToStr(Config->Machine));
42
0
  }
43
0
44
0
  if (auto *F = dyn_cast<ObjFile>(File)) {
45
0
    ObjFile::Instances.push_back(F);
46
0
  } else if (auto *F = dyn_cast<BitcodeFile>(File)) {
47
0
    BitcodeFile::Instances.push_back(F);
48
0
  } else if (auto *F = dyn_cast<ImportFile>(File)) {
49
0
    ImportFile::Instances.push_back(F);
50
0
  }
51
0
52
0
  StringRef S = File->getDirectives();
53
0
  if (S.empty())
54
0
    return;
55
0
56
0
  log("Directives: " + toString(File) + ": " + S);
57
0
  Driver->parseDirectives(S);
58
0
}
59
60
0
static void errorOrWarn(const Twine &S) {
61
0
  if (Config->Force)
62
0
    warn(S);
63
0
  else
64
0
    error(S);
65
0
}
66
67
0
void SymbolTable::reportRemainingUndefines() {
68
0
  SmallPtrSet<Symbol *, 8> Undefs;
69
0
  DenseMap<Symbol *, Symbol *> LocalImports;
70
0
71
0
  for (auto &I : SymMap) {
72
0
    Symbol *Sym = I.second;
73
0
    auto *Undef = dyn_cast<Undefined>(Sym);
74
0
    if (!Undef)
75
0
      continue;
76
0
    if (!Sym->IsUsedInRegularObj)
77
0
      continue;
78
0
79
0
    StringRef Name = Undef->getName();
80
0
81
0
    // A weak alias may have been resolved, so check for that.
82
0
    if (Defined *D = Undef->getWeakAlias()) {
83
0
      // We want to replace Sym with D. However, we can't just blindly
84
0
      // copy sizeof(SymbolUnion) bytes from D to Sym because D may be an
85
0
      // internal symbol, and internal symbols are stored as "unparented"
86
0
      // Symbols. For that reason we need to check which type of symbol we
87
0
      // are dealing with and copy the correct number of bytes.
88
0
      if (isa<DefinedRegular>(D))
89
0
        memcpy(Sym, D, sizeof(DefinedRegular));
90
0
      else if (isa<DefinedAbsolute>(D))
91
0
        memcpy(Sym, D, sizeof(DefinedAbsolute));
92
0
      else
93
0
        memcpy(Sym, D, sizeof(SymbolUnion));
94
0
      continue;
95
0
    }
96
0
97
0
    // If we can resolve a symbol by removing __imp_ prefix, do that.
98
0
    // This odd rule is for compatibility with MSVC linker.
99
0
    if (Name.startswith("__imp_")) {
100
0
      Symbol *Imp = find(Name.substr(strlen("__imp_")));
101
0
      if (Imp && isa<Defined>(Imp)) {
102
0
        auto *D = cast<Defined>(Imp);
103
0
        replaceSymbol<DefinedLocalImport>(Sym, Name, D);
104
0
        LocalImportChunks.push_back(cast<DefinedLocalImport>(Sym)->getChunk());
105
0
        LocalImports[Sym] = D;
106
0
        continue;
107
0
      }
108
0
    }
109
0
110
0
    // Remaining undefined symbols are not fatal if /force is specified.
111
0
    // They are replaced with dummy defined symbols.
112
0
    if (Config->Force)
113
0
      replaceSymbol<DefinedAbsolute>(Sym, Name, 0);
114
0
    Undefs.insert(Sym);
115
0
  }
116
0
117
0
  if (Undefs.empty() && LocalImports.empty())
118
0
    return;
119
0
120
0
  for (Symbol *B : Config->GCRoot) {
121
0
    if (Undefs.count(B))
122
0
      errorOrWarn("<root>: undefined symbol: " + B->getName());
123
0
    if (Config->WarnLocallyDefinedImported)
124
0
      if (Symbol *Imp = LocalImports.lookup(B))
125
0
        warn("<root>: locally defined symbol imported: " + Imp->getName() +
126
0
             " (defined in " + toString(Imp->getFile()) + ")");
127
0
  }
128
0
129
0
  for (ObjFile *File : ObjFile::Instances) {
130
0
    for (Symbol *Sym : File->getSymbols()) {
131
0
      if (!Sym)
132
0
        continue;
133
0
      if (Undefs.count(Sym))
134
0
        errorOrWarn(toString(File) + ": undefined symbol: " + Sym->getName());
135
0
      if (Config->WarnLocallyDefinedImported)
136
0
        if (Symbol *Imp = LocalImports.lookup(Sym))
137
0
          warn(toString(File) + ": locally defined symbol imported: " +
138
0
               Imp->getName() + " (defined in " + toString(Imp->getFile()) +
139
0
               ")");
140
0
    }
141
0
  }
142
0
}
143
144
0
std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name) {
145
0
  Symbol *&Sym = SymMap[CachedHashStringRef(Name)];
146
0
  if (Sym)
147
0
    return {Sym, false};
148
0
  Sym = (Symbol *)make<SymbolUnion>();
149
0
  Sym->IsUsedInRegularObj = false;
150
0
  Sym->PendingArchiveLoad = false;
151
0
  return {Sym, true};
152
0
}
153
154
Symbol *SymbolTable::addUndefined(StringRef Name, InputFile *F,
155
0
                                  bool IsWeakAlias) {
156
0
  Symbol *S;
157
0
  bool WasInserted;
158
0
  std::tie(S, WasInserted) = insert(Name);
159
0
  if (!F || !isa<BitcodeFile>(F))
160
0
    S->IsUsedInRegularObj = true;
161
0
  if (WasInserted || (isa<Lazy>(S) && IsWeakAlias)) {
162
0
    replaceSymbol<Undefined>(S, Name);
163
0
    return S;
164
0
  }
165
0
  if (auto *L = dyn_cast<Lazy>(S)) {
166
0
    if (!S->PendingArchiveLoad) {
167
0
      S->PendingArchiveLoad = true;
168
0
      L->File->addMember(&L->Sym);
169
0
    }
170
0
  }
171
0
  return S;
172
0
}
173
174
0
void SymbolTable::addLazy(ArchiveFile *F, const Archive::Symbol Sym) {
175
0
  StringRef Name = Sym.getName();
176
0
  Symbol *S;
177
0
  bool WasInserted;
178
0
  std::tie(S, WasInserted) = insert(Name);
179
0
  if (WasInserted) {
180
0
    replaceSymbol<Lazy>(S, F, Sym);
181
0
    return;
182
0
  }
183
0
  auto *U = dyn_cast<Undefined>(S);
184
0
  if (!U || U->WeakAlias || S->PendingArchiveLoad)
185
0
    return;
186
0
  S->PendingArchiveLoad = true;
187
0
  F->addMember(&Sym);
188
0
}
189
190
0
void SymbolTable::reportDuplicate(Symbol *Existing, InputFile *NewFile) {
191
0
  error("duplicate symbol: " + toString(*Existing) + " in " +
192
0
        toString(Existing->getFile()) + " and in " + toString(NewFile));
193
0
}
194
195
0
Symbol *SymbolTable::addAbsolute(StringRef N, COFFSymbolRef Sym) {
196
0
  Symbol *S;
197
0
  bool WasInserted;
198
0
  std::tie(S, WasInserted) = insert(N);
199
0
  S->IsUsedInRegularObj = true;
200
0
  if (WasInserted || isa<Undefined>(S) || isa<Lazy>(S))
201
0
    replaceSymbol<DefinedAbsolute>(S, N, Sym);
202
0
  else if (!isa<DefinedCOFF>(S))
203
0
    reportDuplicate(S, nullptr);
204
0
  return S;
205
0
}
206
207
0
Symbol *SymbolTable::addAbsolute(StringRef N, uint64_t VA) {
208
0
  Symbol *S;
209
0
  bool WasInserted;
210
0
  std::tie(S, WasInserted) = insert(N);
211
0
  S->IsUsedInRegularObj = true;
212
0
  if (WasInserted || isa<Undefined>(S) || isa<Lazy>(S))
213
0
    replaceSymbol<DefinedAbsolute>(S, N, VA);
214
0
  else if (!isa<DefinedCOFF>(S))
215
0
    reportDuplicate(S, nullptr);
216
0
  return S;
217
0
}
218
219
0
Symbol *SymbolTable::addSynthetic(StringRef N, Chunk *C) {
220
0
  Symbol *S;
221
0
  bool WasInserted;
222
0
  std::tie(S, WasInserted) = insert(N);
223
0
  S->IsUsedInRegularObj = true;
224
0
  if (WasInserted || isa<Undefined>(S) || isa<Lazy>(S))
225
0
    replaceSymbol<DefinedSynthetic>(S, N, C);
226
0
  else if (!isa<DefinedCOFF>(S))
227
0
    reportDuplicate(S, nullptr);
228
0
  return S;
229
0
}
230
231
Symbol *SymbolTable::addRegular(InputFile *F, StringRef N,
232
                                const coff_symbol_generic *Sym,
233
0
                                SectionChunk *C) {
234
0
  Symbol *S;
235
0
  bool WasInserted;
236
0
  std::tie(S, WasInserted) = insert(N);
237
0
  if (!isa<BitcodeFile>(F))
238
0
    S->IsUsedInRegularObj = true;
239
0
  if (WasInserted || !isa<DefinedRegular>(S))
240
0
    replaceSymbol<DefinedRegular>(S, F, N, /*IsCOMDAT*/ false,
241
0
                                  /*IsExternal*/ true, Sym, C);
242
0
  else
243
0
    reportDuplicate(S, F);
244
0
  return S;
245
0
}
246
247
std::pair<Symbol *, bool>
248
SymbolTable::addComdat(InputFile *F, StringRef N,
249
0
                       const coff_symbol_generic *Sym) {
250
0
  Symbol *S;
251
0
  bool WasInserted;
252
0
  std::tie(S, WasInserted) = insert(N);
253
0
  if (!isa<BitcodeFile>(F))
254
0
    S->IsUsedInRegularObj = true;
255
0
  if (WasInserted || !isa<DefinedRegular>(S)) {
256
0
    replaceSymbol<DefinedRegular>(S, F, N, /*IsCOMDAT*/ true,
257
0
                                  /*IsExternal*/ true, Sym, nullptr);
258
0
    return {S, true};
259
0
  }
260
0
  if (!cast<DefinedRegular>(S)->isCOMDAT())
261
0
    reportDuplicate(S, F);
262
0
  return {S, false};
263
0
}
264
265
Symbol *SymbolTable::addCommon(InputFile *F, StringRef N, uint64_t Size,
266
0
                               const coff_symbol_generic *Sym, CommonChunk *C) {
267
0
  Symbol *S;
268
0
  bool WasInserted;
269
0
  std::tie(S, WasInserted) = insert(N);
270
0
  if (!isa<BitcodeFile>(F))
271
0
    S->IsUsedInRegularObj = true;
272
0
  if (WasInserted || !isa<DefinedCOFF>(S))
273
0
    replaceSymbol<DefinedCommon>(S, F, N, Size, Sym, C);
274
0
  else if (auto *DC = dyn_cast<DefinedCommon>(S))
275
0
    if (Size > DC->getSize())
276
0
      replaceSymbol<DefinedCommon>(S, F, N, Size, Sym, C);
277
0
  return S;
278
0
}
279
280
0
DefinedImportData *SymbolTable::addImportData(StringRef N, ImportFile *F) {
281
0
  Symbol *S;
282
0
  bool WasInserted;
283
0
  std::tie(S, WasInserted) = insert(N);
284
0
  S->IsUsedInRegularObj = true;
285
0
  if (WasInserted || isa<Undefined>(S) || isa<Lazy>(S)) {
286
0
    replaceSymbol<DefinedImportData>(S, N, F);
287
0
    return cast<DefinedImportData>(S);
288
0
  }
289
0
290
0
  reportDuplicate(S, F);
291
0
  return nullptr;
292
0
}
293
294
DefinedImportThunk *SymbolTable::addImportThunk(StringRef Name,
295
                                               DefinedImportData *ID,
296
0
                                               uint16_t Machine) {
297
0
  Symbol *S;
298
0
  bool WasInserted;
299
0
  std::tie(S, WasInserted) = insert(Name);
300
0
  S->IsUsedInRegularObj = true;
301
0
  if (WasInserted || isa<Undefined>(S) || isa<Lazy>(S)) {
302
0
    replaceSymbol<DefinedImportThunk>(S, Name, ID, Machine);
303
0
    return cast<DefinedImportThunk>(S);
304
0
  }
305
0
306
0
  reportDuplicate(S, ID->File);
307
0
  return nullptr;
308
0
}
309
310
0
std::vector<Chunk *> SymbolTable::getChunks() {
311
0
  std::vector<Chunk *> Res;
312
0
  for (ObjFile *File : ObjFile::Instances) {
313
0
    ArrayRef<Chunk *> V = File->getChunks();
314
0
    Res.insert(Res.end(), V.begin(), V.end());
315
0
  }
316
0
  return Res;
317
0
}
318
319
0
Symbol *SymbolTable::find(StringRef Name) {
320
0
  auto It = SymMap.find(CachedHashStringRef(Name));
321
0
  if (It == SymMap.end())
322
0
    return nullptr;
323
0
  return It->second;
324
0
}
325
326
0
Symbol *SymbolTable::findUnderscore(StringRef Name) {
327
0
  if (Config->Machine == I386)
328
0
    return find(("_" + Name).str());
329
0
  return find(Name);
330
0
}
331
332
0
StringRef SymbolTable::findByPrefix(StringRef Prefix) {
333
0
  for (auto Pair : SymMap) {
334
0
    StringRef Name = Pair.first.val();
335
0
    if (Name.startswith(Prefix))
336
0
      return Name;
337
0
  }
338
0
  return "";
339
0
}
340
341
0
StringRef SymbolTable::findMangle(StringRef Name) {
342
0
  if (Symbol *Sym = find(Name))
343
0
    if (!isa<Undefined>(Sym))
344
0
      return Name;
345
0
  if (Config->Machine != I386)
346
0
    return findByPrefix(("?" + Name + "@@Y").str());
347
0
  if (!Name.startswith("_"))
348
0
    return "";
349
0
  // Search for x86 stdcall function.
350
0
  StringRef S = findByPrefix((Name + "@").str());
351
0
  if (!S.empty())
352
0
    return S;
353
0
  // Search for x86 fastcall function.
354
0
  S = findByPrefix(("@" + Name.substr(1) + "@").str());
355
0
  if (!S.empty())
356
0
    return S;
357
0
  // Search for x86 vectorcall function.
358
0
  S = findByPrefix((Name.substr(1) + "@@").str());
359
0
  if (!S.empty())
360
0
    return S;
361
0
  // Search for x86 C++ non-member function.
362
0
  return findByPrefix(("?" + Name.substr(1) + "@@Y").str());
363
0
}
364
365
0
void SymbolTable::mangleMaybe(Symbol *B) {
366
0
  auto *U = dyn_cast<Undefined>(B);
367
0
  if (!U || U->WeakAlias)
368
0
    return;
369
0
  StringRef Alias = findMangle(U->getName());
370
0
  if (!Alias.empty()) {
371
0
    log(U->getName() + " aliased to " + Alias);
372
0
    U->WeakAlias = addUndefined(Alias);
373
0
  }
374
0
}
375
376
0
Symbol *SymbolTable::addUndefined(StringRef Name) {
377
0
  return addUndefined(Name, nullptr, false);
378
0
}
379
380
0
std::vector<StringRef> SymbolTable::compileBitcodeFiles() {
381
0
  LTO.reset(new BitcodeCompiler);
382
0
  for (BitcodeFile *F : BitcodeFile::Instances)
383
0
    LTO->add(*F);
384
0
  return LTO->compile();
385
0
}
386
387
0
void SymbolTable::addCombinedLTOObjects() {
388
0
  if (BitcodeFile::Instances.empty())
389
0
    return;
390
0
391
0
  ScopedTimer T(LTOTimer);
392
0
  for (StringRef Object : compileBitcodeFiles()) {
393
0
    auto *Obj = make<ObjFile>(MemoryBufferRef(Object, "lto.tmp"));
394
0
    Obj->parse();
395
0
    ObjFile::Instances.push_back(Obj);
396
0
  }
397
0
}
398
399
} // namespace coff
400
} // namespace lld