Index: lld/trunk/ELF/Config.h =================================================================== --- lld/trunk/ELF/Config.h +++ lld/trunk/ELF/Config.h @@ -45,6 +45,7 @@ struct SymbolVersion { llvm::StringRef Name; bool IsExternCpp; + bool HasWildcards; }; // This struct contains symbols version definition that Index: lld/trunk/ELF/LinkerScript.cpp =================================================================== --- lld/trunk/ELF/LinkerScript.cpp +++ lld/trunk/ELF/LinkerScript.cpp @@ -780,12 +780,18 @@ } } +static StringRef unquote(StringRef S) { + if (!S.startswith("\"")) + return S; + return S.substr(1, S.size() - 2); +} + void ScriptParser::readAsNeeded() { expect("("); bool Orig = Config->AsNeeded; Config->AsNeeded = true; while (!Error && !skip(")")) - addFile(next()); + addFile(unquote(next())); Config->AsNeeded = Orig; } @@ -811,7 +817,7 @@ if (Tok == "AS_NEEDED") readAsNeeded(); else - addFile(Tok); + addFile(unquote(Tok)); } } @@ -1004,7 +1010,7 @@ expect("("); Expr E = readExpr(); expect(","); - StringRef Msg = next(); + StringRef Msg = unquote(next()); expect(")"); return [=](uint64_t Dot) { uint64_t V = E(Dot); @@ -1421,13 +1427,14 @@ } void ScriptParser::readExtern(std::vector *Globals) { - expect("C++"); + expect("\"C++\""); expect("{"); for (;;) { if (peek() == "}" || Error) break; - Globals->push_back({next(), true}); + bool HasWildcard = !peek().startswith("\"") && hasWildcard(peek()); + Globals->push_back({unquote(next()), true, HasWildcard}); expect(";"); } @@ -1450,7 +1457,7 @@ if (Cur == "}" || Cur == "local:" || Error) return; next(); - Globals->push_back({Cur, false}); + Globals->push_back({unquote(Cur), false, hasWildcard(Cur)}); expect(";"); } } Index: lld/trunk/ELF/ScriptParser.cpp =================================================================== --- lld/trunk/ELF/ScriptParser.cpp +++ lld/trunk/ELF/ScriptParser.cpp @@ -60,14 +60,17 @@ if (S.empty()) return Ret; - // Quoted token. + // Quoted token. Note that double-quote characters are parts of a token + // because, in a glob match context, only unquoted tokens are interpreted + // as glob patterns. Double-quoted tokens are literal patterns in that + // context. if (S.startswith("\"")) { size_t E = S.find("\"", 1); if (E == StringRef::npos) { error("unclosed quote"); return {}; } - Ret.push_back(S.substr(1, E - 1)); + Ret.push_back(S.take_front(E + 1)); S = S.substr(E + 1); continue; } Index: lld/trunk/ELF/SymbolTable.cpp =================================================================== --- lld/trunk/ELF/SymbolTable.cpp +++ lld/trunk/ELF/SymbolTable.cpp @@ -18,7 +18,6 @@ #include "Config.h" #include "Error.h" #include "LinkerScript.h" -#include "Strings.h" #include "SymbolListFile.h" #include "Symbols.h" #include "llvm/Bitcode/ReaderWriter.h" @@ -678,7 +677,7 @@ // i.e. version definitions not containing any glob meta-characters. for (VersionDefinition &V : Config->VersionDefinitions) { for (SymbolVersion Sym : V.Globals) { - if (hasWildcard(Sym.Name)) + if (Sym.HasWildcards) continue; StringRef N = Sym.Name; SymbolBody *B = Sym.IsExternCpp ? findDemangled(Demangled, N) : find(N); @@ -693,7 +692,7 @@ 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)) + if (!Sym.HasWildcards) continue; Regex Re = compileGlobPatterns({Sym.Name}); std::vector Syms = Index: lld/trunk/test/ELF/version-script-extern-exact.s =================================================================== --- lld/trunk/test/ELF/version-script-extern-exact.s +++ lld/trunk/test/ELF/version-script-extern-exact.s @@ -0,0 +1,22 @@ +# REQUIRES: x86 + +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +# RUN: echo "FOO { global: extern \"C++\" { \"aaa*\"; }; };" > %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: Symbol { +# CHECK: Name: _Z3aaaPf@ (1) +# CHECK: Symbol { +# CHECK: Name: _Z3aaaPi@ (10) + +.text +.globl _Z3aaaPi +.type _Z3aaaPi,@function +_Z3aaaPi: +retq + +.globl _Z3aaaPf +.type _Z3aaaPf,@function +_Z3aaaPf: +retq