[lld] r325125 - [ELF] Add warnings for various symbols that cannot be ordered

James Henderson via llvm-commits llvm-commits at lists.llvm.org
Wed Feb 14 05:36:22 PST 2018


Author: jhenderson
Date: Wed Feb 14 05:36:22 2018
New Revision: 325125

URL: http://llvm.org/viewvc/llvm-project?rev=325125&view=rev
Log:
[ELF] Add warnings for various symbols that cannot be ordered

There are a number of different situations when symbols are requested
to be ordered in the --symbol-ordering-file that cannot be ordered for
some reason. To assist with identifying these symbols, and either
tidying up the order file, or the inputs, a number of warnings have
been added. As some users may find these warnings unhelpful, due to how
they use the symbol ordering file, a switch has also been added to
disable these warnings.

The cases where we now warn are:

 * Entries in the order file that don't correspond to any symbol in the input
 * Undefined symbols
 * Absolute symbols
 * Symbols imported from shared objects
 * Symbols that are discarded, due to e.g. --gc-sections or /DISCARD/ linker script sections
 * Multiple of the same entry in the order file

Reviewed by: rafael, ruiu

Differential Revision: https://reviews.llvm.org/D42475


Added:
    lld/trunk/test/ELF/Inputs/symbol-ordering-file-warnings1.s
    lld/trunk/test/ELF/Inputs/symbol-ordering-file-warnings2.s
    lld/trunk/test/ELF/symbol-ordering-file-warnings.s
Modified:
    lld/trunk/ELF/Config.h
    lld/trunk/ELF/Driver.cpp
    lld/trunk/ELF/Options.td
    lld/trunk/ELF/Writer.cpp

