Index: ELF/SymbolTable.cpp =================================================================== --- ELF/SymbolTable.cpp +++ ELF/SymbolTable.cpp @@ -460,15 +460,6 @@ // Returns a list of defined symbols that match with a given glob pattern. template std::vector SymbolTable::findAll(StringRef Pattern) { - // Fast-path. Fallback to find() if Pattern doesn't contain any wildcard - // characters. - if (Pattern.find_first_of("?*") == StringRef::npos) { - if (SymbolBody *B = find(Pattern)) - if (!B->isUndefined()) - return {B}; - return {}; - } - std::vector Res; for (auto &It : Symtab) { StringRef Name = It.first.Val; @@ -574,27 +565,48 @@ return; } + if (Config->SymbolVersions.empty()) + return; + // If we have symbols version declarations, we should // assign version references for each symbol. - size_t I = 2; - for (Version &V : Config->SymbolVersions) { - for (StringRef Name : V.Globals) { - std::vector Syms = findAll(Name); - if (Syms.empty()) { - if (Config->NoUndefinedVersion) - error("version script assignment of " + V.Name + " to symbol " + - Name + " failed: symbol not defined"); - continue; - } + // Current rules are: + // * 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 (Name.find_first_of("?*") == StringRef::npos) { + 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; + } - for (SymbolBody *B : Syms) { if (B->symbol()->VersionId != VER_NDX_GLOBAL && B->symbol()->VersionId != VER_NDX_LOCAL) warning("duplicate symbol " + Name + " in version script"); - B->symbol()->VersionId = I; + + B->symbol()->VersionId = I + 2; + } + } + + for (size_t I = Config->SymbolVersions.size() - 1; I != (size_t)-1; --I) { + Version &V = Config->SymbolVersions[I]; + for (StringRef Name : V.Globals) + if (Name.find_first_of("?*") != StringRef::npos) { + std::vector Syms = findAll(Name); + for (SymbolBody *B : Syms) { + if (B->symbol()->VersionId == VER_NDX_GLOBAL || + B->symbol()->VersionId == VER_NDX_LOCAL) + B->symbol()->VersionId = I + 2; + } } - } - ++I; } }