[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