Index: ELF/Config.h =================================================================== --- ELF/Config.h +++ ELF/Config.h @@ -86,6 +86,7 @@ bool Mips64EL = false; bool NoGnuUnique; bool NoUndefined; + bool NoUndefinedVersion; bool NoinhibitExec; bool Pic; bool Pie; Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -331,6 +331,7 @@ Config->ICF = Args.hasArg(OPT_icf); Config->NoGnuUnique = Args.hasArg(OPT_no_gnu_unique); Config->NoUndefined = Args.hasArg(OPT_no_undefined); + Config->NoUndefinedVersion = Args.hasArg(OPT_no_undefined_version); Config->NoinhibitExec = Args.hasArg(OPT_noinhibit_exec); Config->Pie = Args.hasArg(OPT_pie); Config->PrintGcSections = Args.hasArg(OPT_print_gc_sections); Index: ELF/Options.td =================================================================== --- ELF/Options.td +++ ELF/Options.td @@ -108,6 +108,9 @@ def no_undefined: F<"no-undefined">, HelpText<"Report unresolved symbols even if the linker is creating a shared library">; +def no_undefined_version: F<"no-undefined-version">, + HelpText<"Report version scripts that refer undefined symbols">; + def o: JoinedOrSeparate<["-"], "o">, MetaVarName<"">, HelpText<"Path to file to write output">; @@ -234,7 +237,6 @@ def no_dynamic_linker: F<"no-dynamic-linker">; def no_fatal_warnings: F<"no-fatal-warnings">; def no_mmap_output_file: F<"no-mmap-output-file">; -def no_undefined_version: F<"no-undefined-version">; def no_warn_common: F<"no-warn-common">; def no_warn_mismatch: F<"no-warn-mismatch">; def rpath_link: S<"rpath-link">; Index: ELF/SymbolTable.cpp =================================================================== --- ELF/SymbolTable.cpp +++ ELF/SymbolTable.cpp @@ -530,13 +530,19 @@ // assign version references for each symbol. size_t I = 2; for (Version &V : Config->SymbolVersions) { - for (StringRef Name : V.Globals) - if (SymbolBody *B = find(Name)) { - if (B->symbol()->VersionId != VER_NDX_GLOBAL && - B->symbol()->VersionId != VER_NDX_LOCAL) - error("duplicate symbol " + Name + " in version script"); - B->symbol()->VersionId = I; + for (StringRef Name : V.Globals) { + SymbolBody *B = find(Name); + if (!B || B->isUndefined()) { + if (Config->NoUndefinedVersion) + error("version script lists not defined symbol: " + Name); + continue; } + + if (B->symbol()->VersionId != VER_NDX_GLOBAL && + B->symbol()->VersionId != VER_NDX_LOCAL) + error("duplicate symbol " + Name + " in version script"); + B->symbol()->VersionId = I; + } ++I; } } Index: test/ELF/version-script-noundef.s =================================================================== --- test/ELF/version-script-noundef.s +++ test/ELF/version-script-noundef.s @@ -0,0 +1,22 @@ +# REQUIRES: x86 + +# RUN: echo "VERSION_1.0{ \ +# RUN: global: bar; \ +# RUN: };" > %t.script +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o +# RUN: not ld.lld --version-script %t.script -shared --no-undefined-version \ +# RUN: %t.o -o %t.so 2>&1 | FileCheck -check-prefix=ERR1 %s +# ERR1: version script lists not defined symbol: bar + +# RUN: echo "VERSION_1.0{ \ +# RUN: global: und; \ +# RUN: };" > %t2.script +# RUN: not ld.lld --version-script %t2.script -shared --no-undefined-version \ +# RUN: %t.o -o %t.so 2>&1 | FileCheck -check-prefix=ERR2 %s +# ERR2: version script lists not defined symbol: und + +.text +.globl foo +.type foo,@function +foo: +callq und@PLT