From b5e77c47fb8c047959e97e841f2d3210da005ce0 Mon Sep 17 00:00:00 2001 From: George Rimar Date: Fri, 9 Sep 2016 13:58:07 +0000 Subject: [PATCH] Recommit [ELF] - Versionscript: do not treat non-wildcarded names as wildcards. Fixed code that was not checked by testcases that are disabled on windows. Inital commit message: "[ELF] - Versionscript: do not treat non-wildcarded names as wildcards." Previously we incorrectly handled cases when symbol name in extern c++ tag was enclosed in quotes. Next case was treated as wildcard: GLIBCXX_3.4 { extern "C++" { "aaa*" } But it should have not. Quotes around aaa here means that we should have do exact name matching. That is PR30268 which has name with pointer is interpreted as wildcard by lld: extern "C++" { "operator delete[](void*)"; Patch fixes the issue. Differential revision: https://reviews.llvm.org/D24229 llvm-svn: 281045 --- lld/ELF/Config.h | 1 + lld/ELF/LinkerScript.cpp | 23 +++++++++++++++-------- lld/ELF/ScriptParser.cpp | 7 +++++-- lld/ELF/SymbolTable.cpp | 5 ++--- lld/test/ELF/version-script-extern-exact.s | 22 ++++++++++++++++++++++ 5 files changed, 45 insertions(+), 13 deletions(-) create mode 100644 lld/test/ELF/version-script-extern-exact.s diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index 4d7cf3e2..98246c3 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -45,6 +45,7 @@ enum class UnresolvedPolicy { NoUndef, ReportError, Warn, Ignore }; struct SymbolVersion { llvm::StringRef Name; bool IsExternCpp; + bool HasWildcards; }; // This struct contains symbols version definition that diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index 9d6935f..364435f 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -780,12 +780,18 @@ void ScriptParser::addFile(StringRef S) { } } +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,13 +817,13 @@ void ScriptParser::readGroup() { if (Tok == "AS_NEEDED") readAsNeeded(); else - addFile(Tok); + addFile(unquote(Tok)); } } void ScriptParser::readInclude() { StringRef Tok = next(); - auto MBOrErr = MemoryBuffer::getFile(Tok); + auto MBOrErr = MemoryBuffer::getFile(unquote(Tok)); if (!MBOrErr) { setError("cannot open " + Tok); return; @@ -833,7 +839,7 @@ void ScriptParser::readOutput() { expect("("); StringRef Tok = next(); if (Config->OutputFile.empty()) - Config->OutputFile = Tok; + Config->OutputFile = unquote(Tok); expect(")"); } @@ -1004,7 +1010,7 @@ Expr ScriptParser::readAssert() { 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::readLocal() { } 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 @@ void ScriptParser::readGlobal(StringRef VerStr) { if (Cur == "}" || Cur == "local:" || Error) return; next(); - Globals->push_back({Cur, false}); + Globals->push_back({unquote(Cur), false, hasWildcard(Cur)}); expect(";"); } } diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp index 19e20b6..97d68d9 100644 --- a/lld/ELF/ScriptParser.cpp +++ b/lld/ELF/ScriptParser.cpp @@ -60,14 +60,17 @@ std::vector ScriptParserBase::tokenize(StringRef S) { 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; } diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp index d80e512..f758247 100644 --- a/lld/ELF/SymbolTable.cpp +++ b/lld/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 @@ template void SymbolTable::scanVersionScript() { // 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 @@ template void SymbolTable::scanVersionScript() { 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 = diff --git a/lld/test/ELF/version-script-extern-exact.s b/lld/test/ELF/version-script-extern-exact.s new file mode 100644 index 0000000..b33ea35 --- /dev/null +++ b/lld/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 -- 2.7.4