Index: ELF/SymbolTable.cpp =================================================================== --- ELF/SymbolTable.cpp +++ ELF/SymbolTable.cpp @@ -613,6 +613,26 @@ return false; } +static SymbolBody *findDemangled(const std::map &D, + StringRef Name) { + auto I = D.find(Name); + if (I != D.end()) + return I->second; + return nullptr; +} + +static std::vector +findAllDemangled(const std::map &D, + StringRef Pattern) { + std::vector Res; + for (auto &P : D) { + SymbolBody *Body = P.second; + if (!Body->isUndefined() && globMatch(Pattern, P.first)) + Res.push_back(Body); + } + return Res; +} + // 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. @@ -647,8 +667,9 @@ for (SymbolVersion Sym : V.Globals) { if (hasWildcard(Sym.Name)) continue; - SymbolBody *B = Sym.IsExternCpp ? Demangled[Sym.Name] : find(Sym.Name); - setVersionId(B, V.Name, Sym.Name, V.Id); + StringRef N = Sym.Name; + SymbolBody *B = Sym.IsExternCpp ? findDemangled(Demangled, N) : find(N); + setVersionId(B, V.Name, N, V.Id); } } @@ -656,10 +677,15 @@ for (size_t I = Config->VersionDefinitions.size() - 1; I != (size_t)-1; --I) { VersionDefinition &V = Config->VersionDefinitions[I]; for (SymbolVersion &Sym : V.Globals) - if (hasWildcard(Sym.Name)) - for (SymbolBody *B : findAll(Sym.Name)) + if (hasWildcard(Sym.Name)) { + std::vector All = + Sym.IsExternCpp ? findAllDemangled(Demangled, Sym.Name) + : findAll(Sym.Name); + + for (SymbolBody *B : All) if (B->symbol()->VersionId == Config->DefaultSymbolVersion) B->symbol()->VersionId = V.Id; + } } } Index: test/ELF/version-script-extern-wildcards.s =================================================================== --- test/ELF/version-script-extern-wildcards.s +++ test/ELF/version-script-extern-wildcards.s @@ -0,0 +1,40 @@ +# REQUIRES: shell + +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +# RUN: echo "LIBSAMPLE_1.0 { \ +# RUN: global: \ +# RUN: extern "C++" { \ +# RUN: foo*; \ +# RUN: }; \ +# RUN: }; \ +# RUN: LIBSAMPLE_2.0 { \ +# RUN: global: \ +# RUN: extern "C++" { \ +# RUN: zed*; \ +# RUN: bar; \ +# RUN: }; \ +# RUN: }; " > %t.script +# RUN: ld.lld --version-script %t.script -shared %t.o -o %t.so +# RUN: llvm-readobj -V -dyn-symbols %t.so | FileCheck %s + +# CHECK: Version symbols { +# CHECK: Symbols [ +# CHECK: Name: _Z3bari@ +# CHECK: Name: _Z3fooi@@LIBSAMPLE_1.0 +# CHECK: Name: _Z3zedi@@LIBSAMPLE_2.0 + +.text +.globl _Z3fooi +.type _Z3fooi,@function +_Z3fooi: +retq + +.globl _Z3bari +.type _Z3bari,@function +_Z3bari: +retq + +.globl _Z3zedi +.type _Z3zedi,@function +_Z3zedi: +retq