[ELF] - Implemented --no-undefined-version flag

Option checks for cases where a version script explicitly lists
a symbol, but the symbol is not defined and errors out such
cases if any.

Differential revision: http://reviews.llvm.org/D21745

llvm-svn: 273998
This commit is contained in:
George Rimar 2016-06-28 08:07:26 +00:00
parent 9c366cdf2a
commit 36b2c0a683
5 changed files with 40 additions and 7 deletions

View File

@ -86,6 +86,7 @@ struct Configuration {
bool Mips64EL = false;
bool NoGnuUnique;
bool NoUndefined;
bool NoUndefinedVersion;
bool NoinhibitExec;
bool Pic;
bool Pie;

View File

@ -331,6 +331,7 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) {
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);

View File

@ -108,6 +108,9 @@ def noinhibit_exec: F<"noinhibit-exec">,
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<"<path>">,
HelpText<"Path to file to write output">;
@ -234,7 +237,6 @@ def no_copy_dt_needed_entries: F<"no-copy-dt-needed-entries">,
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">;

View File

@ -530,13 +530,20 @@ template <class ELFT> void SymbolTable<ELFT>::scanVersionScript() {
// 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)
warning("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 assignment of " + V.Name + " to symbol " +
Name + " failed: symbol not defined");
continue;
}
if (B->symbol()->VersionId != VER_NDX_GLOBAL &&
B->symbol()->VersionId != VER_NDX_LOCAL)
warning("duplicate symbol " + Name + " in version script");
B->symbol()->VersionId = I;
}
++I;
}
}

View File

@ -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 assignment of VERSION_1.0 to symbol bar failed: symbol not defined
# 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 assignment of VERSION_1.0 to symbol und failed: symbol not defined
.text
.globl foo
.type foo,@function
foo:
callq und@PLT