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