Coverage Report

Created: 2018-01-17 17:22

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/lld/wasm/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
12
#include "Config.h"
13
#include "InputChunks.h"
14
#include "WriterUtils.h"
15
#include "lld/Common/ErrorHandler.h"
16
#include "lld/Common/Memory.h"
17
18
#include <unordered_set>
19
20
#define DEBUG_TYPE "lld"
21
22
using namespace llvm;
23
using namespace llvm::wasm;
24
using namespace lld;
25
using namespace lld::wasm;
26
27
SymbolTable *lld::wasm::Symtab;
28
29
0
void SymbolTable::addFile(InputFile *File) {
30
0
  log("Processing: " + toString(File));
31
0
  File->parse();
32
0
33
0
  if (auto *F = dyn_cast<ObjFile>(File))
34
0
    ObjectFiles.push_back(F);
35
0
}
36
37
0
void SymbolTable::reportRemainingUndefines() {
38
0
  std::unordered_set<Symbol *> Undefs;
39
0
  for (Symbol *Sym : SymVector) {
40
0
    if (Sym->isUndefined() && !Sym->isWeak() &&
41
0
        Config->AllowUndefinedSymbols.count(Sym->getName()) == 0) {
42
0
      Undefs.insert(Sym);
43
0
    }
44
0
  }
45
0
46
0
  if (Undefs.empty())
47
0
    return;
48
0
49
0
  for (ObjFile *File : ObjectFiles)
50
0
    for (Symbol *Sym : File->getSymbols())
51
0
      if (Undefs.count(Sym))
52
0
        error(toString(File) + ": undefined symbol: " + toString(*Sym));
53
0
54
0
  for (Symbol *Sym : Undefs)
55
0
    if (!Sym->getFile())
56
0
      error("undefined symbol: " + toString(*Sym));
57
0
}
58
59
0
Symbol *SymbolTable::find(StringRef Name) {
60
0
  auto It = SymMap.find(CachedHashStringRef(Name));
61
0
  if (It == SymMap.end())
62
0
    return nullptr;
63
0
  return It->second;
64
0
}
65
66
0
std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name) {
67
0
  Symbol *&Sym = SymMap[CachedHashStringRef(Name)];
68
0
  if (Sym)
69
0
    return {Sym, false};
70
0
  Sym = make<Symbol>(Name, false);
71
0
  SymVector.emplace_back(Sym);
72
0
  return {Sym, true};
73
0
}
74
75
0
void SymbolTable::reportDuplicate(Symbol *Existing, InputFile *NewFile) {
76
0
  error("duplicate symbol: " + toString(*Existing) + "\n>>> defined in " +
77
0
        toString(Existing->getFile()) + "\n>>> defined in " +
78
0
        toString(NewFile));
79
0
}
80
81
// Check the type of new symbol matches that of the symbol is replacing.
82
// For functions this can also involve verifying that the signatures match.
83
static void checkSymbolTypes(const Symbol &Existing, const InputFile &F,
84
0
                             Symbol::Kind Kind, const WasmSignature *NewSig) {
85
0
  if (Existing.isLazy())
86
0
    return;
87
0
88
0
  bool NewIsFunction = Kind == Symbol::Kind::UndefinedFunctionKind ||
89
0
                       Kind == Symbol::Kind::DefinedFunctionKind;
90
0
91
0
  // First check the symbol types match (i.e. either both are function
92
0
  // symbols or both are data symbols).
93
0
  if (Existing.isFunction() != NewIsFunction) {
94
0
    error("symbol type mismatch: " + Existing.getName() + "\n>>> defined as " +
95
0
          (Existing.isFunction() ? "Function" : "Global") + " in " +
96
0
          toString(Existing.getFile()) + "\n>>> defined as " +
97
0
          (NewIsFunction ? "Function" : "Global") + " in " + F.getName());
98
0
    return;
99
0
  }
100
0
101
0
  // For function symbols, optionally check the function signature matches too.
102
0
  if (!NewIsFunction || !Config->CheckSignatures)
103
0
    return;
104
0
  // Skip the signature check if the existing function has no signature (e.g.
105
0
  // if it is an undefined symbol generated by --undefined command line flag).
106
0
  if (!Existing.hasFunctionType())
107
0
    return;
108
0
109
0
  DEBUG(dbgs() << "checkSymbolTypes: " << Existing.getName() << "\n");
110
0
  assert(NewSig);
111
0
112
0
  const WasmSignature &OldSig = Existing.getFunctionType();
113
0
  if (*NewSig == OldSig)
114
0
    return;
115
0
116
0
  error("function signature mismatch: " + Existing.getName() +
117
0
        "\n>>> defined as " + toString(OldSig) + " in " +
118
0
        toString(Existing.getFile()) + "\n>>> defined as " + toString(*NewSig) +
119
0
        " in " + F.getName());
120
0
}
121
122
Symbol *SymbolTable::addDefinedFunction(StringRef Name,
123
                                        const WasmSignature *Type,
124
0
                                        uint32_t Flags) {
125
0
  DEBUG(dbgs() << "addDefinedFunction: " << Name << "\n");
126
0
  Symbol *S;
127
0
  bool WasInserted;
128
0
  std::tie(S, WasInserted) = insert(Name);
129
0
  if (WasInserted) {
130
0
    S->update(Symbol::DefinedFunctionKind, nullptr, Flags);
131
0
    S->setFunctionType(Type);
132
0
  } else if (!S->isFunction()) {
133
0
    error("symbol type mismatch: " + Name);
134
0
  }
135
0
  return S;
136
0
}
137
138
0
Symbol *SymbolTable::addDefinedGlobal(StringRef Name) {
139
0
  DEBUG(dbgs() << "addDefinedGlobal: " << Name << "\n");
140
0
  Symbol *S;
141
0
  bool WasInserted;
142
0
  std::tie(S, WasInserted) = insert(Name);
143
0
  if (WasInserted)
144
0
    S->update(Symbol::DefinedGlobalKind);
145
0
  else if (!S->isGlobal())
146
0
    error("symbol type mismatch: " + Name);
147
0
  return S;
148
0
}
149
150
Symbol *SymbolTable::addDefined(StringRef Name, Symbol::Kind Kind,
151
                                uint32_t Flags, InputFile *F,
152
                                const InputSegment *Segment,
153
0
                                InputFunction *Function, uint32_t Address) {
154
0
  DEBUG(dbgs() << "addDefined: " << Name << " addr:" << Address << "\n");
155
0
  Symbol *S;
156
0
  bool WasInserted;
157
0
158
0
  std::tie(S, WasInserted) = insert(Name);
159
0
  if (WasInserted) {
160
0
    S->update(Kind, F, Flags, Segment, Function, Address);
161
0
  } else if (S->isLazy()) {
162
0
    // The existing symbol is lazy. Replace it without checking types since
163
0
    // lazy symbols don't have any type information.
164
0
    DEBUG(dbgs() << "replacing existing lazy symbol: " << Name << "\n");
165
0
    S->update(Kind, F, Flags, Segment, Function, Address);
166
0
  } else if (!S->isDefined()) {
167
0
    // The existing symbol table entry is undefined. The new symbol replaces
168
0
    // it, after checking the type matches
169
0
    DEBUG(dbgs() << "resolving existing undefined symbol: " << Name << "\n");
170
0
    checkSymbolTypes(*S, *F, Kind, Function ? &Function->Signature : nullptr);
171
0
    S->update(Kind, F, Flags, Segment, Function, Address);
172
0
  } else if ((Flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) {
173
0
    // the new symbol is weak we can ignore it
174
0
    DEBUG(dbgs() << "existing symbol takes precedence\n");
175
0
  } else if (S->isWeak()) {
176
0
    // the new symbol is not weak and the existing symbol is, so we replace
177
0
    // it
178
0
    DEBUG(dbgs() << "replacing existing weak symbol\n");
179
0
    checkSymbolTypes(*S, *F, Kind, Function ? &Function->Signature : nullptr);
180
0
    S->update(Kind, F, Flags, Segment, Function, Address);
181
0
  } else {
182
0
    // neither symbol is week. They conflict.
183
0
    reportDuplicate(S, F);
184
0
  }
185
0
  return S;
186
0
}
187
188
Symbol *SymbolTable::addUndefinedFunction(StringRef Name,
189
0
                                          const WasmSignature *Type) {
190
0
  Symbol *S;
191
0
  bool WasInserted;
192
0
  std::tie(S, WasInserted) = insert(Name);
193
0
  if (WasInserted) {
194
0
    S->update(Symbol::UndefinedFunctionKind);
195
0
    S->setFunctionType(Type);
196
0
  } else if (!S->isFunction()) {
197
0
    error("symbol type mismatch: " + Name);
198
0
  }
199
0
  return S;
200
0
}
201
202
Symbol *SymbolTable::addUndefined(StringRef Name, Symbol::Kind Kind,
203
                                  uint32_t Flags, InputFile *F,
204
0
                                  const WasmSignature *Type) {
205
0
  DEBUG(dbgs() << "addUndefined: " << Name << "\n");
206
0
  Symbol *S;
207
0
  bool WasInserted;
208
0
  std::tie(S, WasInserted) = insert(Name);
209
0
  if (WasInserted) {
210
0
    S->update(Kind, F, Flags);
211
0
    if (Type)
212
0
      S->setFunctionType(Type);
213
0
  } else if (S->isLazy()) {
214
0
    DEBUG(dbgs() << "resolved by existing lazy\n");
215
0
    auto *AF = cast<ArchiveFile>(S->getFile());
216
0
    AF->addMember(&S->getArchiveSymbol());
217
0
  } else if (S->isDefined()) {
218
0
    DEBUG(dbgs() << "resolved by existing\n");
219
0
    checkSymbolTypes(*S, *F, Kind, Type);
220
0
  }
221
0
  return S;
222
0
}
223
224
0
void SymbolTable::addLazy(ArchiveFile *F, const Archive::Symbol *Sym) {
225
0
  DEBUG(dbgs() << "addLazy: " << Sym->getName() << "\n");
226
0
  StringRef Name = Sym->getName();
227
0
  Symbol *S;
228
0
  bool WasInserted;
229
0
  std::tie(S, WasInserted) = insert(Name);
230
0
  if (WasInserted) {
231
0
    S->update(Symbol::LazyKind, F);
232
0
    S->setArchiveSymbol(*Sym);
233
0
  } else if (S->isUndefined()) {
234
0
    // There is an existing undefined symbol.  The can load from the
235
0
    // archive.
236
0
    DEBUG(dbgs() << "replacing existing undefined\n");
237
0
    F->addMember(Sym);
238
0
  }
239
0
}
240
241
0
bool SymbolTable::addComdat(StringRef Name, ObjFile *F) {
242
0
  DEBUG(dbgs() << "addComdat: " << Name << "\n");
243
0
  ObjFile *&File = ComdatMap[CachedHashStringRef(Name)];
244
0
  if (File) {
245
0
    DEBUG(dbgs() << "COMDAT already defined\n");
246
0
    return false;
247
0
  }
248
0
  File = F;
249
0
  return true;
250
0
}
251
252
0
ObjFile *SymbolTable::findComdat(StringRef Name) const {
253
0
  auto It = ComdatMap.find(CachedHashStringRef(Name));
254
0
  return It == ComdatMap.end() ? nullptr : It->second;
255
0
}