Index: ELF/SymbolTable.cpp =================================================================== --- ELF/SymbolTable.cpp +++ ELF/SymbolTable.cpp @@ -210,7 +210,15 @@ // Find an existing symbol or create and insert a new one. template -std::pair SymbolTable::insert(StringRef Name) { +std::pair SymbolTable::insert(StringRef OrigName) { + // @@ means the symbol is the default version. In that + // case symbol must exist and @@ will be used to + // resolve references to . + StringRef Name = OrigName; + size_t Pos = Name.find("@@"); + if (Pos != StringRef::npos) + Name = Name.take_front(Pos); + auto P = Symtab.insert( {CachedHashStringRef(Name), SymIndex((int)SymVector.size(), false)}); SymIndex &V = P.first->second; @@ -234,6 +242,12 @@ SymVector.push_back(Sym); } else { Sym = SymVector[V.Idx]; + + // This is for the case where an input file has both foo and + // foo@ver. This is a really odd case, but has been observed in + // the wild and the expected behavior is to give precedence to + // keeping the version info. + Sym->body()->Name = OrigName; } return {Sym, IsNew}; } @@ -717,32 +731,9 @@ B->symbol()->VersionId = VersionId; } -static bool isDefaultVersion(SymbolBody *B) { - return B->isInCurrentDSO() && B->getName().find("@@") != StringRef::npos; -} - // This function processes version scripts by updating VersionId // member of symbols. template void SymbolTable::scanVersionScript() { - // Symbol themselves might know their versions because symbols - // can contain versions in the form of @. - // Let them parse and update their names to exclude version suffix. - for (Symbol *Sym : SymVector) { - SymbolBody *Body = Sym->body(); - bool IsDefault = isDefaultVersion(Body); - Body->parseSymbolVersion(); - - if (!IsDefault) - continue; - - // @@ means the symbol is the default version. If that's the - // case, the symbol is not used only to resolve of version - // but also undefined unversioned symbols with name . - SymbolBody *S = find(Body->getName()); - if (S && S->isUndefined()) - S->copy(Body); - } - // Handle edge cases first. handleAnonymousVersion(); Index: ELF/Symbols.h =================================================================== --- ELF/Symbols.h +++ ELF/Symbols.h @@ -145,7 +145,6 @@ bool isObject() const { return Type == llvm::ELF::STT_OBJECT; } bool isFile() const { return Type == llvm::ELF::STT_FILE; } -protected: StringRefZ Name; }; Index: test/ELF/Inputs/symver-archive1.s =================================================================== --- /dev/null +++ test/ELF/Inputs/symver-archive1.s @@ -0,0 +1,6 @@ +.text +.globl x +.type x, @function +x: + +.symver x, xx@@VER Index: test/ELF/Inputs/symver-archive2.s =================================================================== --- /dev/null +++ test/ELF/Inputs/symver-archive2.s @@ -0,0 +1 @@ +call xx@PLT Index: test/ELF/symver-archive.s =================================================================== --- /dev/null +++ test/ELF/symver-archive.s @@ -0,0 +1,15 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t1 +# RUN: rm -f %t.a +# RUN: llvm-ar rcs %t.a %t1 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/symver-archive1.s -o %t2.o +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/symver-archive2.s -o %t3.o +# RUN: ld.lld -o %t.out %t2.o %t3.o %t.a + +.text +.globl x +.type x, @function +x: + +.globl xx +xx = x