Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -626,7 +626,7 @@ ScriptParser(StringRef S, bool B) : ScriptParserBase(S), IsUnderSysroot(B) {} void readLinkerScript(); - void readVersionScript(); + void readVersionScript(bool IsCommand); private: void addFile(StringRef Path); @@ -643,6 +643,7 @@ void readPhdrs(); void readSearchDir(); void readSections(); + void readVersion(); SymbolAssignment *readAssignment(StringRef Name); OutputSectionCommand *readOutputSectionDescription(StringRef OutSec); @@ -666,7 +667,7 @@ // For parsing version script. void readExtern(std::vector *Globals); - void readVersion(StringRef VerStr); + void readVersionDeclaration(StringRef VerStr); void readGlobal(StringRef VerStr); void readLocal(); @@ -688,29 +689,41 @@ {"PHDRS", &ScriptParser::readPhdrs}, {"SEARCH_DIR", &ScriptParser::readSearchDir}, {"SECTIONS", &ScriptParser::readSections}, + {"VERSION", &ScriptParser::readVersion}, {";", &ScriptParser::readNothing}}; -void ScriptParser::readVersionScript() { +void ScriptParser::readVersionScript(bool IsCommand) { StringRef Msg = "anonymous version definition is used in " "combination with other version definitions"; if (skip("{")) { - readVersion(""); + readVersionDeclaration(""); if (!atEOF()) setError(Msg); return; } while (!atEOF() && !Error) { + // If this script is inside VERSION command of linkerscript, + // we should just exit here and let linker script parser continu + if (IsCommand && peek() == "}") + return; + StringRef VerStr = next(); if (VerStr == "{") { setError(Msg); return; } expect("{"); - readVersion(VerStr); + readVersionDeclaration(VerStr); } } +void ScriptParser::readVersion() { + expect("{"); + readVersionScript(true); + expect("}"); +} + void ScriptParser::readLinkerScript() { while (!atEOF()) { StringRef Tok = next(); @@ -1363,7 +1376,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; @@ -1440,7 +1453,7 @@ } void elf::readVersionScript(MemoryBufferRef MB) { - ScriptParser(MB.getBuffer(), false).readVersionScript(); + ScriptParser(MB.getBuffer(), false).readVersionScript(false); } template class elf::LinkerScript; 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: