From: Rui Ueyama Date: Wed, 31 Aug 2016 20:03:54 +0000 (+0000) Subject: Linker script: support VERSION command. X-Git-Tag: llvmorg-4.0.0-rc1~10954 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=95769b4a2907457c19d5f72c2f557ff099d1ffa3;p=platform%2Fupstream%2Fllvm.git Linker script: support VERSION command. Summary: VERSION commands define symbol versions. The grammar of the commnad is as follows VERSION { version-script-commands } where version-script-commands is [ name ] { version-definitions }. Note that we already support version-script-commands because it is being used for version script command. This patch is based on George's patch https://reviews.llvm.org/D23609 Reviewers: grimar Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D24089 llvm-svn: 280284 --- diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp index 9403233..b3a1c45 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 *Globals); - void readVersion(StringRef VerStr); + void readVersionDeclaration(StringRef VerStr); void readGlobal(StringRef VerStr); void readLocal(); @@ -698,29 +700,39 @@ const StringMap 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 9463de0..4f7f7b0 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 ba9c95a..fc6e6df 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; \