diff options
| -rw-r--r-- | lld/ELF/Config.h | 5 | ||||
| -rw-r--r-- | lld/ELF/Driver.cpp | 24 | ||||
| -rw-r--r-- | lld/ELF/Options.td | 3 | ||||
| -rw-r--r-- | lld/ELF/Writer.cpp | 14 | ||||
| -rw-r--r-- | lld/test/ELF/Inputs/unresolved-symbols.s | 3 | ||||
| -rw-r--r-- | lld/test/ELF/unresolved-symbols.s | 63 | 
6 files changed, 100 insertions, 12 deletions
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index 703dedfaa2a..a12ff35c4cd 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -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; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index e614db02673..c8041e0db65 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -296,6 +296,25 @@ void LinkerDriver::main(ArrayRef<const char *> ArgsArr) {    }  } +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::InputArgList &Args) {    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::InputArgList &Args) {    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); diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td index c224eef5752..857e620ad8e 100644 --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -150,6 +150,9 @@ def trace_symbol : J<"trace-symbol=">, HelpText<"Trace references to symbols">;  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">; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 323a791c3de..28036d3dbeb 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -275,17 +275,17 @@ template <bool Is64Bits> struct DenseMapInfo<SectionKey<Is64Bits>> {  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); diff --git a/lld/test/ELF/Inputs/unresolved-symbols.s b/lld/test/ELF/Inputs/unresolved-symbols.s new file mode 100644 index 00000000000..b504708e43d --- /dev/null +++ b/lld/test/ELF/Inputs/unresolved-symbols.s @@ -0,0 +1,3 @@ +.globl _shared +_shared: +  callq undef@PLT diff --git a/lld/test/ELF/unresolved-symbols.s b/lld/test/ELF/unresolved-symbols.s new file mode 100644 index 00000000000..2fa59cb0ffd --- /dev/null +++ b/lld/test/ELF/unresolved-symbols.s @@ -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:  | 

