diff options
-rw-r--r-- | lld/ELF/LinkerScript.cpp | 32 | ||||
-rw-r--r-- | lld/test/ELF/verdef.s | 8 | ||||
-rw-r--r-- | lld/test/ELF/version-script.s | 7 |
3 files changed, 34 insertions, 13 deletions
diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index 94032330185..b3a1c45ea2c 100644 --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -653,6 +653,8 @@ private: void readPhdrs(); void readSearchDir(); void readSections(); + void readVersion(); + void readVersionScriptCommand(); SymbolAssignment *readAssignment(StringRef Name); OutputSectionCommand *readOutputSectionDescription(StringRef OutSec); @@ -676,7 +678,7 @@ private: // For parsing version script. void readExtern(std::vector<SymbolVersion> *Globals); - void readVersion(StringRef VerStr); + void readVersionDeclaration(StringRef VerStr); void readGlobal(StringRef VerStr); void readLocal(); @@ -698,29 +700,39 @@ const StringMap<elf::ScriptParser::Handler> elf::ScriptParser::Cmd = { {"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(); @@ -1377,7 +1389,7 @@ unsigned ScriptParser::readPhdrType() { 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; diff --git a/lld/test/ELF/verdef.s b/lld/test/ELF/verdef.s index 9463de0c0a0..4f7f7b0c302 100644 --- a/lld/test/ELF/verdef.s +++ b/lld/test/ELF/verdef.s @@ -101,6 +101,14 @@ # 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: diff --git a/lld/test/ELF/version-script.s b/lld/test/ELF/version-script.s index ba9c95a96fc..fc6e6df2c93 100644 --- a/lld/test/ELF/version-script.s +++ b/lld/test/ELF/version-script.s @@ -35,8 +35,8 @@ # 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; \ @@ -45,7 +45,8 @@ # 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; \ |