Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / lld / ELF / SymbolTable.cpp
blobfe7edd5b0eb49aa5fb9247fd4ed173f736028299
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.
14 //===----------------------------------------------------------------------===//
16 #include "SymbolTable.h"
17 #include "Config.h"
18 #include "InputFiles.h"
19 #include "Symbols.h"
20 #include "lld/Common/ErrorHandler.h"
21 #include "lld/Common/Memory.h"
22 #include "lld/Common/Strings.h"
23 #include "llvm/ADT/STLExtras.h"
24 #include "llvm/Demangle/Demangle.h"
26 using namespace llvm;
27 using namespace llvm::object;
28 using namespace llvm::ELF;
29 using namespace lld;
30 using namespace lld::elf;
32 SymbolTable elf::symtab;
34 void SymbolTable::wrap(Symbol *sym, Symbol *real, Symbol *wrap) {
35 // Redirect __real_foo to the original foo and foo to the original __wrap_foo.
36 int &idx1 = symMap[CachedHashStringRef(sym->getName())];
37 int &idx2 = symMap[CachedHashStringRef(real->getName())];
38 int &idx3 = symMap[CachedHashStringRef(wrap->getName())];
40 idx2 = idx1;
41 idx1 = idx3;
43 // Propagate symbol usage information to the redirected symbols.
44 if (sym->isUsedInRegularObj)
45 wrap->isUsedInRegularObj = true;
46 if (real->isUsedInRegularObj)
47 sym->isUsedInRegularObj = true;
48 else if (!sym->isDefined())
49 // Now that all references to sym have been redirected to wrap, if there are
50 // no references to real (which has been redirected to sym), we only need to
51 // keep sym if it was defined, otherwise it's unused and can be dropped.
52 sym->isUsedInRegularObj = false;
54 // Now renaming is complete, and no one refers to real. We drop real from
55 // .symtab and .dynsym. If real is undefined, it is important that we don't
56 // leave it in .dynsym, because otherwise it might lead to an undefined symbol
57 // error in a subsequent link. If real is defined, we could emit real as an
58 // alias for sym, but that could degrade the user experience of some tools
59 // that can print out only one symbol for each location: sym is a preferred
60 // name than real, but they might print out real instead.
61 memcpy(real, sym, sizeof(SymbolUnion));
62 real->isUsedInRegularObj = false;
65 // Find an existing symbol or create a new one.
66 Symbol *SymbolTable::insert(StringRef name) {
67 // <name>@@<version> means the symbol is the default version. In that
68 // case <name>@@<version> will be used to resolve references to <name>.
70 // Since this is a hot path, the following string search code is
71 // optimized for speed. StringRef::find(char) is much faster than
72 // StringRef::find(StringRef).
73 StringRef stem = name;
74 size_t pos = name.find('@');
75 if (pos != StringRef::npos && pos + 1 < name.size() && name[pos + 1] == '@')
76 stem = name.take_front(pos);
78 auto p = symMap.insert({CachedHashStringRef(stem), (int)symVector.size()});
79 if (!p.second) {
80 Symbol *sym = symVector[p.first->second];
81 if (stem.size() != name.size()) {
82 sym->setName(name);
83 sym->hasVersionSuffix = true;
85 return sym;
88 Symbol *sym = reinterpret_cast<Symbol *>(make<SymbolUnion>());
89 symVector.push_back(sym);
91 // *sym was not initialized by a constructor. Initialize all Symbol fields.
92 memset(sym, 0, sizeof(Symbol));
93 sym->setName(name);
94 sym->partition = 1;
95 sym->verdefIndex = -1;
96 sym->versionId = VER_NDX_GLOBAL;
97 if (pos != StringRef::npos)
98 sym->hasVersionSuffix = true;
99 return sym;
102 // This variant of addSymbol is used by BinaryFile::parse to check duplicate
103 // symbol errors.
104 Symbol *SymbolTable::addAndCheckDuplicate(const Defined &newSym) {
105 Symbol *sym = insert(newSym.getName());
106 if (sym->isDefined())
107 sym->checkDuplicate(newSym);
108 sym->resolve(newSym);
109 sym->isUsedInRegularObj = true;
110 return sym;
113 Symbol *SymbolTable::find(StringRef name) {
114 auto it = symMap.find(CachedHashStringRef(name));
115 if (it == symMap.end())
116 return nullptr;
117 return symVector[it->second];
120 // A version script/dynamic list is only meaningful for a Defined symbol.
121 // A CommonSymbol will be converted to a Defined in replaceCommonSymbols().
122 // A lazy symbol may be made Defined if an LTO libcall extracts it.
123 static bool canBeVersioned(const Symbol &sym) {
124 return sym.isDefined() || sym.isCommon() || sym.isLazy();
127 // Initialize demangledSyms with a map from demangled symbols to symbol
128 // objects. Used to handle "extern C++" directive in version scripts.
130 // The map will contain all demangled symbols. That can be very large,
131 // and in LLD we generally want to avoid do anything for each symbol.
132 // Then, why are we doing this? Here's why.
134 // Users can use "extern C++ {}" directive to match against demangled
135 // C++ symbols. For example, you can write a pattern such as
136 // "llvm::*::foo(int, ?)". Obviously, there's no way to handle this
137 // other than trying to match a pattern against all demangled symbols.
138 // So, if "extern C++" feature is used, we need to demangle all known
139 // symbols.
140 StringMap<SmallVector<Symbol *, 0>> &SymbolTable::getDemangledSyms() {
141 if (!demangledSyms) {
142 demangledSyms.emplace();
143 std::string demangled;
144 for (Symbol *sym : symVector)
145 if (canBeVersioned(*sym)) {
146 StringRef name = sym->getName();
147 size_t pos = name.find('@');
148 std::string substr;
149 if (pos == std::string::npos)
150 demangled = demangle(name);
151 else if (pos + 1 == name.size() || name[pos + 1] == '@') {
152 substr = name.substr(0, pos);
153 demangled = demangle(substr);
154 } else {
155 substr = name.substr(0, pos);
156 demangled = (demangle(substr) + name.substr(pos)).str();
158 (*demangledSyms)[demangled].push_back(sym);
161 return *demangledSyms;
164 SmallVector<Symbol *, 0> SymbolTable::findByVersion(SymbolVersion ver) {
165 if (ver.isExternCpp)
166 return getDemangledSyms().lookup(ver.name);
167 if (Symbol *sym = find(ver.name))
168 if (canBeVersioned(*sym))
169 return {sym};
170 return {};
173 SmallVector<Symbol *, 0> SymbolTable::findAllByVersion(SymbolVersion ver,
174 bool includeNonDefault) {
175 SmallVector<Symbol *, 0> res;
176 SingleStringMatcher m(ver.name);
177 auto check = [&](const Symbol &sym) -> bool {
178 if (!includeNonDefault)
179 return !sym.hasVersionSuffix;
180 StringRef name = sym.getName();
181 size_t pos = name.find('@');
182 return !(pos + 1 < name.size() && name[pos + 1] == '@');
185 if (ver.isExternCpp) {
186 for (auto &p : getDemangledSyms())
187 if (m.match(p.first()))
188 for (Symbol *sym : p.second)
189 if (check(*sym))
190 res.push_back(sym);
191 return res;
194 for (Symbol *sym : symVector)
195 if (canBeVersioned(*sym) && check(*sym) && m.match(sym->getName()))
196 res.push_back(sym);
197 return res;
200 void SymbolTable::handleDynamicList() {
201 SmallVector<Symbol *, 0> syms;
202 for (SymbolVersion &ver : config->dynamicList) {
203 if (ver.hasWildcard)
204 syms = findAllByVersion(ver, /*includeNonDefault=*/true);
205 else
206 syms = findByVersion(ver);
208 for (Symbol *sym : syms)
209 sym->inDynamicList = true;
213 // Set symbol versions to symbols. This function handles patterns containing no
214 // wildcard characters. Return false if no symbol definition matches ver.
215 bool SymbolTable::assignExactVersion(SymbolVersion ver, uint16_t versionId,
216 StringRef versionName,
217 bool includeNonDefault) {
218 // Get a list of symbols which we need to assign the version to.
219 SmallVector<Symbol *, 0> syms = findByVersion(ver);
221 auto getName = [](uint16_t ver) -> std::string {
222 if (ver == VER_NDX_LOCAL)
223 return "VER_NDX_LOCAL";
224 if (ver == VER_NDX_GLOBAL)
225 return "VER_NDX_GLOBAL";
226 return ("version '" + config->versionDefinitions[ver].name + "'").str();
229 // Assign the version.
230 for (Symbol *sym : syms) {
231 // For a non-local versionId, skip symbols containing version info because
232 // symbol versions specified by symbol names take precedence over version
233 // scripts. See parseSymbolVersion().
234 if (!includeNonDefault && versionId != VER_NDX_LOCAL &&
235 sym->getName().contains('@'))
236 continue;
238 // If the version has not been assigned, verdefIndex is -1. Use an arbitrary
239 // number (0) to indicate the version has been assigned.
240 if (sym->verdefIndex == uint16_t(-1)) {
241 sym->verdefIndex = 0;
242 sym->versionId = versionId;
244 if (sym->versionId == versionId)
245 continue;
247 warn("attempt to reassign symbol '" + ver.name + "' of " +
248 getName(sym->versionId) + " to " + getName(versionId));
250 return !syms.empty();
253 void SymbolTable::assignWildcardVersion(SymbolVersion ver, uint16_t versionId,
254 bool includeNonDefault) {
255 // Exact matching takes precedence over fuzzy matching,
256 // so we set a version to a symbol only if no version has been assigned
257 // to the symbol. This behavior is compatible with GNU.
258 for (Symbol *sym : findAllByVersion(ver, includeNonDefault))
259 if (sym->verdefIndex == uint16_t(-1)) {
260 sym->verdefIndex = 0;
261 sym->versionId = versionId;
265 // This function processes version scripts by updating the versionId
266 // member of symbols.
267 // If there's only one anonymous version definition in a version
268 // script file, the script does not actually define any symbol version,
269 // but just specifies symbols visibilities.
270 void SymbolTable::scanVersionScript() {
271 SmallString<128> buf;
272 // First, we assign versions to exact matching symbols,
273 // i.e. version definitions not containing any glob meta-characters.
274 for (VersionDefinition &v : config->versionDefinitions) {
275 auto assignExact = [&](SymbolVersion pat, uint16_t id, StringRef ver) {
276 bool found =
277 assignExactVersion(pat, id, ver, /*includeNonDefault=*/false);
278 buf.clear();
279 found |= assignExactVersion({(pat.name + "@" + v.name).toStringRef(buf),
280 pat.isExternCpp, /*hasWildCard=*/false},
281 id, ver, /*includeNonDefault=*/true);
282 if (!found && !config->undefinedVersion)
283 errorOrWarn("version script assignment of '" + ver + "' to symbol '" +
284 pat.name + "' failed: symbol not defined");
286 for (SymbolVersion &pat : v.nonLocalPatterns)
287 if (!pat.hasWildcard)
288 assignExact(pat, v.id, v.name);
289 for (SymbolVersion pat : v.localPatterns)
290 if (!pat.hasWildcard)
291 assignExact(pat, VER_NDX_LOCAL, "local");
294 // Next, assign versions to wildcards that are not "*". Note that because the
295 // last match takes precedence over previous matches, we iterate over the
296 // definitions in the reverse order.
297 auto assignWildcard = [&](SymbolVersion pat, uint16_t id, StringRef ver) {
298 assignWildcardVersion(pat, id, /*includeNonDefault=*/false);
299 buf.clear();
300 assignWildcardVersion({(pat.name + "@" + ver).toStringRef(buf),
301 pat.isExternCpp, /*hasWildCard=*/true},
303 /*includeNonDefault=*/true);
305 for (VersionDefinition &v : llvm::reverse(config->versionDefinitions)) {
306 for (SymbolVersion &pat : v.nonLocalPatterns)
307 if (pat.hasWildcard && pat.name != "*")
308 assignWildcard(pat, v.id, v.name);
309 for (SymbolVersion &pat : v.localPatterns)
310 if (pat.hasWildcard && pat.name != "*")
311 assignWildcard(pat, VER_NDX_LOCAL, v.name);
314 // Then, assign versions to "*". In GNU linkers they have lower priority than
315 // other wildcards.
316 for (VersionDefinition &v : llvm::reverse(config->versionDefinitions)) {
317 for (SymbolVersion &pat : v.nonLocalPatterns)
318 if (pat.hasWildcard && pat.name == "*")
319 assignWildcard(pat, v.id, v.name);
320 for (SymbolVersion &pat : v.localPatterns)
321 if (pat.hasWildcard && pat.name == "*")
322 assignWildcard(pat, VER_NDX_LOCAL, v.name);
325 // Symbol themselves might know their versions because symbols
326 // can contain versions in the form of <name>@<version>.
327 // Let them parse and update their names to exclude version suffix.
328 for (Symbol *sym : symVector)
329 if (sym->hasVersionSuffix)
330 sym->parseSymbolVersion();
332 // isPreemptible is false at this point. To correctly compute the binding of a
333 // Defined (which is used by includeInDynsym()), we need to know if it is
334 // VER_NDX_LOCAL or not. Compute symbol versions before handling
335 // --dynamic-list.
336 handleDynamicList();