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
26using namespace llvm;
27using namespace llvm::object;
28using namespace llvm::ELF;
29using namespace lld;
30using namespace lld::elf;
31
32SymbolTable *elf::symtab;
33
34void SymbolTable::wrap(Symbol *sym, Symbol *real, Symbol *wrap) {
35  // Swap symbols as instructed by -wrap.
36  int &idx1 = symMap[CachedHashStringRef(sym->getName())];
37  int &idx2 = symMap[CachedHashStringRef(real->getName())];
38  int &idx3 = symMap[CachedHashStringRef(wrap->getName())];
39
40  idx2 = idx1;
41  idx1 = idx3;
42
43  if (real->exportDynamic)
44    sym->exportDynamic = true;
45
46  // Now renaming is complete, and no one refers to real. We drop real from
47  // .symtab and .dynsym. If real is undefined, it is important that we don't
48  // leave it in .dynsym, because otherwise it might lead to an undefined symbol
49  // error in a subsequent link. If real is defined, we could emit real as an
50  // alias for sym, but that could degrade the user experience of some tools
51  // that can print out only one symbol for each location: sym is a preferred
52  // name than real, but they might print out real instead.
53  memcpy(real, sym, sizeof(SymbolUnion));
54  real->isUsedInRegularObj = false;
55}
56
57// Find an existing symbol or create a new one.
58Symbol *SymbolTable::insert(StringRef name) {
59  // <name>@@<version> means the symbol is the default version. In that
60  // case <name>@@<version> will be used to resolve references to <name>.
61  //
62  // Since this is a hot path, the following string search code is
63  // optimized for speed. StringRef::find(char) is much faster than
64  // StringRef::find(StringRef).
65  size_t pos = name.find('@');
66  if (pos != StringRef::npos && pos + 1 < name.size() && name[pos + 1] == '@')
67    name = name.take_front(pos);
68
69  auto p = symMap.insert({CachedHashStringRef(name), (int)symVector.size()});
70  int &symIndex = p.first->second;
71  bool isNew = p.second;
72
73  if (!isNew)
74    return symVector[symIndex];
75
76  Symbol *sym = reinterpret_cast<Symbol *>(make<SymbolUnion>());
77  symVector.push_back(sym);
78
79  // *sym was not initialized by a constructor. Fields that may get referenced
80  // when it is a placeholder must be initialized here.
81  sym->setName(name);
82  sym->symbolKind = Symbol::PlaceholderKind;
83  sym->versionId = VER_NDX_GLOBAL;
84  sym->visibility = STV_DEFAULT;
85  sym->isUsedInRegularObj = false;
86  sym->exportDynamic = false;
87  sym->inDynamicList = false;
88  sym->canInline = true;
89  sym->referenced = false;
90  sym->traced = false;
91  sym->scriptDefined = false;
92  sym->partition = 1;
93  return sym;
94}
95
96Symbol *SymbolTable::addSymbol(const Symbol &newSym) {
97  Symbol *sym = insert(newSym.getName());
98  sym->resolve(newSym);
99  return sym;
100}
101
102Symbol *SymbolTable::find(StringRef name) {
103  auto it = symMap.find(CachedHashStringRef(name));
104  if (it == symMap.end())
105    return nullptr;
106  Symbol *sym = symVector[it->second];
107  if (sym->isPlaceholder())
108    return nullptr;
109  return sym;
110}
111
112// A version script/dynamic list is only meaningful for a Defined symbol.
113// A CommonSymbol will be converted to a Defined in replaceCommonSymbols().
114// A lazy symbol may be made Defined if an LTO libcall fetches it.
115static bool canBeVersioned(const Symbol &sym) {
116  return sym.isDefined() || sym.isCommon() || sym.isLazy();
117}
118
119// Initialize demangledSyms with a map from demangled symbols to symbol
120// objects. Used to handle "extern C++" directive in version scripts.
121//
122// The map will contain all demangled symbols. That can be very large,
123// and in LLD we generally want to avoid do anything for each symbol.
124// Then, why are we doing this? Here's why.
125//
126// Users can use "extern C++ {}" directive to match against demangled
127// C++ symbols. For example, you can write a pattern such as
128// "llvm::*::foo(int, ?)". Obviously, there's no way to handle this
129// other than trying to match a pattern against all demangled symbols.
130// So, if "extern C++" feature is used, we need to demangle all known
131// symbols.
132StringMap<std::vector<Symbol *>> &SymbolTable::getDemangledSyms() {
133  if (!demangledSyms) {
134    demangledSyms.emplace();
135    for (Symbol *sym : symVector)
136      if (canBeVersioned(*sym))
137        (*demangledSyms)[demangleItanium(sym->getName())].push_back(sym);
138  }
139  return *demangledSyms;
140}
141
142std::vector<Symbol *> SymbolTable::findByVersion(SymbolVersion ver) {
143  if (ver.isExternCpp)
144    return getDemangledSyms().lookup(ver.name);
145  if (Symbol *sym = find(ver.name))
146    if (canBeVersioned(*sym))
147      return {sym};
148  return {};
149}
150
151std::vector<Symbol *> SymbolTable::findAllByVersion(SymbolVersion ver) {
152  std::vector<Symbol *> res;
153  SingleStringMatcher m(ver.name);
154
155  if (ver.isExternCpp) {
156    for (auto &p : getDemangledSyms())
157      if (m.match(p.first()))
158        res.insert(res.end(), p.second.begin(), p.second.end());
159    return res;
160  }
161
162  for (Symbol *sym : symVector)
163    if (canBeVersioned(*sym) && m.match(sym->getName()))
164      res.push_back(sym);
165  return res;
166}
167
168// Handles -dynamic-list.
169void SymbolTable::handleDynamicList() {
170  for (SymbolVersion &ver : config->dynamicList) {
171    std::vector<Symbol *> syms;
172    if (ver.hasWildcard)
173      syms = findAllByVersion(ver);
174    else
175      syms = findByVersion(ver);
176
177    for (Symbol *sym : syms)
178      sym->inDynamicList = true;
179  }
180}
181
182// Set symbol versions to symbols. This function handles patterns
183// containing no wildcard characters.
184void SymbolTable::assignExactVersion(SymbolVersion ver, uint16_t versionId,
185                                     StringRef versionName) {
186  if (ver.hasWildcard)
187    return;
188
189  // Get a list of symbols which we need to assign the version to.
190  std::vector<Symbol *> syms = findByVersion(ver);
191  if (syms.empty()) {
192    if (!config->undefinedVersion)
193      error("version script assignment of '" + versionName + "' to symbol '" +
194            ver.name + "' failed: symbol not defined");
195    return;
196  }
197
198  auto getName = [](uint16_t ver) -> std::string {
199    if (ver == VER_NDX_LOCAL)
200      return "VER_NDX_LOCAL";
201    if (ver == VER_NDX_GLOBAL)
202      return "VER_NDX_GLOBAL";
203    return ("version '" + config->versionDefinitions[ver].name + "'").str();
204  };
205
206  // Assign the version.
207  for (Symbol *sym : syms) {
208    // Skip symbols containing version info because symbol versions
209    // specified by symbol names take precedence over version scripts.
210    // See parseSymbolVersion().
211    if (sym->getName().contains('@'))
212      continue;
213
214    // If the version has not been assigned, verdefIndex is -1. Use an arbitrary
215    // number (0) to indicate the version has been assigned.
216    if (sym->verdefIndex == UINT32_C(-1)) {
217      sym->verdefIndex = 0;
218      sym->versionId = versionId;
219    }
220    if (sym->versionId == versionId)
221      continue;
222
223    warn("attempt to reassign symbol '" + ver.name + "' of " +
224         getName(sym->versionId) + " to " + getName(versionId));
225  }
226}
227
228void SymbolTable::assignWildcardVersion(SymbolVersion ver, uint16_t versionId) {
229  // Exact matching takes precedence over fuzzy matching,
230  // so we set a version to a symbol only if no version has been assigned
231  // to the symbol. This behavior is compatible with GNU.
232  for (Symbol *sym : findAllByVersion(ver))
233    if (sym->verdefIndex == UINT32_C(-1)) {
234      sym->verdefIndex = 0;
235      sym->versionId = versionId;
236    }
237}
238
239// This function processes version scripts by updating the versionId
240// member of symbols.
241// If there's only one anonymous version definition in a version
242// script file, the script does not actually define any symbol version,
243// but just specifies symbols visibilities.
244void SymbolTable::scanVersionScript() {
245  // First, we assign versions to exact matching symbols,
246  // i.e. version definitions not containing any glob meta-characters.
247  for (VersionDefinition &v : config->versionDefinitions)
248    for (SymbolVersion &pat : v.patterns)
249      assignExactVersion(pat, v.id, v.name);
250
251  // Next, assign versions to wildcards that are not "*". Note that because the
252  // last match takes precedence over previous matches, we iterate over the
253  // definitions in the reverse order.
254  for (VersionDefinition &v : llvm::reverse(config->versionDefinitions))
255    for (SymbolVersion &pat : v.patterns)
256      if (pat.hasWildcard && pat.name != "*")
257        assignWildcardVersion(pat, v.id);
258
259  // Then, assign versions to "*". In GNU linkers they have lower priority than
260  // other wildcards.
261  for (VersionDefinition &v : config->versionDefinitions)
262    for (SymbolVersion &pat : v.patterns)
263      if (pat.hasWildcard && pat.name == "*")
264        assignWildcardVersion(pat, v.id);
265
266  // Symbol themselves might know their versions because symbols
267  // can contain versions in the form of <name>@<version>.
268  // Let them parse and update their names to exclude version suffix.
269  for (Symbol *sym : symVector)
270    sym->parseSymbolVersion();
271
272  // isPreemptible is false at this point. To correctly compute the binding of a
273  // Defined (which is used by includeInDynsym()), we need to know if it is
274  // VER_NDX_LOCAL or not. Compute symbol versions before handling
275  // --dynamic-list.
276  handleDynamicList();
277}
278