diff options
Diffstat (limited to 'lld/ELF/SymbolTable.cpp')
-rw-r--r-- | lld/ELF/SymbolTable.cpp | 72 |
1 files changed, 22 insertions, 50 deletions
diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp index b3887249be0..2474bb35a54 100644 --- a/lld/ELF/SymbolTable.cpp +++ b/lld/ELF/SymbolTable.cpp @@ -567,37 +567,6 @@ static bool hasWildcard(StringRef S) { return S.find_first_of("?*") != StringRef::npos; } -static void setVersionId(SymbolBody *Body, StringRef VersionName, - StringRef Name, uint16_t Version) { - if (!Body || Body->isUndefined()) { - if (Config->NoUndefinedVersion) - error("version script assignment of " + VersionName + " to symbol " + - Name + " failed: symbol not defined"); - return; - } - - Symbol *Sym = Body->symbol(); - if (Sym->VersionId != VER_NDX_GLOBAL && Sym->VersionId != VER_NDX_LOCAL) - warning("duplicate symbol " + Name + " in version script"); - Sym->VersionId = Version; -} - -template <class ELFT> -std::map<std::string, SymbolBody *> SymbolTable<ELFT>::getDemangledSyms() { - std::map<std::string, SymbolBody *> Result; - for (std::pair<SymName, unsigned> Sym : Symtab) - Result[demangle(Sym.first.Val)] = SymVector[Sym.second]->body(); - return Result; -} - -static bool hasExternCpp() { - for (Version& V : Config->SymbolVersions) - for (SymbolVersion Sym : V.Globals) - if (Sym.IsExternCpp) - return true; - return false; -} - // This function processes the --version-script option by marking all global // symbols with the VersionScriptGlobal flag, which acts as a filter on the // dynamic symbol table. @@ -605,8 +574,8 @@ template <class ELFT> void SymbolTable<ELFT>::scanVersionScript() { // If version script does not contain versions declarations, // we just should mark global symbols. if (!Config->VersionScriptGlobals.empty()) { - for (SymbolVersion &Sym : Config->VersionScriptGlobals) - if (SymbolBody *B = find(Sym.Name)) + for (StringRef S : Config->VersionScriptGlobals) + if (SymbolBody *B = find(S)) B->symbol()->VersionId = VER_NDX_GLOBAL; return; } @@ -617,35 +586,38 @@ template <class ELFT> void SymbolTable<ELFT>::scanVersionScript() { // If we have symbols version declarations, we should // assign version references for each symbol. // Current rules are: - // * If there is an exact match for the mangled name or we have extern C++ - // exact match, then we use it. + // * If there is an exact match for the mangled name, we use it. // * Otherwise, we look through the wildcard patterns. We look through the // version tags in reverse order. We use the first match we find (the last // matching version tag in the file). + for (size_t I = 0, E = Config->SymbolVersions.size(); I < E; ++I) { + Version &V = Config->SymbolVersions[I]; + for (StringRef Name : V.Globals) { + if (hasWildcard(Name)) + continue; - // Handle exact matches and build a map of demangled externs for - // quick search during next step. - std::map<std::string, SymbolBody *> Demangled; - if (hasExternCpp()) - Demangled = getDemangledSyms(); - - for (Version &V : Config->SymbolVersions) { - for (SymbolVersion Sym : V.Globals) { - if (hasWildcard(Sym.Name)) + SymbolBody *B = find(Name); + if (!B || B->isUndefined()) { + if (Config->NoUndefinedVersion) + error("version script assignment of " + V.Name + " to symbol " + + Name + " failed: symbol not defined"); continue; - SymbolBody *B = Sym.IsExternCpp ? Demangled[Sym.Name] : find(Sym.Name); - setVersionId(B, V.Name, Sym.Name, V.Id); + } + + if (B->symbol()->VersionId != VER_NDX_GLOBAL && + B->symbol()->VersionId != VER_NDX_LOCAL) + warning("duplicate symbol " + Name + " in version script"); + B->symbol()->VersionId = V.Id; } } - // Handle wildcards. for (size_t I = Config->SymbolVersions.size() - 1; I != (size_t)-1; --I) { Version &V = Config->SymbolVersions[I]; - for (SymbolVersion Sym : V.Globals) { - if (!hasWildcard(Sym.Name)) + for (StringRef Name : V.Globals) { + if (!hasWildcard(Name)) continue; - for (SymbolBody *B : findAll(Sym.Name)) + for (SymbolBody *B : findAll(Name)) if (B->symbol()->VersionId == VER_NDX_GLOBAL || B->symbol()->VersionId == VER_NDX_LOCAL) B->symbol()->VersionId = V.Id; |