Modified: lld/trunk/ELF/Config.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Config.h?rev=325125&r1=325124&r2=325125&view=diff
==============================================================================
--- lld/trunk/ELF/Config.h (original)
+++ lld/trunk/ELF/Config.h Wed Feb 14 05:36:22 2018
@@ -152,6 +152,7 @@ struct Configuration {
   bool UndefinedVersion;
   bool WarnCommon;
   bool WarnMissingEntry;
+  bool WarnSymbolOrdering;
   bool WriteAddends;
   bool ZCombreloc;
   bool ZExecstack;

Modified: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=325125&r1=325124&r2=325125&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Wed Feb 14 05:36:22 2018
@@ -45,6 +45,7 @@
 #include "lld/Common/TargetOptionsCommandFlags.h"
 #include "lld/Common/Threads.h"
 #include "lld/Common/Version.h"
+#include "llvm/ADT/SetVector.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/Support/CommandLine.h"
@@ -589,6 +590,16 @@ static int parseInt(StringRef S, opt::Ar
   return V;
 }
 
+// Parse the symbol ordering file and warn for any duplicate entries.
+static std::vector<StringRef> getSymbolOrderingFile(MemoryBufferRef MB) {
+  SetVector<StringRef> Names;
+  for (StringRef S : args::getLines(MB))
+    if (!Names.insert(S) && Config->WarnSymbolOrdering)
+      warn(MB.getBufferIdentifier() + ": duplicate ordered symbol: " + S);
+
+  return Names.takeVector();
+}
+
 // Initializes Config members by the command line options.
 void LinkerDriver::readConfigs(opt::InputArgList &Args) {
   errorHandler().Verbose = Args.hasArg(OPT_verbose);
@@ -677,6 +688,8 @@ void LinkerDriver::readConfigs(opt::Inpu
       Args.hasFlag(OPT_undefined_version, OPT_no_undefined_version, true);
   Config->UnresolvedSymbols = getUnresolvedSymbolPolicy(Args);
   Config->WarnCommon = Args.hasFlag(OPT_warn_common, OPT_no_warn_common, false);
+  Config->WarnSymbolOrdering =
+      Args.hasFlag(OPT_warn_symbol_ordering, OPT_no_warn_symbol_ordering, true);
   Config->ZCombreloc = !hasZOption(Args, "nocombreloc");
   Config->ZExecstack = hasZOption(Args, "execstack");
   Config->ZNocopyreloc = hasZOption(Args, "nocopyreloc");
@@ -767,7 +780,7 @@ void LinkerDriver::readConfigs(opt::Inpu
 
   if (auto *Arg = Args.getLastArg(OPT_symbol_ordering_file))
     if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue()))
-      Config->SymbolOrderingFile = args::getLines(*Buffer);
+      Config->SymbolOrderingFile = getSymbolOrderingFile(*Buffer);
 
   // If --retain-symbol-file is used, we'll keep only the symbols listed in
   // the file and discard all others.

Modified: lld/trunk/ELF/Options.td
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Options.td?rev=325125&r1=325124&r2=325125&view=diff
==============================================================================
--- lld/trunk/ELF/Options.td (original)
+++ lld/trunk/ELF/Options.td Wed Feb 14 05:36:22 2018
@@ -324,6 +324,10 @@ defm warn_common: B<"warn-common",
     "Warn about duplicate common symbols",
     "Do not warn about duplicate common symbols">;
 
+defm warn_symbol_ordering : B<"warn-symbol-ordering",
+    "Warn about problems with the symbol ordering file",
+    "Do not warn about problems with the symbol ordering file">;
+
 def warn_unresolved_symbols: F<"warn-unresolved-symbols">,
   HelpText<"Report unresolved symbols as warnings">;
 

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=325125&r1=325124&r2=325125&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Wed Feb 14 05:36:22 2018
@@ -1022,25 +1022,58 @@ static DenseMap<const InputSectionBase *
   if (Config->SymbolOrderingFile.empty())
     return SectionOrder;
 
+  struct SymbolOrderEntry {
+    int Priority;
+    bool Present;
+  };
+
   // Build a map from symbols to their priorities. Symbols that didn't
   // appear in the symbol ordering file have the lowest priority 0.
   // All explicitly mentioned symbols have negative (higher) priorities.
-  DenseMap<StringRef, int> SymbolOrder;
+  DenseMap<StringRef, SymbolOrderEntry> SymbolOrder;
   int Priority = -Config->SymbolOrderingFile.size();
   for (StringRef S : Config->SymbolOrderingFile)
-    SymbolOrder.insert({S, Priority++});
+    SymbolOrder.insert({S, {Priority++, false}});
 
   // Build a map from sections to their priorities.
   for (InputFile *File : ObjectFiles) {
     for (Symbol *Sym : File->getSymbols()) {
-      if (auto *D = dyn_cast<Defined>(Sym)) {
-        if (auto *Sec = dyn_cast_or_null<InputSectionBase>(D->Section)) {
-          int &Priority = SectionOrder[Sec];
-          Priority = std::min(Priority, SymbolOrder.lookup(D->getName()));
-        }
+      auto It = SymbolOrder.find(Sym->getName());
+      if (It == SymbolOrder.end())
+        continue;
+      SymbolOrderEntry &Ent = It->second;
+      Ent.Present = true;
+
+      auto *D = dyn_cast<Defined>(Sym);
+      if (Config->WarnSymbolOrdering) {
+        if (Sym->isUndefined())
+          warn(File->getName() +
+               ": unable to order undefined symbol: " + Sym->getName());
+        else if (Sym->isShared())
+          warn(File->getName() +
+               ": unable to order shared symbol: " + Sym->getName());
+        else if (D && !D->Section)
+          warn(File->getName() +
+               ": unable to order absolute symbol: " + Sym->getName());
+        else if (D && !D->Section->Live)
+          warn(File->getName() +
+               ": unable to order discarded symbol: " + Sym->getName());
+      }
+      if (!D)
+        continue;
+
+      if (auto *Sec = dyn_cast_or_null<InputSectionBase>(D->Section)) {
+        int &Priority = SectionOrder[Sec];
+        Priority = std::min(Priority, Ent.Priority);
       }
     }
   }
+
+  if (Config->WarnSymbolOrdering)
+    for (auto OrderEntry : SymbolOrder)
+      if (!OrderEntry.second.Present)
+        warn("symbol ordering file: no such symbol: " + OrderEntry.first);
+
   return SectionOrder;
 }
 

Added: lld/trunk/test/ELF/Inputs/symbol-ordering-file-warnings1.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/symbol-ordering-file-warnings1.s?rev=325125&view=auto
==============================================================================
--- lld/trunk/test/ELF/Inputs/symbol-ordering-file-warnings1.s (added)
+++ lld/trunk/test/ELF/Inputs/symbol-ordering-file-warnings1.s Wed Feb 14 05:36:22 2018
@@ -0,0 +1,19 @@
+# This is a "bad" (absolute) instance of the symbol
+multi = 1234
+
+.text
+.global shared
+.type shared, @function
+shared:
+  movq  %rax, multi
+  ret
+
+.section .text.comdat,"axG", at progbits,comdat,comdat
+.weak comdat
+comdat:
+  ret
+
+.section .text.glob_or_wk,"ax", at progbits
+.global glob_or_wk
+glob_or_wk:
+  ret

Added: lld/trunk/test/ELF/Inputs/symbol-ordering-file-warnings2.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/symbol-ordering-file-warnings2.s?rev=325125&view=auto
==============================================================================
--- lld/trunk/test/ELF/Inputs/symbol-ordering-file-warnings2.s (added)
+++ lld/trunk/test/ELF/Inputs/symbol-ordering-file-warnings2.s Wed Feb 14 05:36:22 2018
@@ -0,0 +1,6 @@
+.text
+.global missing
+missing:
+  callq undefined
+  # This is a "bad" (undefined) instance of the symbol
+  callq multi

Added: lld/trunk/test/ELF/symbol-ordering-file-warnings.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/symbol-ordering-file-warnings.s?rev=325125&view=auto
==============================================================================
--- lld/trunk/test/ELF/symbol-ordering-file-warnings.s (added)
+++ lld/trunk/test/ELF/symbol-ordering-file-warnings.s Wed Feb 14 05:36:22 2018
@@ -0,0 +1,140 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t1.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/symbol-ordering-file-warnings1.s -o %t2.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/symbol-ordering-file-warnings2.s -o %t3.o
+# RUN: ld.lld -shared %t2.o -o %t.so
+
+# Check that a warning is emitted for entries in the file that are not present in any used input.
+# RUN: echo "missing" > %t-order-missing.txt
+# RUN: ld.lld %t1.o -o %t --symbol-ordering-file %t-order-missing.txt --unresolved-symbols=ignore-all 2>&1 | \
+# RUN:   FileCheck %s --check-prefixes=WARN,MISSING
+
+# Check that the warning can be disabled.
+# RUN: ld.lld %t1.o -o %t --symbol-ordering-file %t-order-missing.txt --unresolved-symbols=ignore-all --no-warn-symbol-ordering 2>&1 | \
+# RUN:   FileCheck %s --check-prefixes=WARN --allow-empty
+
+# Check that the warning can be re-enabled
+# RUN: ld.lld %t1.o -o %t --symbol-ordering-file %t-order-missing.txt --unresolved-symbols=ignore-all --no-warn-symbol-ordering --warn-symbol-ordering 2>&1 | \
+# RUN:   FileCheck %s --check-prefixes=WARN,MISSING
+
+# Check that a warning is emitted for undefined symbols.
+# RUN: echo "undefined" > %t-order-undef.txt
+# RUN: ld.lld %t1.o %t3.o -o %t --symbol-ordering-file %t-order-undef.txt --unresolved-symbols=ignore-all 2>&1 | \
+# RUN:   FileCheck %s --check-prefixes=WARN,UNDEFINED
+
+# Check that a warning is emitted for imported shared symbols.
+# RUN: echo "shared" > %t-order-shared.txt
+# RUN: ld.lld %t1.o %t.so -o %t --symbol-ordering-file %t-order-shared.txt --unresolved-symbols=ignore-all 2>&1 | \
+# RUN:   FileCheck %s --check-prefixes=WARN,SHARED
+
+# Check that a warning is emitted for absolute symbols.
+# RUN: echo "absolute" > %t-order-absolute.txt
+# RUN: ld.lld %t1.o -o %t --symbol-ordering-file %t-order-absolute.txt --unresolved-symbols=ignore-all 2>&1 | \
+# RUN:   FileCheck %s --check-prefixes=WARN,ABSOLUTE
+
+# Check that a warning is emitted for symbols discarded due to --gc-sections.
+# RUN: echo "gc" > %t-order-gc.txt
+# RUN: ld.lld %t1.o -o %t --symbol-ordering-file %t-order-gc.txt --gc-sections --unresolved-symbols=ignore-all 2>&1 | \
+# RUN:   FileCheck %s --check-prefixes=WARN,GC
+
+# Check that a warning is emitted for symbols discarded due to a linker script /DISCARD/ section.
+# RUN: echo "discard" > %t-order-discard.txt
+# RUN: echo "SECTIONS { /DISCARD/ : { *(.text.discard) } }" > %t.script
+# RUN: ld.lld %t1.o -o %t --symbol-ordering-file %t-order-discard.txt -T %t.script --unresolved-symbols=ignore-all 2>&1 | \
+# RUN:   FileCheck %s --check-prefixes=WARN,DISCARD
+
+# Check that LLD does not warn for discarded COMDAT symbols, if they are present in the kept instance.
+# RUN: echo "comdat" > %t-order-comdat.txt
+# RUN: ld.lld %t1.o %t2.o -o %t --symbol-ordering-file %t-order-comdat.txt --unresolved-symbols=ignore-all 2>&1 | \
+# RUN:   FileCheck %s --check-prefixes=WARN --allow-empty
+
+# Check that if a COMDAT was unused and discarded via --gc-sections, warn for each instance.
+# RUN: ld.lld %t1.o %t2.o -o %t --symbol-ordering-file %t-order-comdat.txt --gc-sections --unresolved-symbols=ignore-all 2>&1 | \
+# RUN:   FileCheck %s --check-prefixes=WARN,COMDAT
+
+# Check that if a weak symbol is not kept, because of an equivalent global symbol, no warning is emitted.
+# RUN: echo "glob_or_wk" > %t-order-weak.txt
+# RUN: ld.lld %t1.o %t2.o -o %t --symbol-ordering-file %t-order-weak.txt --unresolved-symbols=ignore-all 2>&1 | \
+# RUN:   FileCheck %s --check-prefixes=WARN --allow-empty
+
+# Check that symbols only in unused archive members result in a warning.
+# RUN: rm -f %t.a
+# RUN: llvm-ar rc %t.a %t3.o
+# RUN: ld.lld %t1.o %t.a -o %t --symbol-ordering-file %t-order-missing.txt --unresolved-symbols=ignore-all 2>&1 | \
+# RUN:   FileCheck %s --check-prefixes=WARN,MISSING --allow-empty
+
+# Check that a warning for each same-named symbol with an issue.
+# RUN: echo "multi" > %t-order-same-name.txt
+# RUN: ld.lld %t1.o %t2.o %t3.o -o %t --symbol-ordering-file %t-order-same-name.txt --unresolved-symbols=ignore-all 2>&1 | \
+# RUN:   FileCheck %s --check-prefixes=WARN,MULTI
+
+# Check that a warning is emitted if the same symbol is mentioned multiple times in the ordering file.
+# RUN: echo "_start" > %t-order-multiple-same.txt
+# RUN: echo "_start" >> %t-order-multiple-same.txt
+# RUN: ld.lld %t1.o -o %t --symbol-ordering-file %t-order-multiple-same.txt --unresolved-symbols=ignore-all 2>&1 | \
+# RUN:   FileCheck %s --check-prefixes=WARN,SAMESYM
+
+# Check that all warnings can be emitted from the same input.
+# RUN: echo "missing_sym" > %t-order-multi.txt
+# RUN: echo "undefined" >> %t-order-multi.txt
+# RUN: echo "_start" >> %t-order-multi.txt
+# RUN: echo "shared" >> %t-order-multi.txt
+# RUN: echo "absolute" >> %t-order-multi.txt
+# RUN: echo "gc" >> %t-order-multi.txt
+# RUN: echo "discard" >> %t-order-multi.txt
+# RUN: echo "_start" >> %t-order-multi.txt
+# RUN: ld.lld %t1.o %t3.o %t.so -o %t --symbol-ordering-file %t-order-multi.txt --gc-sections -T %t.script --unresolved-symbols=ignore-all 2>&1 | \
+# RUN:   FileCheck %s --check-prefixes=WARN,SAMESYM,ABSOLUTE,SHARED,UNDEFINED,GC,DISCARD,MISSING2
+
+# WARN-NOT:    warning:
+# SAMESYM:     warning: {{.*}}.txt: duplicate ordered symbol: _start
+# WARN-NOT:    warning:
+# ABSOLUTE:    warning: {{.*}}1.o: unable to order absolute symbol: absolute
+# WARN-NOT:    warning:
+# DISCARD:     warning: {{.*}}1.o: unable to order discarded symbol: discard
+# WARN-NOT:    warning:
+# GC:          warning: {{.*}}1.o: unable to order discarded symbol: gc
+# WARN-NOT:    warning:
+# SHARED:      warning: {{.*}}1.o: unable to order shared symbol: shared
+# WARN-NOT:    warning:
+# UNDEFINED:   warning: {{.*}}3.o: unable to order undefined symbol: undefined
+# WARN-NOT:    warning:
+# MISSING:     warning: symbol ordering file: no such symbol: missing
+# MISSING2:    warning: symbol ordering file: no such symbol: missing_sym
+# COMDAT:      warning: {{.*}}1.o: unable to order discarded symbol: comdat
+# COMDAT-NEXT: warning: {{.*}}2.o: unable to order discarded symbol: comdat
+# MULTI:       warning: {{.*}}2.o: unable to order absolute symbol: multi
+# MULTI-NEXT:  warning: {{.*}}3.o: unable to order undefined symbol: multi
+# WARN-NOT:    warning:
+
+absolute = 0x1234
+
+.section .text.gc,"ax", at progbits
+.global gc
+gc:
+  nop
+
+.section .text.discard,"ax", at progbits
+.global discard
+discard:
+  nop
+
+.section .text.comdat,"axG", at progbits,comdat,comdat
+.weak comdat
+comdat:
+  nop
+
+.section .text.glob_or_wk,"ax", at progbits
+.weak glob_or_wk
+glob_or_wk:
+  nop
+
+.text
+.global _start
+_start:
+  movq  %rax, absolute
+  callq shared
+
+# This is a "good" instance of the symbol
+multi:
+  nop




More information about the llvm-commits mailing list