[lld] r297402 - Handle ":" as a regular token character in linker scripts.
Rui Ueyama via llvm-commits
llvm-commits at lists.llvm.org
Thu Mar 9 11:23:00 PST 2017
Author: ruiu
Date: Thu Mar 9 13:23:00 2017
New Revision: 297402
URL: http://llvm.org/viewvc/llvm-project?rev=297402&view=rev
Log:
Handle ":" as a regular token character in linker scripts.
This is an alternative to https://reviews.llvm.org/D30500 to simplify the
version definition parser and allow ":" in symbol names.
Differential Revision: https://reviews.llvm.org/D30722
Modified:
lld/trunk/ELF/Config.h
lld/trunk/ELF/LinkerScript.cpp
lld/trunk/ELF/ScriptLexer.cpp
lld/trunk/ELF/ScriptLexer.h
lld/trunk/test/ELF/version-script-extern-wildcards-anon.s
Modified: lld/trunk/ELF/Config.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Config.h?rev=297402&r1=297401&r2=297402&view=diff
==============================================================================
--- lld/trunk/ELF/Config.h (original)
+++ lld/trunk/ELF/Config.h Thu Mar 9 13:23:00 2017
@@ -59,11 +59,10 @@ struct SymbolVersion {
// This struct contains symbols version definition that
// can be found in version script if it is used for link.
struct VersionDefinition {
- VersionDefinition(llvm::StringRef Name, uint16_t Id) : Name(Name), Id(Id) {}
llvm::StringRef Name;
- uint16_t Id;
+ uint16_t Id = 0;
std::vector<SymbolVersion> Globals;
- size_t NameOff; // Offset in string table.
+ size_t NameOff = 0; // Offset in the string table
};
// This struct contains the global configuration for the linker.
Modified: lld/trunk/ELF/LinkerScript.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/LinkerScript.cpp?rev=297402&r1=297401&r2=297402&view=diff
==============================================================================
--- lld/trunk/ELF/LinkerScript.cpp (original)
+++ lld/trunk/ELF/LinkerScript.cpp Thu Mar 9 13:23:00 2017
@@ -1055,8 +1055,9 @@ private:
std::vector<SymbolVersion> readVersionExtern();
void readAnonymousDeclaration();
void readVersionDeclaration(StringRef VerStr);
- std::vector<SymbolVersion> readSymbols();
- void readLocals();
+
+ std::pair<std::vector<SymbolVersion>, std::vector<SymbolVersion>>
+ readSymbols();
ScriptConfiguration &Opt = *ScriptConfig;
bool IsUnderSysroot;
@@ -1918,50 +1919,49 @@ unsigned ScriptParser::readPhdrType() {
return Ret;
}
-// Reads a list of symbols, e.g. "{ global: foo; bar; local: *; };".
+// Reads an anonymous version declaration.
void ScriptParser::readAnonymousDeclaration() {
- // Read global symbols first. "global:" is default, so if there's
- // no label, we assume global symbols.
- if (peek() != "local") {
- if (consume("global"))
- expect(":");
- for (SymbolVersion V : readSymbols())
- Config->VersionScriptGlobals.push_back(V);
- }
- readLocals();
- expect("}");
- expect(";");
-}
+ std::vector<SymbolVersion> Locals;
+ std::vector<SymbolVersion> Globals;
+ std::tie(Locals, Globals) = readSymbols();
-void ScriptParser::readLocals() {
- if (!consume("local"))
- return;
- expect(":");
- std::vector<SymbolVersion> Locals = readSymbols();
for (SymbolVersion V : Locals) {
- if (V.Name == "*") {
+ if (V.Name == "*")
Config->DefaultSymbolVersion = VER_NDX_LOCAL;
- continue;
- }
- Config->VersionScriptLocals.push_back(V);
+ else
+ Config->VersionScriptLocals.push_back(V);
}
+
+ for (SymbolVersion V : Globals)
+ Config->VersionScriptGlobals.push_back(V);
+
+ expect(";");
}
-// Reads a list of symbols, e.g. "VerStr { global: foo; bar; local: *; };".
+// Reads a non-anonymous version definition,
+// e.g. "VerStr { global: foo; bar; local: *; };".
void ScriptParser::readVersionDeclaration(StringRef VerStr) {
- // Identifiers start at 2 because 0 and 1 are reserved
- // for VER_NDX_LOCAL and VER_NDX_GLOBAL constants.
- uint16_t VersionId = Config->VersionDefinitions.size() + 2;
- Config->VersionDefinitions.push_back({VerStr, VersionId});
-
- // Read global symbols.
- if (peek() != "local") {
- if (consume("global"))
- expect(":");
- Config->VersionDefinitions.back().Globals = readSymbols();
+ // Read a symbol list.
+ std::vector<SymbolVersion> Locals;
+ std::vector<SymbolVersion> Globals;
+ std::tie(Locals, Globals) = readSymbols();
+
+ for (SymbolVersion V : Locals) {
+ if (V.Name == "*")
+ Config->DefaultSymbolVersion = VER_NDX_LOCAL;
+ else
+ Config->VersionScriptLocals.push_back(V);
}
- readLocals();
- expect("}");
+
+ // Create a new version definition and add that to the global symbols.
+ VersionDefinition Ver;
+ Ver.Name = VerStr;
+ Ver.Globals = Globals;
+
+ // User-defined version number starts from 2 because 0 and 1 are
+ // reserved for VER_NDX_LOCAL and VER_NDX_GLOBAL, respectively.
+ Ver.Id = Config->VersionDefinitions.size() + 2;
+ Config->VersionDefinitions.push_back(Ver);
// Each version may have a parent version. For example, "Ver2"
// defined as "Ver2 { global: foo; local: *; } Ver1;" has "Ver1"
@@ -1973,23 +1973,35 @@ void ScriptParser::readVersionDeclaratio
expect(";");
}
-// Reads a list of symbols for a versions cript.
-std::vector<SymbolVersion> ScriptParser::readSymbols() {
- std::vector<SymbolVersion> Ret;
- for (;;) {
- if (consume("extern")) {
- for (SymbolVersion V : readVersionExtern())
- Ret.push_back(V);
+// Reads a list of symbols, e.g. "{ global: foo; bar; local: *; };".
+std::pair<std::vector<SymbolVersion>, std::vector<SymbolVersion>>
+ScriptParser::readSymbols() {
+ std::vector<SymbolVersion> Locals;
+ std::vector<SymbolVersion> Globals;
+ std::vector<SymbolVersion> *V = &Globals;
+
+ while (!Error) {
+ if (consume("}"))
+ break;
+ if (consumeLabel("local")) {
+ V = &Locals;
+ continue;
+ }
+ if (consumeLabel("global")) {
+ V = &Globals;
continue;
}
- if (peek() == "}" || (peek() == "local" && peek(1) == ":") || Error)
- break;
- StringRef Tok = next();
- Ret.push_back({unquote(Tok), false, hasWildcard(Tok)});
+ if (consume("extern")) {
+ std::vector<SymbolVersion> Ext = readVersionExtern();
+ V->insert(V->end(), Ext.begin(), Ext.end());
+ } else {
+ StringRef Tok = next();
+ V->push_back({unquote(Tok), false, hasWildcard(Tok)});
+ }
expect(";");
}
- return Ret;
+ return {Locals, Globals};
}
// Reads an "extern C++" directive, e.g.,
@@ -2010,7 +2022,6 @@ std::vector<SymbolVersion> ScriptParser:
}
expect("}");
- expect(";");
return Ret;
}
Modified: lld/trunk/ELF/ScriptLexer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/ScriptLexer.cpp?rev=297402&r1=297401&r2=297402&view=diff
==============================================================================
--- lld/trunk/ELF/ScriptLexer.cpp (original)
+++ lld/trunk/ELF/ScriptLexer.cpp Thu Mar 9 13:23:00 2017
@@ -124,7 +124,7 @@ void ScriptLexer::tokenize(MemoryBufferR
// so that you can write "file-name.cpp" as one bare token, for example.
size_t Pos = S.find_first_not_of(
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
- "0123456789_.$/\\~=+[]*?-!<>^");
+ "0123456789_.$/\\~=+[]*?-!<>^:");
// A character that cannot start a word (which is usually a
// punctuation) forms a single character token.
@@ -169,7 +169,7 @@ bool ScriptLexer::atEOF() { return Error
// Split a given string as an expression.
// This function returns "3", "*" and "5" for "3*5" for example.
static std::vector<StringRef> tokenizeExpr(StringRef S) {
- StringRef Ops = "+-*/"; // List of operators
+ StringRef Ops = "+-*/:"; // List of operators
// Quoted strings are literal strings, so we don't want to split it.
if (S.startswith("\""))
@@ -229,14 +229,11 @@ StringRef ScriptLexer::next() {
return Tokens[Pos++];
}
-StringRef ScriptLexer::peek(unsigned N) {
- StringRef Tok;
- for (unsigned I = 0; I <= N; ++I) {
- Tok = next();
- if (Error)
- return "";
- }
- Pos = Pos - N - 1;
+StringRef ScriptLexer::peek() {
+ StringRef Tok = next();
+ if (Error)
+ return "";
+ Pos = Pos - 1;
return Tok;
}
@@ -246,6 +243,18 @@ bool ScriptLexer::consume(StringRef Tok)
return true;
}
return false;
+}
+
+// Consumes Tok followed by ":". Space is allowed between Tok and ":".
+bool ScriptLexer::consumeLabel(StringRef Tok) {
+ if (consume((Tok + ":").str()))
+ return true;
+ if (Tokens.size() >= Pos + 2 && Tokens[Pos] == Tok &&
+ Tokens[Pos + 1] == ":") {
+ Pos += 2;
+ return true;
+ }
+ return false;
}
void ScriptLexer::skip() { (void)next(); }
Modified: lld/trunk/ELF/ScriptLexer.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/ScriptLexer.h?rev=297402&r1=297401&r2=297402&view=diff
==============================================================================
--- lld/trunk/ELF/ScriptLexer.h (original)
+++ lld/trunk/ELF/ScriptLexer.h Thu Mar 9 13:23:00 2017
@@ -28,10 +28,11 @@ public:
static StringRef skipSpace(StringRef S);
bool atEOF();
StringRef next();
- StringRef peek(unsigned N = 0);
+ StringRef peek();
void skip();
bool consume(StringRef Tok);
void expect(StringRef Expect);
+ bool consumeLabel(StringRef Tok);
std::string getCurrentLocation();
std::vector<MemoryBufferRef> MBs;
Modified: lld/trunk/test/ELF/version-script-extern-wildcards-anon.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/version-script-extern-wildcards-anon.s?rev=297402&r1=297401&r2=297402&view=diff
==============================================================================
--- lld/trunk/test/ELF/version-script-extern-wildcards-anon.s (original)
+++ lld/trunk/test/ELF/version-script-extern-wildcards-anon.s Thu Mar 9 13:23:00 2017
@@ -7,6 +7,7 @@
# RUN: extern "C++" { \
# RUN: "foo(int)"; \
# RUN: z*; \
+# RUN: std::q*; \
# RUN: }; \
# RUN: local: *; \
# RUN: }; ' > %t.script
@@ -50,6 +51,15 @@
# CHECK-NEXT: Other:
# CHECK-NEXT: Section:
# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: _ZSt3qux
+# CHECK-NEXT: Value:
+# CHECK-NEXT: Size:
+# CHECK-NEXT: Binding: Global
+# CHECK-NEXT: Type:
+# CHECK-NEXT: Other:
+# CHECK-NEXT: Section:
+# CHECK-NEXT: }
# CHECK-NEXT: ]
.global _Z3fooi
@@ -60,3 +70,5 @@ _Z3bari:
_Z3zedi:
.global _Z3bazi
_Z3bazi:
+.global _ZSt3qux
+_ZSt3qux:
More information about the llvm-commits
mailing list