From 403b093eff905f45005f9c1fcfd4e2bcee8fa2f2 Mon Sep 17 00:00:00 2001 From: Rafael Espindola Date: Fri, 27 Jan 2017 15:52:08 +0000 Subject: [PATCH] Fix and simplify the reporting of undefined symbols. Now reportUndefined only has to look at Config->UnresolvedSymbols and the symbol. getUnresolvedSymbolOption does all the hard work of mapping options like -shared and -z defs to one of the UnresolvedPolicy enum entries. The critical fix is that now "-z defs --warn-unresolved-symbols" only warns. llvm-svn: 293290 --- lld/ELF/Config.h | 2 +- lld/ELF/Driver.cpp | 44 ++++++++++++------- lld/ELF/Relocations.cpp | 12 ++--- lld/test/ELF/warn-unresolved-symbols-hidden.s | 14 ++++++ 4 files changed, 48 insertions(+), 24 deletions(-) create mode 100644 lld/test/ELF/warn-unresolved-symbols-hidden.s diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index af4390e8aa6d..2649a96e9441 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -41,7 +41,7 @@ enum class DiscardPolicy { Default, All, Locals, None }; enum class StripPolicy { None, All, Debug }; // For --unresolved-symbols. -enum class UnresolvedPolicy { NoUndef, ReportError, Warn, Ignore }; +enum class UnresolvedPolicy { ReportError, Warn, WarnAll, Ignore, IgnoreAll }; // For --sort-section and linkerscript sorting rules. enum class SortSectionPolicy { Default, None, Alignment, Name, Priority }; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index cb35287bf395..93995bed4a1d 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -350,29 +350,39 @@ void LinkerDriver::main(ArrayRef ArgsArr, bool CanExitEarly) { } static UnresolvedPolicy getUnresolvedSymbolOption(opt::InputArgList &Args) { + // Find the last of --unresolved-symbols, --no-undefined and -z defs. + bool UnresolvedSymbolIsIgnoreAll = false; + bool ZDefs = false; + for (auto *Arg : Args) { + unsigned ID = Arg->getOption().getID(); + if (ID == OPT_unresolved_symbols) { + StringRef S = Arg->getValue(); + if (S == "ignore-all" || S == "ignore-in-object-files") { + ZDefs = false; + UnresolvedSymbolIsIgnoreAll = true; + } else if (S != "ignore-in-shared-libs" && S != "report-all") { + error("unknown --unresolved-symbols value: " + S); + } + } else if (ID == OPT_no_undefined || + (ID == OPT_z && Arg->getValue() == StringRef("defs"))) { + ZDefs = true; + UnresolvedSymbolIsIgnoreAll = false; + } + } + if (Args.hasArg(OPT_noinhibit_exec)) - return UnresolvedPolicy::Warn; - if (Args.hasArg(OPT_no_undefined) || hasZOption(Args, "defs")) - return UnresolvedPolicy::NoUndef; + return UnresolvedPolicy::WarnAll; if (Config->Relocatable) - return UnresolvedPolicy::Ignore; - - if (auto *Arg = Args.getLastArg(OPT_warn_undef, OPT_error_undef)) { - if (Arg->getOption().getID() == OPT_warn_undef) - return UnresolvedPolicy::Warn; + return UnresolvedPolicy::IgnoreAll; + if (ZDefs || (!Config->Shared && !UnresolvedSymbolIsIgnoreAll)) { + if (auto *Arg = Args.getLastArg(OPT_warn_undef, OPT_error_undef)) + if (Arg->getOption().getID() == OPT_warn_undef) + return UnresolvedPolicy::Warn; return UnresolvedPolicy::ReportError; } - if (auto *Arg = Args.getLastArg(OPT_unresolved_symbols)) { - StringRef S = Arg->getValue(); - if (S == "ignore-all" || S == "ignore-in-object-files") - return UnresolvedPolicy::Ignore; - if (S == "ignore-in-shared-libs" || S == "report-all") - return UnresolvedPolicy::ReportError; - error("unknown --unresolved-symbols value: " + S); - } - return UnresolvedPolicy::ReportError; + return UnresolvedPolicy::Ignore; } static Target2Policy getTarget2Option(opt::InputArgList &Args) { diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp index a14cff6fe3bb..4d2ff37d8032 100644 --- a/lld/ELF/Relocations.cpp +++ b/lld/ELF/Relocations.cpp @@ -555,17 +555,17 @@ static typename ELFT::uint computeAddend(const elf::ObjectFile &File, template static void reportUndefined(SymbolBody &Sym, InputSectionBase &S, typename ELFT::uint Offset) { - if (Config->UnresolvedSymbols == UnresolvedPolicy::Ignore) - return; - - if (Config->Shared && Sym.symbol()->Visibility == STV_DEFAULT && - Config->UnresolvedSymbols != UnresolvedPolicy::NoUndef) + bool CanBeExternal = Sym.symbol()->computeBinding() != STB_LOCAL && + Sym.getVisibility() == STV_DEFAULT; + if (Config->UnresolvedSymbols == UnresolvedPolicy::IgnoreAll || + (Config->UnresolvedSymbols == UnresolvedPolicy::Ignore && CanBeExternal)) return; std::string Msg = S.getLocation(Offset) + ": undefined symbol '" + toString(Sym) + "'"; - if (Config->UnresolvedSymbols == UnresolvedPolicy::Warn) + if (Config->UnresolvedSymbols == UnresolvedPolicy::WarnAll || + (Config->UnresolvedSymbols == UnresolvedPolicy::Warn && CanBeExternal)) warn(Msg); else error(Msg); diff --git a/lld/test/ELF/warn-unresolved-symbols-hidden.s b/lld/test/ELF/warn-unresolved-symbols-hidden.s new file mode 100644 index 000000000000..437fdfcefacd --- /dev/null +++ b/lld/test/ELF/warn-unresolved-symbols-hidden.s @@ -0,0 +1,14 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +# RUN: not ld.lld -shared %t.o -o %t.so -z defs --warn-unresolved-symbols 2>&1| FileCheck %s + +# CHECK: warning: {{.*}}: undefined symbol 'foo' +# CHECK: error: {{.*}}: undefined symbol 'bar' +# CHECK: error: {{.*}}: undefined symbol 'zed' + + .data + .quad foo + .hidden bar + .quad bar + .protected zed + .quad zed -- GitLab