diff options
| -rw-r--r-- | lld/ELF/Config.h | 1 | ||||
| -rw-r--r-- | lld/ELF/LinkerScript.cpp | 19 | ||||
| -rw-r--r-- | lld/ELF/ScriptParser.cpp | 7 | ||||
| -rw-r--r-- | lld/ELF/Strings.cpp | 6 | ||||
| -rw-r--r-- | lld/ELF/Strings.h | 1 | ||||
| -rw-r--r-- | lld/ELF/SymbolListFile.cpp | 3 | ||||
| -rw-r--r-- | lld/ELF/SymbolTable.cpp | 5 | ||||
| -rw-r--r-- | lld/test/ELF/invalid-dynamic-list.test | 2 | ||||
| -rw-r--r-- | lld/test/ELF/version-script-extern-exact.s | 22 |
9 files changed, 50 insertions, 16 deletions
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index 4d7cf3e273d..98246c31bef 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 9d6935f7742..ef8ccb9f315 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -785,7 +785,7 @@ void ScriptParser::readAsNeeded() { bool Orig = Config->AsNeeded; Config->AsNeeded = true; while (!Error && !skip(")")) - addFile(next()); + addFile(unquote(next())); Config->AsNeeded = Orig; } @@ -811,13 +811,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 +833,7 @@ void ScriptParser::readOutput() { expect("("); StringRef Tok = next(); if (Config->OutputFile.empty()) - Config->OutputFile = Tok; + Config->OutputFile = unquote(Tok); expect(")"); } @@ -896,7 +896,7 @@ void ScriptParser::readSearchDir() { expect("("); StringRef Tok = next(); if (!Config->Nostdlib) - Config->SearchPaths.push_back(Tok); + Config->SearchPaths.push_back(unquote(Tok)); expect(")"); } @@ -1004,7 +1004,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 +1421,14 @@ void ScriptParser::readLocal() { } void ScriptParser::readExtern(std::vector<SymbolVersion> *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 +1451,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 19e20b653bc..97d68d92318 100644 --- a/lld/ELF/ScriptParser.cpp +++ b/lld/ELF/ScriptParser.cpp @@ -60,14 +60,17 @@ std::vector<StringRef> 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/Strings.cpp b/lld/ELF/Strings.cpp index fec7bd4e1f2..cd19612acc6 100644 --- a/lld/ELF/Strings.cpp +++ b/lld/ELF/Strings.cpp @@ -24,6 +24,12 @@ bool elf::hasWildcard(StringRef S) { return S.find_first_of("?*[") != StringRef::npos; } +StringRef elf::unquote(StringRef S) { + if (!S.startswith("\"")) + return S; + return S.substr(1, S.size() - 2); +} + // Converts a glob pattern to a regular expression. static std::string toRegex(StringRef S) { std::string T; diff --git a/lld/ELF/Strings.h b/lld/ELF/Strings.h index ad99eb9bae9..e08423a0246 100644 --- a/lld/ELF/Strings.h +++ b/lld/ELF/Strings.h @@ -20,6 +20,7 @@ llvm::Regex compileGlobPatterns(ArrayRef<StringRef> V); bool hasWildcard(StringRef S); std::vector<uint8_t> parseHex(StringRef S); bool isValidCIdentifier(StringRef S); +StringRef unquote(StringRef S); // Returns a demangled C++ symbol name. If Name is not a mangled // name or the system does not provide __cxa_demangle function, diff --git a/lld/ELF/SymbolListFile.cpp b/lld/ELF/SymbolListFile.cpp index cd977c5e129..3fe83d470f2 100644 --- a/lld/ELF/SymbolListFile.cpp +++ b/lld/ELF/SymbolListFile.cpp @@ -16,6 +16,7 @@ #include "SymbolListFile.h" #include "Config.h" #include "ScriptParser.h" +#include "Strings.h" #include "llvm/Support/MemoryBuffer.h" using namespace llvm; @@ -43,7 +44,7 @@ void DynamicListParser::run() { while (!atEOF()) { expect("{"); while (!Error) { - Config->DynamicList.push_back(next()); + Config->DynamicList.push_back(unquote(next())); expect(";"); if (skip("}")) break; diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp index d80e512a4c0..f758247ac9c 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 <class ELFT> void SymbolTable<ELFT>::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 <class ELFT> void SymbolTable<ELFT>::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<SymbolBody *> Syms = diff --git a/lld/test/ELF/invalid-dynamic-list.test b/lld/test/ELF/invalid-dynamic-list.test index 0e7c820f563..11b7900a540 100644 --- a/lld/test/ELF/invalid-dynamic-list.test +++ b/lld/test/ELF/invalid-dynamic-list.test @@ -34,4 +34,4 @@ # RUN: echo "{ extern \"BOGUS\" { test }; };" > %t1 # RUN: not ld.lld --dynamic-list %t1 2>&1 | FileCheck -check-prefix=ERR6 %s -# ERR6: line 1: ; expected, but got BOGUS +# ERR6: line 1: ; expected, but got "BOGUS" 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 00000000000..b33ea35a49b --- /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 |

