184487f11SMichael J. Spencer //===- SymbolTable.cpp ----------------------------------------------------===//
284487f11SMichael J. Spencer //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
684487f11SMichael J. Spencer //
784487f11SMichael J. Spencer //===----------------------------------------------------------------------===//
834f29246SRui Ueyama //
934f29246SRui Ueyama // Symbol table is a bag of all known symbols. We put all symbols of
10c9559d93SRui Ueyama // all input files to the symbol table. The symbol table is basically
1134f29246SRui Ueyama // a hash table with the logic to resolve symbol name conflicts using
1234f29246SRui Ueyama // the symbol types.
1334f29246SRui Ueyama //
1434f29246SRui Ueyama //===----------------------------------------------------------------------===//
1584487f11SMichael J. Spencer
1684487f11SMichael J. Spencer #include "SymbolTable.h"
174340aad1SRafael Espindola #include "Config.h"
1838fbedabSFangrui Song #include "InputFiles.h"
1984487f11SMichael J. Spencer #include "Symbols.h"
20b8a59c8aSBob Haarman #include "lld/Common/ErrorHandler.h"
212017d52bSRui Ueyama #include "lld/Common/Memory.h"
2253fe4691SRui Ueyama #include "lld/Common/Strings.h"
23cd236a95SRui Ueyama #include "llvm/ADT/STLExtras.h"
2484487f11SMichael J. Spencer
2584487f11SMichael J. Spencer using namespace llvm;
26daa92a61SRafael Espindola using namespace llvm::object;
2701205f79SRafael Espindola using namespace llvm::ELF;
2807837b8fSFangrui Song using namespace lld;
2907837b8fSFangrui Song using namespace lld::elf;
3084487f11SMichael J. Spencer
315fc4323eSFangrui Song std::unique_ptr<SymbolTable> elf::symtab;
32244ef981SRafael Espindola
wrap(Symbol * sym,Symbol * real,Symbol * wrap)333837f427SRui Ueyama void SymbolTable::wrap(Symbol *sym, Symbol *real, Symbol *wrap) {
34bf6e259bSFangrui Song // Redirect __real_foo to the original foo and foo to the original __wrap_foo.
353837f427SRui Ueyama int &idx1 = symMap[CachedHashStringRef(sym->getName())];
363837f427SRui Ueyama int &idx2 = symMap[CachedHashStringRef(real->getName())];
373837f427SRui Ueyama int &idx3 = symMap[CachedHashStringRef(wrap->getName())];
38c9c0ccc8SGeorge Rimar
393837f427SRui Ueyama idx2 = idx1;
403837f427SRui Ueyama idx1 = idx3;
41c9c0ccc8SGeorge Rimar
421af25a98SShoaib Meenai // Propagate symbol usage information to the redirected symbols.
431af25a98SShoaib Meenai if (sym->isUsedInRegularObj)
441af25a98SShoaib Meenai wrap->isUsedInRegularObj = true;
451af25a98SShoaib Meenai if (real->isUsedInRegularObj)
461af25a98SShoaib Meenai sym->isUsedInRegularObj = true;
47*2a04f5c4SShoaib Meenai else if (!sym->isDefined())
48*2a04f5c4SShoaib Meenai // Now that all references to sym have been redirected to wrap, if there are
49*2a04f5c4SShoaib Meenai // no references to real (which has been redirected to sym), we only need to
50*2a04f5c4SShoaib Meenai // keep sym if it was defined, otherwise it's unused and can be dropped.
510334578eSFangrui Song sym->isUsedInRegularObj = false;
52a6ae333aSFangrui Song
5354d28968SRui Ueyama // Now renaming is complete, and no one refers to real. We drop real from
5454d28968SRui Ueyama // .symtab and .dynsym. If real is undefined, it is important that we don't
5554d28968SRui Ueyama // leave it in .dynsym, because otherwise it might lead to an undefined symbol
5654d28968SRui Ueyama // error in a subsequent link. If real is defined, we could emit real as an
5754d28968SRui Ueyama // alias for sym, but that could degrade the user experience of some tools
5854d28968SRui Ueyama // that can print out only one symbol for each location: sym is a preferred
5954d28968SRui Ueyama // name than real, but they might print out real instead.
60a6ae333aSFangrui Song memcpy(real, sym, sizeof(SymbolUnion));
6154d28968SRui Ueyama real->isUsedInRegularObj = false;
6246935081SRafael Espindola }
639703ad22SGeorge Rimar
64bbf154cfSRui Ueyama // Find an existing symbol or create a new one.
insert(StringRef name)653837f427SRui Ueyama Symbol *SymbolTable::insert(StringRef name) {
663ddf2110SRafael Espindola // <name>@@<version> means the symbol is the default version. In that
673ddf2110SRafael Espindola // case <name>@@<version> will be used to resolve references to <name>.
6868b3acc4SRui Ueyama //
6968b3acc4SRui Ueyama // Since this is a hot path, the following string search code is
7068b3acc4SRui Ueyama // optimized for speed. StringRef::find(char) is much faster than
7168b3acc4SRui Ueyama // StringRef::find(StringRef).
722bdad163SFangrui Song StringRef stem = name;
733837f427SRui Ueyama size_t pos = name.find('@');
743837f427SRui Ueyama if (pos != StringRef::npos && pos + 1 < name.size() && name[pos + 1] == '@')
752bdad163SFangrui Song stem = name.take_front(pos);
763ddf2110SRafael Espindola
772bdad163SFangrui Song auto p = symMap.insert({CachedHashStringRef(stem), (int)symVector.size()});
78a2baf634SFangrui Song if (!p.second) {
79a2baf634SFangrui Song Symbol *sym = symVector[p.first->second];
807924b381SFangrui Song if (stem.size() != name.size()) {
812bdad163SFangrui Song sym->setName(name);
827924b381SFangrui Song sym->hasVersionSuffix = true;
837924b381SFangrui Song }
842bdad163SFangrui Song return sym;
852bdad163SFangrui Song }
86e65cb488SRui Ueyama
873837f427SRui Ueyama Symbol *sym = reinterpret_cast<Symbol *>(make<SymbolUnion>());
883837f427SRui Ueyama symVector.push_back(sym);
89bbf154cfSRui Ueyama
90f1d538ccSFangrui Song // *sym was not initialized by a constructor. Fields that may get referenced
91f1d538ccSFangrui Song // when it is a placeholder must be initialized here.
923837f427SRui Ueyama sym->setName(name);
933837f427SRui Ueyama sym->symbolKind = Symbol::PlaceholderKind;
9473f55fbaSFangrui Song sym->partition = 1;
953837f427SRui Ueyama sym->visibility = STV_DEFAULT;
963837f427SRui Ueyama sym->isUsedInRegularObj = false;
973837f427SRui Ueyama sym->exportDynamic = false;
98c6cd6235SFangrui Song sym->inDynamicList = false;
99f1d538ccSFangrui Song sym->referenced = false;
100f1d538ccSFangrui Song sym->traced = false;
1013837f427SRui Ueyama sym->scriptDefined = false;
10273f55fbaSFangrui Song sym->versionId = VER_NDX_GLOBAL;
1037924b381SFangrui Song if (pos != StringRef::npos)
1047924b381SFangrui Song sym->hasVersionSuffix = true;
1053837f427SRui Ueyama return sym;
1064f952706SPeter Collingbourne }
107dadcc17eSPeter Collingbourne
addSymbol(const Symbol & newSym)108ab04ad6aSFangrui Song Symbol *SymbolTable::addSymbol(const Symbol &newSym) {
109dc6b3f03SWilliam S. Moses Symbol *sym = insert(newSym.getName());
110ab04ad6aSFangrui Song sym->resolve(newSym);
1113837f427SRui Ueyama return sym;
1124f952706SPeter Collingbourne }
1134f952706SPeter Collingbourne
11488d66f6eSFangrui Song // This variant of addSymbol is used by BinaryFile::parse to check duplicate
11588d66f6eSFangrui Song // symbol errors.
addAndCheckDuplicate(const Defined & newSym)11688d66f6eSFangrui Song Symbol *SymbolTable::addAndCheckDuplicate(const Defined &newSym) {
11788d66f6eSFangrui Song Symbol *sym = insert(newSym.getName());
11888d66f6eSFangrui Song if (sym->isDefined())
11988d66f6eSFangrui Song sym->checkDuplicate(newSym);
12088d66f6eSFangrui Song sym->resolve(newSym);
1218ca46bbaSFangrui Song sym->isUsedInRegularObj = true;
12288d66f6eSFangrui Song return sym;
12388d66f6eSFangrui Song }
12488d66f6eSFangrui Song
find(StringRef name)1253837f427SRui Ueyama Symbol *SymbolTable::find(StringRef name) {
1263837f427SRui Ueyama auto it = symMap.find(CachedHashStringRef(name));
1273837f427SRui Ueyama if (it == symMap.end())
128f8432d97SRui Ueyama return nullptr;
12989661a0eSFangrui Song return symVector[it->second];
1301b348a68SMichael J. Spencer }
1311b348a68SMichael J. Spencer
132c1c679e2SFangrui Song // A version script/dynamic list is only meaningful for a Defined symbol.
133c1c679e2SFangrui Song // A CommonSymbol will be converted to a Defined in replaceCommonSymbols().
13409401dfcSFangrui Song // A lazy symbol may be made Defined if an LTO libcall extracts it.
canBeVersioned(const Symbol & sym)135c1c679e2SFangrui Song static bool canBeVersioned(const Symbol &sym) {
136c1c679e2SFangrui Song return sym.isDefined() || sym.isCommon() || sym.isLazy();
137c1c679e2SFangrui Song }
138c1c679e2SFangrui Song
13947cfe8f3SFangrui Song // Initialize demangledSyms with a map from demangled symbols to symbol
14082492142SRui Ueyama // objects. Used to handle "extern C++" directive in version scripts.
14182492142SRui Ueyama //
14282492142SRui Ueyama // The map will contain all demangled symbols. That can be very large,
14382492142SRui Ueyama // and in LLD we generally want to avoid do anything for each symbol.
14482492142SRui Ueyama // Then, why are we doing this? Here's why.
14582492142SRui Ueyama //
14682492142SRui Ueyama // Users can use "extern C++ {}" directive to match against demangled
14782492142SRui Ueyama // C++ symbols. For example, you can write a pattern such as
14882492142SRui Ueyama // "llvm::*::foo(int, ?)". Obviously, there's no way to handle this
14982492142SRui Ueyama // other than trying to match a pattern against all demangled symbols.
15082492142SRui Ueyama // So, if "extern C++" feature is used, we need to demangle all known
15182492142SRui Ueyama // symbols.
getDemangledSyms()152417cd2e5SFangrui Song StringMap<SmallVector<Symbol *, 0>> &SymbolTable::getDemangledSyms() {
1533837f427SRui Ueyama if (!demangledSyms) {
1543837f427SRui Ueyama demangledSyms.emplace();
15500809c88SFangrui Song std::string demangled;
156c1c679e2SFangrui Song for (Symbol *sym : symVector)
15700809c88SFangrui Song if (canBeVersioned(*sym)) {
15800809c88SFangrui Song StringRef name = sym->getName();
15900809c88SFangrui Song size_t pos = name.find('@');
16000809c88SFangrui Song if (pos == std::string::npos)
16110e40a4eSLuís Ferreira demangled = demangle(name, config->demangle);
16200809c88SFangrui Song else if (pos + 1 == name.size() || name[pos + 1] == '@')
16310e40a4eSLuís Ferreira demangled = demangle(name.substr(0, pos), config->demangle);
16400809c88SFangrui Song else
16510e40a4eSLuís Ferreira demangled = (demangle(name.substr(0, pos), config->demangle) +
16610e40a4eSLuís Ferreira name.substr(pos))
16710e40a4eSLuís Ferreira .str();
16800809c88SFangrui Song (*demangledSyms)[demangled].push_back(sym);
16900809c88SFangrui Song }
170d6328526SRui Ueyama }
1713837f427SRui Ueyama return *demangledSyms;
17296aff375SRui Ueyama }
17350dcece2SGeorge Rimar
findByVersion(SymbolVersion ver)174417cd2e5SFangrui Song SmallVector<Symbol *, 0> SymbolTable::findByVersion(SymbolVersion ver) {
1753837f427SRui Ueyama if (ver.isExternCpp)
1763837f427SRui Ueyama return getDemangledSyms().lookup(ver.name);
177c1c679e2SFangrui Song if (Symbol *sym = find(ver.name))
178c1c679e2SFangrui Song if (canBeVersioned(*sym))
179c1c679e2SFangrui Song return {sym};
1804c134ea3SRui Ueyama return {};
181c65aee64SRafael Espindola }
182c65aee64SRafael Espindola
findAllByVersion(SymbolVersion ver,bool includeNonDefault)183417cd2e5SFangrui Song SmallVector<Symbol *, 0> SymbolTable::findAllByVersion(SymbolVersion ver,
18400809c88SFangrui Song bool includeNonDefault) {
185417cd2e5SFangrui Song SmallVector<Symbol *, 0> res;
186c42fe247SThomas Preud'homme SingleStringMatcher m(ver.name);
18700809c88SFangrui Song auto check = [&](StringRef name) {
18800809c88SFangrui Song size_t pos = name.find('@');
18900809c88SFangrui Song if (!includeNonDefault)
19000809c88SFangrui Song return pos == StringRef::npos;
19100809c88SFangrui Song return !(pos + 1 < name.size() && name[pos + 1] == '@');
19200809c88SFangrui Song };
193191390a8SRafael Espindola
1943837f427SRui Ueyama if (ver.isExternCpp) {
1953837f427SRui Ueyama for (auto &p : getDemangledSyms())
1963837f427SRui Ueyama if (m.match(p.first()))
19700809c88SFangrui Song for (Symbol *sym : p.second)
19800809c88SFangrui Song if (check(sym->getName()))
19900809c88SFangrui Song res.push_back(sym);
2003837f427SRui Ueyama return res;
201397cd87aSGeorge Rimar }
202191390a8SRafael Espindola
2033837f427SRui Ueyama for (Symbol *sym : symVector)
20400809c88SFangrui Song if (canBeVersioned(*sym) && check(sym->getName()) &&
20500809c88SFangrui Song m.match(sym->getName()))
2063837f427SRui Ueyama res.push_back(sym);
2073837f427SRui Ueyama return res;
208c65aee64SRafael Espindola }
209c65aee64SRafael Espindola
handleDynamicList()210d72d97b3SRafael Espindola void SymbolTable::handleDynamicList() {
211417cd2e5SFangrui Song SmallVector<Symbol *, 0> syms;
2123837f427SRui Ueyama for (SymbolVersion &ver : config->dynamicList) {
2133837f427SRui Ueyama if (ver.hasWildcard)
21400809c88SFangrui Song syms = findAllByVersion(ver, /*includeNonDefault=*/true);
2159ac3154dSEvgeniy Stepanov else
2163837f427SRui Ueyama syms = findByVersion(ver);
217d72d97b3SRafael Espindola
218c6cd6235SFangrui Song for (Symbol *sym : syms)
219c6cd6235SFangrui Song sym->inDynamicList = true;
220d72d97b3SRafael Espindola }
221d72d97b3SRafael Espindola }
222d72d97b3SRafael Espindola
22300809c88SFangrui Song // Set symbol versions to symbols. This function handles patterns containing no
22400809c88SFangrui Song // wildcard characters. Return false if no symbol definition matches ver.
assignExactVersion(SymbolVersion ver,uint16_t versionId,StringRef versionName,bool includeNonDefault)22500809c88SFangrui Song bool SymbolTable::assignExactVersion(SymbolVersion ver, uint16_t versionId,
22600809c88SFangrui Song StringRef versionName,
22700809c88SFangrui Song bool includeNonDefault) {
22894bcfae2SRui Ueyama // Get a list of symbols which we need to assign the version to.
229417cd2e5SFangrui Song SmallVector<Symbol *, 0> syms = findByVersion(ver);
23094bcfae2SRui Ueyama
231be827575SFangrui Song auto getName = [](uint16_t ver) -> std::string {
232be827575SFangrui Song if (ver == VER_NDX_LOCAL)
233be827575SFangrui Song return "VER_NDX_LOCAL";
234be827575SFangrui Song if (ver == VER_NDX_GLOBAL)
235be827575SFangrui Song return "VER_NDX_GLOBAL";
236e28a70daSFangrui Song return ("version '" + config->versionDefinitions[ver].name + "'").str();
237be827575SFangrui Song };
238be827575SFangrui Song
2394c134ea3SRui Ueyama // Assign the version.
2403837f427SRui Ueyama for (Symbol *sym : syms) {
24100809c88SFangrui Song // For a non-local versionId, skip symbols containing version info because
24200809c88SFangrui Song // symbol versions specified by symbol names take precedence over version
24300809c88SFangrui Song // scripts. See parseSymbolVersion().
24400809c88SFangrui Song if (!includeNonDefault && versionId != VER_NDX_LOCAL &&
24500809c88SFangrui Song sym->getName().contains('@'))
2463e8a461bSGeorge Rimar continue;
2473e8a461bSGeorge Rimar
248e28a70daSFangrui Song // If the version has not been assigned, verdefIndex is -1. Use an arbitrary
249e28a70daSFangrui Song // number (0) to indicate the version has been assigned.
250b0211de5SFangrui Song if (sym->verdefIndex == uint16_t(-1)) {
251e28a70daSFangrui Song sym->verdefIndex = 0;
2523837f427SRui Ueyama sym->versionId = versionId;
253e28a70daSFangrui Song }
254be827575SFangrui Song if (sym->versionId == versionId)
255be827575SFangrui Song continue;
256be827575SFangrui Song
257be827575SFangrui Song warn("attempt to reassign symbol '" + ver.name + "' of " +
258be827575SFangrui Song getName(sym->versionId) + " to " + getName(versionId));
25994bcfae2SRui Ueyama }
26000809c88SFangrui Song return !syms.empty();
26194bcfae2SRui Ueyama }
26294bcfae2SRui Ueyama
assignWildcardVersion(SymbolVersion ver,uint16_t versionId,bool includeNonDefault)26300809c88SFangrui Song void SymbolTable::assignWildcardVersion(SymbolVersion ver, uint16_t versionId,
26400809c88SFangrui Song bool includeNonDefault) {
2655976a3f5SNico Weber // Exact matching takes precedence over fuzzy matching,
26682492142SRui Ueyama // so we set a version to a symbol only if no version has been assigned
26782492142SRui Ueyama // to the symbol. This behavior is compatible with GNU.
26800809c88SFangrui Song for (Symbol *sym : findAllByVersion(ver, includeNonDefault))
269b0211de5SFangrui Song if (sym->verdefIndex == uint16_t(-1)) {
270e28a70daSFangrui Song sym->verdefIndex = 0;
271e28a70daSFangrui Song sym->versionId = versionId;
272e28a70daSFangrui Song }
27382492142SRui Ueyama }
27482492142SRui Ueyama
27547cfe8f3SFangrui Song // This function processes version scripts by updating the versionId
276ea26504cSRui Ueyama // member of symbols.
277e1ee3837SFangrui Song // If there's only one anonymous version definition in a version
278e1ee3837SFangrui Song // script file, the script does not actually define any symbol version,
279e1ee3837SFangrui Song // but just specifies symbols visibilities.
scanVersionScript()280244ef981SRafael Espindola void SymbolTable::scanVersionScript() {
28100809c88SFangrui Song SmallString<128> buf;
282dad2b88cSRui Ueyama // First, we assign versions to exact matching symbols,
283dad2b88cSRui Ueyama // i.e. version definitions not containing any glob meta-characters.
28400809c88SFangrui Song for (VersionDefinition &v : config->versionDefinitions) {
28500809c88SFangrui Song auto assignExact = [&](SymbolVersion pat, uint16_t id, StringRef ver) {
28600809c88SFangrui Song bool found =
28700809c88SFangrui Song assignExactVersion(pat, id, ver, /*includeNonDefault=*/false);
28800809c88SFangrui Song buf.clear();
28900809c88SFangrui Song found |= assignExactVersion({(pat.name + "@" + v.name).toStringRef(buf),
29000809c88SFangrui Song pat.isExternCpp, /*hasWildCard=*/false},
29100809c88SFangrui Song id, ver, /*includeNonDefault=*/true);
29200809c88SFangrui Song if (!found && !config->undefinedVersion)
29300809c88SFangrui Song errorOrWarn("version script assignment of '" + ver + "' to symbol '" +
29400809c88SFangrui Song pat.name + "' failed: symbol not defined");
29500809c88SFangrui Song };
29600809c88SFangrui Song for (SymbolVersion &pat : v.nonLocalPatterns)
29700809c88SFangrui Song if (!pat.hasWildcard)
29800809c88SFangrui Song assignExact(pat, v.id, v.name);
29900809c88SFangrui Song for (SymbolVersion pat : v.localPatterns)
30000809c88SFangrui Song if (!pat.hasWildcard)
30100809c88SFangrui Song assignExact(pat, VER_NDX_LOCAL, "local");
30200809c88SFangrui Song }
303f73a2581SGeorge Rimar
304e28a70daSFangrui Song // Next, assign versions to wildcards that are not "*". Note that because the
305e28a70daSFangrui Song // last match takes precedence over previous matches, we iterate over the
306e28a70daSFangrui Song // definitions in the reverse order.
30700809c88SFangrui Song auto assignWildcard = [&](SymbolVersion pat, uint16_t id, StringRef ver) {
30800809c88SFangrui Song assignWildcardVersion(pat, id, /*includeNonDefault=*/false);
30900809c88SFangrui Song buf.clear();
31000809c88SFangrui Song assignWildcardVersion({(pat.name + "@" + ver).toStringRef(buf),
31100809c88SFangrui Song pat.isExternCpp, /*hasWildCard=*/true},
31200809c88SFangrui Song id,
31300809c88SFangrui Song /*includeNonDefault=*/true);
31400809c88SFangrui Song };
31500809c88SFangrui Song for (VersionDefinition &v : llvm::reverse(config->versionDefinitions)) {
31600809c88SFangrui Song for (SymbolVersion &pat : v.nonLocalPatterns)
317e28a70daSFangrui Song if (pat.hasWildcard && pat.name != "*")
31800809c88SFangrui Song assignWildcard(pat, v.id, v.name);
31900809c88SFangrui Song for (SymbolVersion &pat : v.localPatterns)
32000809c88SFangrui Song if (pat.hasWildcard && pat.name != "*")
32100809c88SFangrui Song assignWildcard(pat, VER_NDX_LOCAL, v.name);
32200809c88SFangrui Song }
323e28a70daSFangrui Song
324e28a70daSFangrui Song // Then, assign versions to "*". In GNU linkers they have lower priority than
325e28a70daSFangrui Song // other wildcards.
32600809c88SFangrui Song for (VersionDefinition &v : config->versionDefinitions) {
32700809c88SFangrui Song for (SymbolVersion &pat : v.nonLocalPatterns)
328e28a70daSFangrui Song if (pat.hasWildcard && pat.name == "*")
32900809c88SFangrui Song assignWildcard(pat, v.id, v.name);
33000809c88SFangrui Song for (SymbolVersion &pat : v.localPatterns)
33100809c88SFangrui Song if (pat.hasWildcard && pat.name == "*")
33200809c88SFangrui Song assignWildcard(pat, VER_NDX_LOCAL, v.name);
33300809c88SFangrui Song }
3343e8a461bSGeorge Rimar
3353e8a461bSGeorge Rimar // Symbol themselves might know their versions because symbols
3363e8a461bSGeorge Rimar // can contain versions in the form of <name>@<version>.
3373e8a461bSGeorge Rimar // Let them parse and update their names to exclude version suffix.
3383837f427SRui Ueyama for (Symbol *sym : symVector)
3397924b381SFangrui Song if (sym->hasVersionSuffix)
3403837f427SRui Ueyama sym->parseSymbolVersion();
341e1ee3837SFangrui Song
342e1ee3837SFangrui Song // isPreemptible is false at this point. To correctly compute the binding of a
343e1ee3837SFangrui Song // Defined (which is used by includeInDynsym()), we need to know if it is
344e28a70daSFangrui Song // VER_NDX_LOCAL or not. Compute symbol versions before handling
345e28a70daSFangrui Song // --dynamic-list.
346e1ee3837SFangrui Song handleDynamicList();
347397cd87aSGeorge Rimar }
348