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
This commit is contained in:
Rafael Espindola 2017-01-27 15:52:08 +00:00
parent 095d6b8f99
commit 403b093eff
4 changed files with 48 additions and 24 deletions

View File

@ -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 };

View File

@ -350,29 +350,39 @@ void LinkerDriver::main(ArrayRef<const char *> 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) {

View File

@ -555,17 +555,17 @@ static typename ELFT::uint computeAddend(const elf::ObjectFile<ELFT> &File,
template <class ELFT>
static void reportUndefined(SymbolBody &Sym, InputSectionBase<ELFT> &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);

View File

@ -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