void readPhdrs();
void readSearchDir();
void readSections();
+ void readVersion();
+ void readVersionScriptCommand();
SymbolAssignment *readAssignment(StringRef Name);
OutputSectionCommand *readOutputSectionDescription(StringRef OutSec);
// For parsing version script.
void readExtern(std::vector<SymbolVersion> *Globals);
- void readVersion(StringRef VerStr);
+ void readVersionDeclaration(StringRef VerStr);
void readGlobal(StringRef VerStr);
void readLocal();
{"PHDRS", &ScriptParser::readPhdrs},
{"SEARCH_DIR", &ScriptParser::readSearchDir},
{"SECTIONS", &ScriptParser::readSections},
+ {"VERSION", &ScriptParser::readVersion},
{";", &ScriptParser::readNothing}};
void ScriptParser::readVersionScript() {
- StringRef Msg = "anonymous version definition is used in "
- "combination with other version definitions";
+ readVersionScriptCommand();
+ if (!atEOF())
+ setError("EOF expected, but got " + next());
+}
+
+void ScriptParser::readVersionScriptCommand() {
if (skip("{")) {
- readVersion("");
- if (!atEOF())
- setError(Msg);
+ readVersionDeclaration("");
return;
}
- while (!atEOF() && !Error) {
+ while (!atEOF() && !Error && peek() != "}") {
StringRef VerStr = next();
if (VerStr == "{") {
- setError(Msg);
+ setError("anonymous version definition is used in "
+ "combination with other version definitions");
return;
}
expect("{");
- readVersion(VerStr);
+ readVersionDeclaration(VerStr);
}
}
+void ScriptParser::readVersion() {
+ expect("{");
+ readVersionScriptCommand();
+ expect("}");
+}
+
void ScriptParser::readLinkerScript() {
while (!atEOF()) {
StringRef Tok = next();
return Ret;
}
-void ScriptParser::readVersion(StringRef VerStr) {
+void ScriptParser::readVersionDeclaration(StringRef VerStr) {
// Identifiers start at 2 because 0 and 1 are reserved
// for VER_NDX_LOCAL and VER_NDX_GLOBAL constants.
size_t VersionId = Config->VersionDefinitions.size() + 2;
# MAIN-NEXT: SHT_GNU_verdef {
# MAIN-NEXT: }
+# RUN: echo "VERSION { \
+# RUN: LIBSAMPLE_1.0 { global: a; local: *; }; \
+# RUN: LIBSAMPLE_2.0 { global: b; local: *; }; \
+# RUN: LIBSAMPLE_3.0 { global: c; local: *; }; \
+# RUN: }" > %t.script
+# RUN: ld.lld --script %t.script -shared -soname shared %t.o -o %t2.so
+# RUN: llvm-readobj -V -dyn-symbols %t2.so | FileCheck --check-prefix=DSO %s
+
.globl a
.type a,@function
a:
# RUN: global: foo3; \
# RUN: local: *; }; " > %t5.script
# RUN: not ld.lld --version-script %t5.script -shared %t.o %t2.so -o %t5.so 2>&1 | \
-# RUN: FileCheck -check-prefix=ERR %s
-# ERR: anonymous version definition is used in combination with other version definitions
+# RUN: FileCheck -check-prefix=ERR1 %s
+# ERR1: anonymous version definition is used in combination with other version definitions
# RUN: echo "{ \
# RUN: global: foo1; \
# RUN: global: foo3; \
# RUN: local: *; }; " > %t5.script
# RUN: not ld.lld --version-script %t5.script -shared %t.o %t2.so -o %t5.so 2>&1 | \
-# RUN: FileCheck -check-prefix=ERR %s
+# RUN: FileCheck -check-prefix=ERR2 %s
+# ERR2: EOF expected, but got VERSION_2.0
# RUN: echo "VERSION_1.0{ \
# RUN: global: foo1; \