Index: ELF/SymbolTable.h =================================================================== --- ELF/SymbolTable.h +++ ELF/SymbolTable.h @@ -85,6 +85,7 @@ void traceDefined(); SymbolBody *find(StringRef Name); + std::vector findAll(StringRef Prefix); void wrap(StringRef Name); private: Index: ELF/SymbolTable.cpp =================================================================== --- ELF/SymbolTable.cpp +++ ELF/SymbolTable.cpp @@ -432,6 +432,21 @@ } template +std::vector SymbolTable::findAll(StringRef Prefix) { + std::vector Result; + if (!Prefix.endswith("*")) { + SymbolBody *B = find(Prefix); + if (B != nullptr) + Result.push_back(B); + return Result; + } + for (auto &It : Symtab) + if (It.first.Val.startswith(Prefix.rtrim("*"))) + Result.push_back(SymVector[It.second]->body()); + return Result; +} + +template void SymbolTable::addLazyArchive( ArchiveFile *F, const llvm::object::Archive::Symbol Sym) { Symbol *S; @@ -531,7 +546,7 @@ size_t I = 2; for (Version &V : Config->SymbolVersions) { for (StringRef Name : V.Globals) - if (SymbolBody *B = find(Name)) { + for (SymbolBody *B : findAll(Name)) { if (B->symbol()->VersionId != VER_NDX_GLOBAL && B->symbol()->VersionId != VER_NDX_LOCAL) error("duplicate symbol " + Name + " in version script"); Index: test/ELF/partial-version.s =================================================================== --- /dev/null +++ test/ELF/partial-version.s @@ -0,0 +1,65 @@ +# REQUIRES: x86 + +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o +# RUN: echo "VERSION_1.0{ \ +# RUN: global: foo*; \ +# RUN: local: *; };" > %t.script +# RUN: ld.lld --version-script %t.script -shared %t.o -o %t.so +# RUN: llvm-readobj -dyn-symbols %t.so | FileCheck %s + +# CHECK: DynamicSymbols [ +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: @ +# CHECK-NEXT: Value: 0x0 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Local +# CHECK-NEXT: Type: None +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Undefined +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: foo1@@VERSION_1.0 +# CHECK-NEXT: Value: 0x1000 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Global +# CHECK-NEXT: Type: None +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: .text +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: foo2@@VERSION_1.0 +# CHECK-NEXT: Value: 0x1001 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Global +# CHECK-NEXT: Type: None +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: .text +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: foo3@@VERSION_1.0 +# CHECK-NEXT: Value: 0x1007 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Global +# CHECK-NEXT: Type: None +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: .text +# CHECK-NEXT: } +# CHECK-NEXT: ] + +.globl foo1 +foo1: + ret + +.globl foo2 +foo2: + call foo1@PLT + ret + +.globl foo3 +foo3: + call foo2@PLT + ret + +.globl _start +_start: + ret