Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -653,6 +653,7 @@ void readPhdrs(); void readSearchDir(); void readSections(); + void readVersion(); SymbolAssignment *readAssignment(StringRef Name); OutputSectionCommand *readOutputSectionDescription(StringRef OutSec); @@ -676,7 +677,7 @@ // For parsing version script. void readExtern(std::vector *Globals); - void readVersion(StringRef VerStr); + void readVersionDeclaration(StringRef VerStr); void readGlobal(StringRef VerStr); void readLocal(); @@ -698,13 +699,14 @@ {"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"; if (skip("{")) { - readVersion(""); + readVersionDeclaration(""); if (!atEOF()) setError(Msg); return; @@ -717,10 +719,34 @@ return; } expect("{"); - readVersion(VerStr); + readVersionDeclaration(VerStr); } } +void ScriptParser::readVersion() { + StringRef Msg = "anonymous version definition is used in " + "combination with other version definitions"; + expect("{"); + if (skip("{")) { + readVersionDeclaration(""); + expect("}"); + return; + } + + while (!Error) { + if (peek() == "}") + break; + StringRef VerStr = next(); + if (VerStr == "{") { + setError(Msg); + break; + } + expect("{"); + readVersionDeclaration(VerStr); + } + expect("}"); +} + void ScriptParser::readLinkerScript() { while (!atEOF()) { StringRef Tok = next(); @@ -1377,7 +1403,7 @@ 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; Index: test/ELF/verdef.s =================================================================== --- test/ELF/verdef.s +++ test/ELF/verdef.s @@ -101,6 +101,19 @@ # MAIN-NEXT: SHT_GNU_verdef { # MAIN-NEXT: } +# RUN: echo "VERSION { \ +# RUN: LIBSAMPLE_1.0{ \ +# RUN: global: a; \ +# RUN: local: *; }; \ +# RUN: LIBSAMPLE_2.0{ \ +# RUN: global: b; \ +# RUN: local: *; }; \ +# RUN: LIBSAMPLE_3.0{ \ +# RUN: global: c; \ +# RUN: local: *; }; }" > %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: Index: test/ELF/version-script.s =================================================================== --- test/ELF/version-script.s +++ test/ELF/version-script.s @@ -8,6 +8,10 @@ # RUN: ld.lld --version-script %t.script -shared %t.o %t2.so -o %t.so # RUN: llvm-readobj -dyn-symbols %t.so | FileCheck --check-prefix=DSO %s +# RUN: echo "VERSION { { global: foo1; foo3; local: *; }; }" > %t2.script +# RUN: ld.lld --script %t2.script -shared %t.o %t2.so -o %t2_1.so +# RUN: llvm-readobj -dyn-symbols %t2_1.so | FileCheck --check-prefix=DSO %s + # RUN: echo "# comment" > %t3.script # RUN: echo "{ local: *; # comment" >> %t3.script # RUN: echo -n "}; # comment" >> %t3.script