[lld] 55d310a - [ELF] Fix interaction between --unresolved-symbols= and --[no-]allow-shlib-undefined
Fangrui Song via llvm-commits
llvm-commits at lists.llvm.org
Tue Nov 17 12:21:05 PST 2020
Author: Fangrui Song
Date: 2020-11-17T12:20:57-08:00
New Revision: 55d310adc068a569eaa5370e5b94428ed9ea7ed8
URL: https://github.com/llvm/llvm-project/commit/55d310adc068a569eaa5370e5b94428ed9ea7ed8
DIFF: https://github.com/llvm/llvm-project/commit/55d310adc068a569eaa5370e5b94428ed9ea7ed8.diff
LOG: [ELF] Fix interaction between --unresolved-symbols= and --[no-]allow-shlib-undefined
As mentioned in https://reviews.llvm.org/D67479#1667256 ,
* `--[no-]allow-shlib-undefined` control the diagnostic for an unresolved symbol in a shared object
* `-z defs/-z undefs` control the diagnostic for an unresolved symbol in a regular object file
* `--unresolved-symbols=` controls both bits.
In addition, make --warn-unresolved-symbols affect --no-allow-shlib-undefined.
This patch makes the behavior match GNU ld.
Reviewed By: psmith
Differential Revision: https://reviews.llvm.org/D91510
Added:
Modified:
lld/ELF/Config.h
lld/ELF/Driver.cpp
lld/ELF/Writer.cpp
lld/test/ELF/allow-shlib-undefined.s
lld/test/ELF/unresolved-symbols.s
Removed:
################################################################################
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h
index f043d1d4d30d..596188a33c5f 100644
--- a/lld/ELF/Config.h
+++ b/lld/ELF/Config.h
@@ -137,7 +137,6 @@ struct Configuration {
uint64_t>
callGraphProfile;
bool allowMultipleDefinition;
- bool allowShlibUndefined;
bool androidPackDynRelocs;
bool armHasBlx = false;
bool armHasMovtMovw = false;
@@ -247,6 +246,7 @@ struct Configuration {
SortSectionPolicy sortSection;
StripPolicy strip;
UnresolvedPolicy unresolvedSymbols;
+ UnresolvedPolicy unresolvedSymbolsInShlib;
Target2Policy target2;
ARMVFPArgKind armVFPArgs = ARMVFPArgKind::Default;
BuildIdKind buildId = BuildIdKind::None;
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp
index 318c231088a0..783b85e7e27a 100644
--- a/lld/ELF/Driver.cpp
+++ b/lld/ELF/Driver.cpp
@@ -584,40 +584,58 @@ static std::string getRpath(opt::InputArgList &args) {
// Determines what we should do if there are remaining unresolved
// symbols after the name resolution.
-static UnresolvedPolicy getUnresolvedSymbolPolicy(opt::InputArgList &args) {
+static void setUnresolvedSymbolPolicy(opt::InputArgList &args) {
UnresolvedPolicy errorOrWarn = args.hasFlag(OPT_error_unresolved_symbols,
OPT_warn_unresolved_symbols, true)
? UnresolvedPolicy::ReportError
: UnresolvedPolicy::Warn;
+ // -shared implies -unresolved-symbols=ignore-all because missing
+ // symbols are likely to be resolved at runtime.
+ bool diagRegular = !config->shared, diagShlib = !config->shared;
- // Process the last of -unresolved-symbols, -no-undefined or -z defs.
- for (auto *arg : llvm::reverse(args)) {
+ for (const opt::Arg *arg : args) {
switch (arg->getOption().getID()) {
case 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 errorOrWarn;
- error("unknown --unresolved-symbols value: " + s);
- continue;
+ if (s == "ignore-all") {
+ diagRegular = false;
+ diagShlib = false;
+ } else if (s == "ignore-in-object-files") {
+ diagRegular = false;
+ diagShlib = true;
+ } else if (s == "ignore-in-shared-libs") {
+ diagRegular = true;
+ diagShlib = false;
+ } else if (s == "report-all") {
+ diagRegular = true;
+ diagShlib = true;
+ } else {
+ error("unknown --unresolved-symbols value: " + s);
+ }
+ break;
}
case OPT_no_undefined:
- return errorOrWarn;
+ diagRegular = true;
+ break;
case OPT_z:
if (StringRef(arg->getValue()) == "defs")
- return errorOrWarn;
- if (StringRef(arg->getValue()) == "undefs")
- return UnresolvedPolicy::Ignore;
- continue;
+ diagRegular = true;
+ else if (StringRef(arg->getValue()) == "undefs")
+ diagRegular = false;
+ break;
+ case OPT_allow_shlib_undefined:
+ diagShlib = false;
+ break;
+ case OPT_no_allow_shlib_undefined:
+ diagShlib = true;
+ break;
}
}
- // -shared implies -unresolved-symbols=ignore-all because missing
- // symbols are likely to be resolved at runtime using other DSOs.
- if (config->shared)
- return UnresolvedPolicy::Ignore;
- return errorOrWarn;
+ config->unresolvedSymbols =
+ diagRegular ? errorOrWarn : UnresolvedPolicy::Ignore;
+ config->unresolvedSymbolsInShlib =
+ diagShlib ? errorOrWarn : UnresolvedPolicy::Ignore;
}
static Target2Policy getTarget2(opt::InputArgList &args) {
@@ -913,9 +931,6 @@ static void readConfigs(opt::InputArgList &args) {
args.hasFlag(OPT_allow_multiple_definition,
OPT_no_allow_multiple_definition, false) ||
hasZOption(args, "muldefs");
- config->allowShlibUndefined =
- args.hasFlag(OPT_allow_shlib_undefined, OPT_no_allow_shlib_undefined,
- args.hasArg(OPT_shared));
config->auxiliaryList = args::getStrings(args, OPT_auxiliary);
config->bsymbolic = args.hasArg(OPT_Bsymbolic);
config->bsymbolicFunctions = args.hasArg(OPT_Bsymbolic_functions);
@@ -1051,7 +1066,6 @@ static void readConfigs(opt::InputArgList &args) {
config->unique = args.hasArg(OPT_unique);
config->useAndroidRelrTags = args.hasFlag(
OPT_use_android_relr_tags, OPT_no_use_android_relr_tags, false);
- config->unresolvedSymbols = getUnresolvedSymbolPolicy(args);
config->warnBackrefs =
args.hasFlag(OPT_warn_backrefs, OPT_no_warn_backrefs, false);
config->warnCommon = args.hasFlag(OPT_warn_common, OPT_no_warn_common, false);
@@ -1086,6 +1100,7 @@ static void readConfigs(opt::InputArgList &args) {
config->zStartStopVisibility = getZStartStopVisibility(args);
config->zText = getZFlag(args, "text", "notext", true);
config->zWxneeded = hasZOption(args, "wxneeded");
+ setUnresolvedSymbolPolicy(args);
for (opt::Arg *arg : args.filtered(OPT_z)) {
std::pair<StringRef, StringRef> option =
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp
index 1bb88a25351c..98139b56b29b 100644
--- a/lld/ELF/Writer.cpp
+++ b/lld/ELF/Writer.cpp
@@ -1988,7 +1988,7 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
if (in.iplt && in.iplt->isNeeded())
in.iplt->addSymbols();
- if (!config->allowShlibUndefined) {
+ if (config->unresolvedSymbolsInShlib != UnresolvedPolicy::Ignore) {
// Error on undefined symbols in a shared object, if all of its DT_NEEDED
// entries are seen. These cases would otherwise lead to runtime errors
// reported by the dynamic linker.
@@ -2005,9 +2005,14 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
for (Symbol *sym : symtab->symbols())
if (sym->isUndefined() && !sym->isWeak())
if (auto *f = dyn_cast_or_null<SharedFile>(sym->file))
- if (f->allNeededIsKnown)
- errorOrWarn(toString(f) + ": undefined reference to " +
- toString(*sym) + " [--no-allow-shlib-undefined]");
+ if (f->allNeededIsKnown) {
+ auto diagnose = config->unresolvedSymbolsInShlib ==
+ UnresolvedPolicy::ReportError
+ ? errorOrWarn
+ : warn;
+ diagnose(toString(f) + ": undefined reference to " +
+ toString(*sym) + " [--no-allow-shlib-undefined]");
+ }
}
{
diff --git a/lld/test/ELF/allow-shlib-undefined.s b/lld/test/ELF/allow-shlib-undefined.s
index 59205552eb3c..4994466ec5dc 100644
--- a/lld/test/ELF/allow-shlib-undefined.s
+++ b/lld/test/ELF/allow-shlib-undefined.s
@@ -9,7 +9,8 @@
# RUN: not ld.lld --no-allow-shlib-undefined %t.o %t.so -o /dev/null 2>&1 | FileCheck %s
# Executable defaults to --no-allow-shlib-undefined
# RUN: not ld.lld %t.o %t.so -o /dev/null 2>&1 | FileCheck %s
-# RUN: ld.lld %t.o %t.so --noinhibit-exec -o /dev/null 2>&1 | FileCheck %s
+# RUN: ld.lld %t.o %t.so --noinhibit-exec -o /dev/null 2>&1 | FileCheck %s --check-prefix=WARN
+# RUN: ld.lld %t.o %t.so --warn-unresolved-symbols -o /dev/null 2>&1 | FileCheck %s --check-prefix=WARN
# -shared defaults to --allow-shlib-undefined
# RUN: ld.lld -shared %t.o %t.so -o /dev/null
@@ -28,4 +29,5 @@
_start:
callq _shared at PLT
-# CHECK: {{.*}}.so: undefined reference to _unresolved [--no-allow-shlib-undefined]
+# CHECK: error: {{.*}}.so: undefined reference to _unresolved [--no-allow-shlib-undefined]
+# WARN: warning: {{.*}}.so: undefined reference to _unresolved [--no-allow-shlib-undefined]
diff --git a/lld/test/ELF/unresolved-symbols.s b/lld/test/ELF/unresolved-symbols.s
index 90581e5be4e4..ac7279c1a7bd 100644
--- a/lld/test/ELF/unresolved-symbols.s
+++ b/lld/test/ELF/unresolved-symbols.s
@@ -33,9 +33,10 @@
## Ignoring undefines in objects should not produce error for symbol from object.
# RUN: ld.lld %t1.o %t2.o -o %t2 --unresolved-symbols=ignore-in-object-files
# RUN: llvm-readobj %t2 > /dev/null 2>&1
-## And still should not should produce for undefines from DSOs.
-# RUN: ld.lld %t1.o %t.so -o /dev/null --allow-shlib-undefined --unresolved-symbols=ignore-in-object-files
-# RUN: llvm-readobj %t2 > /dev/null 2>&1
+## --unresolved-symbols overrides a previous --allow-shlib-undefined.
+# RUN: not ld.lld %t1.o %t.so -o /dev/null --allow-shlib-undefined --unresolved-symbols=ignore-in-object-files 2>&1 | FileCheck %s --check-prefix=SHLIB
+
+# SHLIB: error: {{.*}}.so: undefined reference to undef [--no-allow-shlib-undefined]
## Ignoring undefines in shared should produce error for symbol from object.
# RUN: not ld.lld %t2.o -o /dev/null --unresolved-symbols=ignore-in-shared-libs 2>&1 | \
@@ -53,11 +54,9 @@
# RUN: ld.lld -r %t1.o %t2.o -o %t5 --unresolved-symbols=report-all
# RUN: llvm-readobj %t5 > /dev/null 2>&1
-## report-all is the default one. Check that we do not report
-## undefines from DSO and do report undefines from object. With
-## report-all specified and without.
-# RUN: ld.lld -shared %t1.o %t.so -o %t6 --unresolved-symbols=report-all
-# RUN: llvm-readobj %t6 > /dev/null 2>&1
+## report-all is the default when linking an executable. Check that we report
+## unresolved undefines from both DSO and regular object files.
+# RUN: not ld.lld -shared %t1.o %t.so -o /dev/null --unresolved-symbols=report-all 2>&1 | FileCheck %s --check-prefix=SHLIB
# RUN: ld.lld -shared %t1.o %t.so -o %t6_1
# RUN: llvm-readobj %t6_1 > /dev/null 2>&1
# RUN: not ld.lld %t2.o -o /dev/null --unresolved-symbols=report-all 2>&1 | \
More information about the llvm-commits
mailing list