[lld] r274123 - [ELF] - Added support for --unresolved-symbols option.

George Rimar via llvm-commits llvm-commits at lists.llvm.org
Wed Jun 29 05:35:04 PDT 2016


Author: grimar
Date: Wed Jun 29 07:35:04 2016
New Revision: 274123

URL: http://llvm.org/viewvc/llvm-project?rev=274123&view=rev
Log:
[ELF] - Added support for --unresolved-symbols option.

Option has next description (http://linux.die.net/man/1/ld):
"--unresolved-symbols=method
Determine how to handle unresolved symbols. There are four possible values for method
according to documentation:

ignore-all: Do not report any unresolved symbols.
report-all: Report all unresolved symbols. This is the default.
ignore-in-object-files: Report unresolved symbols that are contained in shared libraries, but ignore them if they come from regular object files.
ignore-in-shared-libs: Report unresolved symbols that come from regular object files, but ignore them if they come from shared libraries."

Since report-all is default and we traditionally do not report about undefined symbols in lld,
report-all does not report about undefines from DSO. 
ignore-in-object-files also does not do that. Handling of that option differs from what gnu linkers do.

Option works in next way in lld:
ignore-all: Do not report any unresolved symbols.
report-all: Report all unresolved symbols except symbols from DSOs. This is the default.
ignore-in-object-files: The same as ignore-all.
gnore-in-shared-libs: The same as report-all.

This is PR24524.

Differential revision: http://reviews.llvm.org/D21794

Added:
    lld/trunk/test/ELF/Inputs/unresolved-symbols.s
    lld/trunk/test/ELF/unresolved-symbols.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=274123&r1=274122&r2=274123&view=diff
==============================================================================
--- lld/trunk/ELF/Config.h (original)
+++ lld/trunk/ELF/Config.h Wed Jun 29 07:35:04 2016
@@ -33,6 +33,8 @@ enum ELFKind {
 
 enum class BuildIdKind { None, Fnv1, Md5, Sha1, Hexstring };
 
+enum class UnresolvedPolicy { NoUndef, Error, Warn, Ignore };
+
 // This struct contains symbols version definition that
 // can be found in version script if it is used for link.
 struct Version {
@@ -85,9 +87,7 @@ struct Configuration {
   bool ICF;
   bool Mips64EL = false;
   bool NoGnuUnique;
-  bool NoUndefined;
   bool NoUndefinedVersion;
-  bool NoinhibitExec;
   bool Pic;
   bool Pie;
   bool PrintGcSections;
@@ -110,6 +110,7 @@ struct Configuration {
   bool ZNow;
   bool ZOrigin;
   bool ZRelro;
+  UnresolvedPolicy UnresolvedSymbols;
   BuildIdKind BuildId = BuildIdKind::None;
   ELFKind EKind = ELFNoneKind;
   uint16_t EMachine = llvm::ELF::EM_NONE;

Modified: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=274123&r1=274122&r2=274123&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Wed Jun 29 07:35:04 2016
@@ -296,6 +296,25 @@ void LinkerDriver::main(ArrayRef<const c
   }
 }
 
+static UnresolvedPolicy getUnresolvedSymbolOption(opt::InputArgList &Args) {
+  if (Args.hasArg(OPT_noinhibit_exec))
+    return UnresolvedPolicy::Warn;
+  if (Args.hasArg(OPT_no_undefined) || hasZOption(Args, "defs"))
+    return UnresolvedPolicy::NoUndef;
+  if (Config->Relocatable)
+    return UnresolvedPolicy::Ignore;
+
+  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::Error;
+    error("unknown --unresolved-symbols value: " + S);
+  }
+  return UnresolvedPolicy::Error;
+}
+
 // Initializes Config members by the command line options.
 void LinkerDriver::readConfigs(opt::InputArgList &Args) {
   for (auto *Arg : Args.filtered(OPT_L))
@@ -328,10 +347,7 @@ void LinkerDriver::readConfigs(opt::Inpu
   Config->GcSections = Args.hasArg(OPT_gc_sections);
   Config->ICF = Args.hasArg(OPT_icf);
   Config->NoGnuUnique = Args.hasArg(OPT_no_gnu_unique);
-  Config->NoUndefined =
-      Args.hasArg(OPT_no_undefined) || hasZOption(Args, "defs");
   Config->NoUndefinedVersion = Args.hasArg(OPT_no_undefined_version);
-  Config->NoinhibitExec = Args.hasArg(OPT_noinhibit_exec);
   Config->Pie = Args.hasArg(OPT_pie);
   Config->PrintGcSections = Args.hasArg(OPT_print_gc_sections);
   Config->Relocatable = Args.hasArg(OPT_relocatable);
@@ -412,6 +428,8 @@ void LinkerDriver::readConfigs(opt::Inpu
   for (auto *Arg : Args.filtered(OPT_undefined))
     Config->Undefined.push_back(Arg->getValue());
 
+  Config->UnresolvedSymbols = getUnresolvedSymbolOption(Args);
+
   if (auto *Arg = Args.getLastArg(OPT_dynamic_list))
     if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue()))
       parseDynamicList(*Buffer);

Modified: lld/trunk/ELF/Options.td
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Options.td?rev=274123&r1=274122&r2=274123&view=diff
==============================================================================
--- lld/trunk/ELF/Options.td (original)
+++ lld/trunk/ELF/Options.td Wed Jun 29 07:35:04 2016
@@ -150,6 +150,9 @@ def trace_symbol : J<"trace-symbol=">, H
 def undefined: J<"undefined=">,
   HelpText<"Force undefined symbol during linking">;
 
+def unresolved_symbols: J<"unresolved-symbols=">,
+  HelpText<"Determine how to handle unresolved symbols">;
+
 def verbose: F<"verbose">, HelpText<"Verbose mode">;
 
 def version: F<"version">, HelpText<"Display the version number">;

Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=274123&r1=274122&r2=274123&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Wed Jun 29 07:35:04 2016
@@ -275,17 +275,17 @@ template <bool Is64Bits> struct DenseMap
 
 template <class ELFT>
 static void reportUndefined(SymbolTable<ELFT> &Symtab, SymbolBody *Sym) {
-  if (!Config->NoUndefined) {
-    if (Config->Relocatable)
-      return;
-    if (Config->Shared && Sym->symbol()->Visibility == STV_DEFAULT)
-      return;
-  }
+  if (Config->UnresolvedSymbols == UnresolvedPolicy::Ignore)
+    return;
+
+  if (Config->Shared && Sym->symbol()->Visibility == STV_DEFAULT &&
+      Config->UnresolvedSymbols != UnresolvedPolicy::NoUndef)
+    return;
 
   std::string Msg = "undefined symbol: " + Sym->getName().str();
   if (InputFile *File = Sym->getSourceFile<ELFT>())
     Msg += " in " + getFilename(File);
-  if (Config->NoinhibitExec)
+  if (Config->UnresolvedSymbols == UnresolvedPolicy::Warn)
     warning(Msg);
   else
     error(Msg);

Added: lld/trunk/test/ELF/Inputs/unresolved-symbols.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/Inputs/unresolved-symbols.s?rev=274123&view=auto
==============================================================================
--- lld/trunk/test/ELF/Inputs/unresolved-symbols.s (added)
+++ lld/trunk/test/ELF/Inputs/unresolved-symbols.s Wed Jun 29 07:35:04 2016
@@ -0,0 +1,3 @@
+.globl _shared
+_shared:
+  callq undef at PLT

Added: lld/trunk/test/ELF/unresolved-symbols.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/unresolved-symbols.s?rev=274123&view=auto
==============================================================================
--- lld/trunk/test/ELF/unresolved-symbols.s (added)
+++ lld/trunk/test/ELF/unresolved-symbols.s Wed Jun 29 07:35:04 2016
@@ -0,0 +1,63 @@
+# 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 %p/Inputs/unresolved-symbols.s -o %t2.o
+# RUN: ld.lld -shared %t2.o -o %t.so
+
+## Check that %t2.o contains undefined symbol undef.
+# RUN: not ld.lld %t1.o %t2.o -o %t 2>&1 | \
+# RUN:   FileCheck -check-prefix=UNDCHECK %s
+# UNDCHECK: undefined symbol: undef in {{.*}}2.o
+
+## Error out if unknown option value was set.
+# RUN: not ld.lld %t1.o %t2.o -o %t --unresolved-symbols=xxx 2>&1 | \
+# RUN:   FileCheck -check-prefix=ERR1 %s
+# ERR1: unknown --unresolved-symbols value: xxx
+
+## Ignore all should not produce error for symbols from object except
+## case when --no-undefined specified.
+# RUN: ld.lld %t2.o -o %t1_1 --unresolved-symbols=ignore-all
+# RUN: llvm-readobj %t1_1 > /dev/null 2>&1
+# RUN: not ld.lld %t2.o -o %t1_2 --unresolved-symbols=ignore-all --no-undefined 2>&1 | \
+# RUN:   FileCheck -check-prefix=ERRUND %s
+# ERRUND: undefined symbol: undef
+## Also ignore all should not produce error for symbols from DSOs.
+# RUN: ld.lld %t1.o %t.so -o %t1_3 --unresolved-symbols=ignore-all
+# RUN: llvm-readobj %t1_3 > /dev/null 2>&1
+
+## 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 %t2_1 --unresolved-symbols=ignore-in-object-files
+# RUN: llvm-readobj %t2 > /dev/null 2>&1
+
+## Ignoring undefines in shared should produce error for symbol from object.
+# RUN: not ld.lld %t2.o -o %t3 --unresolved-symbols=ignore-in-shared-libs 2>&1 | \
+# RUN:   FileCheck -check-prefix=ERRUND %s
+## And should not produce errors for symbols from DSO.
+# RUN: ld.lld %t1.o %t.so -o %t3_1 --unresolved-symbols=ignore-in-shared-libs
+# RUN: llvm-readobj %t3_1 > /dev/null 2>&1
+
+## Ignoring undefines in shared libs should not produce error for symbol from object
+## if we are linking DSO.
+# RUN: ld.lld -shared %t1.o -o %t4 --unresolved-symbols=ignore-in-shared-libs
+# RUN: llvm-readobj %t4 > /dev/null 2>&1
+
+## Do not report undefines if linking relocatable.
+# 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
+# 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 %t7 --unresolved-symbols=report-all 2>&1 | \
+# RUN:   FileCheck -check-prefix=ERRUND %s
+# RUN: not ld.lld %t2.o -o %t7_1 2>&1 | \
+# RUN:   FileCheck -check-prefix=ERRUND %s
+
+.globl _start
+_start:




More information about the llvm-commits mailing list