Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/tools/lld/ELF/SymbolTable.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- SymbolTable.cpp ----------------------------------------------------===//
2
//
3
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4
// See https://llvm.org/LICENSE.txt for license information.
5
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6
//
7
//===----------------------------------------------------------------------===//
8
//
9
// Symbol table is a bag of all known symbols. We put all symbols of
10
// all input files to the symbol table. The symbol table is basically
11
// a hash table with the logic to resolve symbol name conflicts using
12
// the symbol types.
13
//
14
//===----------------------------------------------------------------------===//
15
16
#include "SymbolTable.h"
17
#include "Config.h"
18
#include "LinkerScript.h"
19
#include "Symbols.h"
20
#include "SyntheticSections.h"
21
#include "lld/Common/ErrorHandler.h"
22
#include "lld/Common/Memory.h"
23
#include "lld/Common/Strings.h"
24
#include "llvm/ADT/STLExtras.h"
25
26
using namespace llvm;
27
using namespace llvm::object;
28
using namespace llvm::ELF;
29
30
using namespace lld;
31
using namespace lld::elf;
32
33
SymbolTable *elf::symtab;
34
35
13
void SymbolTable::wrap(Symbol *sym, Symbol *real, Symbol *wrap) {
36
13
  // Swap symbols as instructed by -wrap.
37
13
  int &idx1 = symMap[CachedHashStringRef(sym->getName())];
38
13
  int &idx2 = symMap[CachedHashStringRef(real->getName())];
39
13
  int &idx3 = symMap[CachedHashStringRef(wrap->getName())];
40
13
41
13
  idx2 = idx1;
42
13
  idx1 = idx3;
43
13
44
13
  // Now renaming is complete. No one refers Real symbol. We could leave
45
13
  // Real as-is, but if Real is written to the symbol table, that may
46
13
  // contain irrelevant values. So, we copy all values from Sym to Real.
47
13
  StringRef s = real->getName();
48
13
  memcpy(real, sym, sizeof(SymbolUnion));
49
13
  real->setName(s);
50
13
}
51
52
// Find an existing symbol or create a new one.
53
21.0k
Symbol *SymbolTable::insert(StringRef name) {
54
21.0k
  // <name>@@<version> means the symbol is the default version. In that
55
21.0k
  // case <name>@@<version> will be used to resolve references to <name>.
56
21.0k
  //
57
21.0k
  // Since this is a hot path, the following string search code is
58
21.0k
  // optimized for speed. StringRef::find(char) is much faster than
59
21.0k
  // StringRef::find(StringRef).
60
21.0k
  size_t pos = name.find('@');
61
21.0k
  if (pos != StringRef::npos && 
pos + 1 < name.size()115
&&
name[pos + 1] == '@'114
)
62
24
    name = name.take_front(pos);
63
21.0k
64
21.0k
  auto p = symMap.insert({CachedHashStringRef(name), (int)symVector.size()});
65
21.0k
  int &symIndex = p.first->second;
66
21.0k
  bool isNew = p.second;
67
21.0k
68
21.0k
  if (!isNew)
69
2.47k
    return symVector[symIndex];
70
18.5k
71
18.5k
  Symbol *sym = reinterpret_cast<Symbol *>(make<SymbolUnion>());
72
18.5k
  symVector.push_back(sym);
73
18.5k
74
18.5k
  sym->setName(name);
75
18.5k
  sym->symbolKind = Symbol::PlaceholderKind;
76
18.5k
  sym->versionId = config->defaultSymbolVersion;
77
18.5k
  sym->visibility = STV_DEFAULT;
78
18.5k
  sym->isUsedInRegularObj = false;
79
18.5k
  sym->exportDynamic = false;
80
18.5k
  sym->canInline = true;
81
18.5k
  sym->scriptDefined = false;
82
18.5k
  sym->partition = 1;
83
18.5k
  return sym;
84
18.5k
}
85
86
3.34k
Symbol *SymbolTable::addSymbol(const Symbol &New) {
87
3.34k
  Symbol *sym = symtab->insert(New.getName());
88
3.34k
  sym->resolve(New);
89
3.34k
  return sym;
90
3.34k
}
91
92
671k
Symbol *SymbolTable::find(StringRef name) {
93
671k
  auto it = symMap.find(CachedHashStringRef(name));
94
671k
  if (it == symMap.end())
95
667k
    return nullptr;
96
3.71k
  Symbol *sym = symVector[it->second];
97
3.71k
  if (sym->isPlaceholder())
98
1
    return nullptr;
99
3.71k
  return sym;
100
3.71k
}
101
102
// Initialize demangledSyms with a map from demangled symbols to symbol
103
// objects. Used to handle "extern C++" directive in version scripts.
104
//
105
// The map will contain all demangled symbols. That can be very large,
106
// and in LLD we generally want to avoid do anything for each symbol.
107
// Then, why are we doing this? Here's why.
108
//
109
// Users can use "extern C++ {}" directive to match against demangled
110
// C++ symbols. For example, you can write a pattern such as
111
// "llvm::*::foo(int, ?)". Obviously, there's no way to handle this
112
// other than trying to match a pattern against all demangled symbols.
113
// So, if "extern C++" feature is used, we need to demangle all known
114
// symbols.
115
29
StringMap<std::vector<Symbol *>> &SymbolTable::getDemangledSyms() {
116
29
  if (!demangledSyms) {
117
22
    demangledSyms.emplace();
118
45
    for (Symbol *sym : symVector) {
119
45
      if (!sym->isDefined() && 
!sym->isCommon()1
)
120
1
        continue;
121
44
      if (Optional<std::string> s = demangleItanium(sym->getName()))
122
43
        (*demangledSyms)[*s].push_back(sym);
123
1
      else
124
1
        (*demangledSyms)[sym->getName()].push_back(sym);
125
44
    }
126
22
  }
127
29
  return *demangledSyms;
128
29
}
129
130
114
std::vector<Symbol *> SymbolTable::findByVersion(SymbolVersion ver) {
131
114
  if (ver.isExternCpp)
132
12
    return getDemangledSyms().lookup(ver.name);
133
102
  if (Symbol *b = find(ver.name))
134
90
    if (b->isDefined() || 
b->isCommon()4
)
135
87
      return {b};
136
15
  return {};
137
15
}
138
139
28
std::vector<Symbol *> SymbolTable::findAllByVersion(SymbolVersion ver) {
140
28
  std::vector<Symbol *> res;
141
28
  StringMatcher m(ver.name);
142
28
143
28
  if (ver.isExternCpp) {
144
17
    for (auto &p : getDemangledSyms())
145
42
      if (m.match(p.first()))
146
19
        res.insert(res.end(), p.second.begin(), p.second.end());
147
17
    return res;
148
17
  }
149
11
150
11
  for (Symbol *sym : symVector)
151
36
    if ((sym->isDefined() || 
sym->isCommon()0
) && m.match(sym->getName()))
152
24
      res.push_back(sym);
153
11
  return res;
154
11
}
155
156
// Handles -dynamic-list.
157
2.69k
void SymbolTable::handleDynamicList() {
158
2.69k
  for (SymbolVersion &ver : config->dynamicList) {
159
29
    std::vector<Symbol *> syms;
160
29
    if (ver.hasWildcard)
161
1
      syms = findAllByVersion(ver);
162
28
    else
163
28
      syms = findByVersion(ver);
164
29
165
29
    for (Symbol *b : syms) {
166
24
      if (!config->shared)
167
18
        b->exportDynamic = true;
168
6
      else if (b->includeInDynsym())
169
4
        b->isPreemptible = true;
170
24
    }
171
29
  }
172
2.69k
}
173
174
// Set symbol versions to symbols. This function handles patterns
175
// containing no wildcard characters.
176
void SymbolTable::assignExactVersion(SymbolVersion ver, uint16_t versionId,
177
113
                                     StringRef versionName) {
178
113
  if (ver.hasWildcard)
179
27
    return;
180
86
181
86
  // Get a list of symbols which we need to assign the version to.
182
86
  std::vector<Symbol *> syms = findByVersion(ver);
183
86
  if (syms.empty()) {
184
15
    if (!config->undefinedVersion)
185
3
      error("version script assignment of '" + versionName + "' to symbol '" +
186
3
            ver.name + "' failed: symbol not defined");
187
15
    return;
188
15
  }
189
71
190
71
  auto getName = [](uint16_t ver) -> std::string {
191
6
    if (ver == VER_NDX_LOCAL)
192
1
      return "VER_NDX_LOCAL";
193
5
    if (ver == VER_NDX_GLOBAL)
194
1
      return "VER_NDX_GLOBAL";
195
4
    return ("version '" + config->versionDefinitions[ver - 2].name + "'").str();
196
4
  };
197
71
198
71
  // Assign the version.
199
72
  for (Symbol *sym : syms) {
200
72
    // Skip symbols containing version info because symbol versions
201
72
    // specified by symbol names take precedence over version scripts.
202
72
    // See parseSymbolVersion().
203
72
    if (sym->getName().contains('@'))
204
4
      continue;
205
68
206
68
    if (sym->versionId == config->defaultSymbolVersion)
207
64
      sym->versionId = versionId;
208
68
    if (sym->versionId == versionId)
209
65
      continue;
210
3
211
3
    warn("attempt to reassign symbol '" + ver.name + "' of " +
212
3
         getName(sym->versionId) + " to " + getName(versionId));
213
3
  }
214
71
}
215
216
113
void SymbolTable::assignWildcardVersion(SymbolVersion ver, uint16_t versionId) {
217
113
  if (!ver.hasWildcard)
218
86
    return;
219
27
220
27
  // Exact matching takes precendence over fuzzy matching,
221
27
  // so we set a version to a symbol only if no version has been assigned
222
27
  // to the symbol. This behavior is compatible with GNU.
223
27
  for (Symbol *b : findAllByVersion(ver))
224
41
    if (b->versionId == config->defaultSymbolVersion)
225
36
      b->versionId = versionId;
226
27
}
227
228
// This function processes version scripts by updating the versionId
229
// member of symbols.
230
// If there's only one anonymous version definition in a version
231
// script file, the script does not actually define any symbol version,
232
// but just specifies symbols visibilities.
233
2.69k
void SymbolTable::scanVersionScript() {
234
2.69k
  // First, we assign versions to exact matching symbols,
235
2.69k
  // i.e. version definitions not containing any glob meta-characters.
236
2.69k
  for (SymbolVersion &ver : config->versionScriptGlobals)
237
26
    assignExactVersion(ver, VER_NDX_GLOBAL, "global");
238
2.69k
  for (SymbolVersion &ver : config->versionScriptLocals)
239
10
    assignExactVersion(ver, VER_NDX_LOCAL, "local");
240
2.69k
  for (VersionDefinition &v : config->versionDefinitions)
241
97
    for (SymbolVersion &ver : v.globals)
242
77
      assignExactVersion(ver, v.id, v.name);
243
2.69k
244
2.69k
  // Next, we assign versions to fuzzy matching symbols,
245
2.69k
  // i.e. version definitions containing glob meta-characters.
246
2.69k
  for (SymbolVersion &ver : config->versionScriptGlobals)
247
26
    assignWildcardVersion(ver, VER_NDX_GLOBAL);
248
2.69k
  for (SymbolVersion &ver : config->versionScriptLocals)
249
10
    assignWildcardVersion(ver, VER_NDX_LOCAL);
250
2.69k
251
2.69k
  // Note that because the last match takes precedence over previous matches,
252
2.69k
  // we iterate over the definitions in the reverse order.
253
2.69k
  for (VersionDefinition &v : llvm::reverse(config->versionDefinitions))
254
97
    for (SymbolVersion &ver : v.globals)
255
77
      assignWildcardVersion(ver, v.id);
256
2.69k
257
2.69k
  // Symbol themselves might know their versions because symbols
258
2.69k
  // can contain versions in the form of <name>@<version>.
259
2.69k
  // Let them parse and update their names to exclude version suffix.
260
2.69k
  for (Symbol *sym : symVector)
261
16.9k
    sym->parseSymbolVersion();
262
2.69k
263
2.69k
  // isPreemptible is false at this point. To correctly compute the binding of a
264
2.69k
  // Defined (which is used by includeInDynsym()), we need to know if it is
265
2.69k
  // VER_NDX_LOCAL or not. If defaultSymbolVersion is VER_NDX_LOCAL, we should
266
2.69k
  // compute symbol versions before handling --dynamic-list.
267
2.69k
  handleDynamicList();
268
2.69k
}