Index: ELF/SymbolListFile.cpp =================================================================== --- ELF/SymbolListFile.cpp +++ ELF/SymbolListFile.cpp @@ -80,6 +80,7 @@ void parseVersion(StringRef Version); void parseLocal(); void parseVersionSymbols(StringRef Version); + void parseExtern(StringRef Version); }; void VersionScriptParser::parseVersion(StringRef Version) { @@ -104,6 +105,19 @@ Config->VersionScriptGlobalByDefault = false; } +void VersionScriptParser::parseExtern(StringRef Version) { + expect("extern"); + StringRef Lang = next(); + if (Lang != "C" && Lang != "C++") { + setError("unsupported language " + Lang + " in extern scope"); + return; + } + expect("{"); + parseVersionSymbols(Version); + expect("}"); + expect(";"); +} + void VersionScriptParser::parseVersionSymbols(StringRef Version) { std::vector *Globals; if (Version.empty()) { @@ -117,6 +131,10 @@ StringRef Cur = peek(); if (Cur == "}" || Cur == "local:" || Error) return; + if (Cur == "extern") { + parseExtern(Version); + continue; + } next(); Globals->push_back(Cur); expect(";"); Index: test/ELF/version-script-err.s =================================================================== --- test/ELF/version-script-err.s +++ test/ELF/version-script-err.s @@ -8,3 +8,8 @@ // RUN: not ld.lld --version-script %terr1.script -shared %t.o -o %t.so 2>&1 | \ // RUN: FileCheck -check-prefix=ERR1 %s // ERR1: unclosed quote + +// RUN: echo "VERSION { extern "C--" {}; }; " > %terr2.script +// RUN: not ld.lld --version-script %terr2.script -shared %t.o -o %t.so 2>&1 | \ +// RUN: FileCheck -check-prefix=ERR2 %s +// ERR2: unsupported language C-- in extern scope Index: test/ELF/version-script-extern.s =================================================================== --- test/ELF/version-script-extern.s +++ test/ELF/version-script-extern.s @@ -0,0 +1,34 @@ +# REQUIRES: x86 + +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o + +# RUN: echo "VERSION_1.0{ \ +# RUN: extern "C++" { \ +# RUN: foo; \ +# RUN: "bar"; \ +# RUN: }; \ +# RUN: }; " > %t1.script +# RUN: ld.lld --version-script %t1.script -shared %t.o -o %t.so +# RUN: llvm-readobj -dyn-symbols %t.so | FileCheck %s + +# CHECK: DynamicSymbols [ +# CHECK: Symbol { +# CHECK: Name: bar@@VERSION_1.0 +# CHECK: } +# CHECK: Symbol { +# CHECK: Name: foo@@VERSION_1.0 +# CHECK: } +# CHECK: Symbol { +# CHECK: Name: zed@ + +.global foo +.type foo, @function +foo: + +.global bar +.type bar, @function +bar: + +.global zed +.type zed, @function +zed: