summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--lld/ELF/Config.h1
-rw-r--r--lld/ELF/LinkerScript.cpp19
-rw-r--r--lld/ELF/ScriptParser.cpp7
-rw-r--r--lld/ELF/Strings.cpp6
-rw-r--r--lld/ELF/Strings.h1
-rw-r--r--lld/ELF/SymbolListFile.cpp3
-rw-r--r--lld/ELF/SymbolTable.cpp5
-rw-r--r--lld/test/ELF/invalid-dynamic-list.test2
-rw-r--r--lld/test/ELF/version-script-extern-exact.s22
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
OpenPOWER on IntegriCloud