Index: lld/ELF/Config.h =================================================================== --- lld/ELF/Config.h +++ lld/ELF/Config.h @@ -124,6 +124,7 @@ bool GcSections; bool GdbIndex; bool GnuHash = false; + bool GnuUnique; bool HasDynamicList = false; bool HasDynSymTab; bool ICF; @@ -131,8 +132,6 @@ bool IgnoreFunctionAddressEquality; bool MergeArmExidx; bool MipsN32Abi = false; - bool NoGnuUnique; - bool NoUndefinedVersion; bool NoinhibitExec; bool Nostdlib; bool OFormatBinary; @@ -149,6 +148,7 @@ bool SysvHash = false; bool Target1Rel; bool Trace; + bool UndefinedVersion; bool Verbose; bool WarnCommon; bool WarnMissingEntry; Index: lld/ELF/Driver.cpp =================================================================== --- lld/ELF/Driver.cpp +++ lld/ELF/Driver.cpp @@ -621,6 +621,7 @@ Config->Fini = Args.getLastArgValue(OPT_fini, "_fini"); Config->FixCortexA53Errata843419 = Args.hasArg(OPT_fix_cortex_a53_843419); Config->GcSections = Args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, false); + Config->GnuUnique = Args.hasFlag(OPT_gnu_unique, OPT_no_gnu_unique, true); Config->GdbIndex = Args.hasFlag(OPT_gdb_index, OPT_no_gdb_index, false); Config->ICF = Args.hasFlag(OPT_icf_all, OPT_icf_none, false); Config->IgnoreDataAddressEquality = @@ -633,10 +634,8 @@ Config->LTOO = args::getInteger(Args, OPT_lto_O, 2); Config->LTOPartitions = args::getInteger(Args, OPT_lto_partitions, 1); Config->MapFile = Args.getLastArgValue(OPT_Map); - Config->NoGnuUnique = Args.hasArg(OPT_no_gnu_unique); Config->MergeArmExidx = Args.hasFlag(OPT_merge_exidx_entries, OPT_no_merge_exidx_entries, true); - Config->NoUndefinedVersion = Args.hasArg(OPT_no_undefined_version); Config->NoinhibitExec = Args.hasArg(OPT_noinhibit_exec); Config->Nostdlib = Args.hasArg(OPT_nostdlib); Config->OFormatBinary = isOutputFormatBinary(Args); @@ -672,6 +671,7 @@ ThreadsEnabled = Args.hasFlag(OPT_threads, OPT_no_threads, true); Config->Trace = Args.hasArg(OPT_trace); Config->Undefined = args::getStrings(Args, OPT_undefined); + Config->UndefinedVersion = Args.hasFlag(OPT_undefined_version, OPT_no_undefined_version, true); Config->UnresolvedSymbols = getUnresolvedSymbolPolicy(Args); Config->Verbose = Args.hasArg(OPT_verbose); errorHandler().Verbose = Config->Verbose; Index: lld/ELF/Options.td =================================================================== --- lld/ELF/Options.td +++ lld/ELF/Options.td @@ -150,6 +150,10 @@ "Generate .gdb_index section", "Do not generate .gdb_index section">; +defm gnu_unique: B<"gnu-unique", + "Enable STB_GNU_UNIQUE symbol binding", + "Disable STB_GNU_UNIQUE symbol binding">; + defm hash_style: Eq<"hash-style">, HelpText<"Specify hash style (sysv, gnu or both)">; @@ -193,9 +197,6 @@ def no_dynamic_linker: F<"no-dynamic-linker">, HelpText<"Inhibit output of .interp section">; -def no_gnu_unique: F<"no-gnu-unique">, - HelpText<"Disable STB_GNU_UNIQUE symbol binding">; - def noinhibit_exec: F<"noinhibit-exec">, HelpText<"Retain the executable output file whenever it is still usable">; @@ -208,9 +209,6 @@ 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">; @@ -298,6 +296,10 @@ defm unresolved_symbols: Eq<"unresolved-symbols">, HelpText<"Determine how to handle unresolved symbols">; +defm undefined_version: B<"undefined-version", + "Allow unused version in version script", + "Report version scripts that refer undefined symbols">; + defm rsp_quoting: Eq<"rsp-quoting">, HelpText<"Quoting style for response files. Values supported: windows|posix">; Index: lld/ELF/SymbolTable.cpp =================================================================== --- lld/ELF/SymbolTable.cpp +++ lld/ELF/SymbolTable.cpp @@ -700,7 +700,7 @@ // Get a list of symbols which we need to assign the version to. std::vector Syms = findByVersion(Ver); if (Syms.empty()) { - if (Config->NoUndefinedVersion) + if (!Config->UndefinedVersion) error("version script assignment of '" + VersionName + "' to symbol '" + Ver.Name + "' failed: symbol not defined"); return; Index: lld/ELF/Symbols.cpp =================================================================== --- lld/ELF/Symbols.cpp +++ lld/ELF/Symbols.cpp @@ -241,7 +241,7 @@ return STB_LOCAL; if (VersionId == VER_NDX_LOCAL && isDefined()) return STB_LOCAL; - if (Config->NoGnuUnique && Binding == STB_GNU_UNIQUE) + if (!Config->GnuUnique && Binding == STB_GNU_UNIQUE) return STB_GLOBAL; return Binding; } Index: lld/test/ELF/gnu-unique.s =================================================================== --- lld/test/ELF/gnu-unique.s +++ lld/test/ELF/gnu-unique.s @@ -3,6 +3,8 @@ // // RUN: ld.lld %t -shared -o %tout.so // RUN: llvm-readobj -dyn-symbols %tout.so | FileCheck -check-prefix=GNU %s +// RUN: ld.lld %t -shared -o %tout.so --gnu-unique +// RUN: llvm-readobj -dyn-symbols %tout.so | FileCheck -check-prefix=GNU %s // // RUN: ld.lld %t -shared -o %tout.so --no-gnu-unique // RUN: llvm-readobj -dyn-symbols %tout.so | FileCheck -check-prefix=NO %s Index: lld/test/ELF/version-script-noundef.s =================================================================== --- lld/test/ELF/version-script-noundef.s +++ lld/test/ELF/version-script-noundef.s @@ -2,6 +2,8 @@ # RUN: echo "VERSION_1.0 { global: bar; };" > %t.script # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o +# RUN: ld.lld --version-script %t.script -shared %t.o -o %t.so +# RUN: ld.lld --version-script %t.script -shared --undefined-version %t.o -o %t.so # 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 assignment of 'VERSION_1.0' to symbol 'bar' failed: symbol not defined