Index: include/lld/Core/LinkingContext.h =================================================================== --- include/lld/Core/LinkingContext.h +++ include/lld/Core/LinkingContext.h @@ -29,6 +29,14 @@ class Node; class SharedLibraryFile; +enum UnresolvedSymbols : uint8_t { + DEFAULT = 0, + REPORT_ALL = 1, + IGNORE_ALL = 2, + IGNORE_IN_OBJECT_FILES = 3, + IGNORE_IN_SHARED_LIBS = 4, +}; + /// \brief The LinkingContext class encapsulates "what and how" to link. /// /// The base class LinkingContext contains the options needed by core linking. @@ -149,6 +157,12 @@ /// to be an error. bool allowShlibUndefines() const { return _allowShlibUndefines; } + /// Normally, every UndefinedAtom must be replaced by a DefinedAtom or a + /// SharedLibraryAtom for the link to be successful. This method controls + /// whether core linking considers remaining undefines from the shared library + /// and executable to be an error. + UnresolvedSymbols unresolvedSymbols() { return _unresolvedSymbols; } + /// If true, core linking will write the path to each input file to stdout /// (i.e. llvm::outs()) as it is used. This is used to implement the -t /// linker option. @@ -197,6 +211,7 @@ _allowRemainingUndefines = allow; } void setAllowShlibUndefines(bool allow) { _allowShlibUndefines = allow; } + void setUnresolvedSymbols(UnresolvedSymbols value) { _unresolvedSymbols = value; } void setLogInputFiles(bool log) { _logInputFiles = log; } // Returns true if multiple definitions should not be treated as a @@ -340,6 +355,7 @@ bool _allowRemainingUndefines; bool _logInputFiles; bool _allowShlibUndefines; + UnresolvedSymbols _unresolvedSymbols; OutputFileType _outputFileType; std::vector _deadStripRoots; std::map _aliasSymbols; Index: lib/Core/LinkingContext.cpp =================================================================== --- lib/Core/LinkingContext.cpp +++ lib/Core/LinkingContext.cpp @@ -25,6 +25,7 @@ _warnIfCoalesableAtomsHaveDifferentLoadName(false), _printRemainingUndefines(true), _allowRemainingUndefines(false), _logInputFiles(false), _allowShlibUndefines(true), + _unresolvedSymbols(UnresolvedSymbols::DEFAULT), _outputFileType(OutputFileType::Default), _nextOrdinal(0) {} LinkingContext::~LinkingContext() {} Index: lib/Core/Resolver.cpp =================================================================== --- lib/Core/Resolver.cpp +++ lib/Core/Resolver.cpp @@ -452,6 +452,28 @@ if (undef->canBeNull() != UndefinedAtom::canBeNullNever) continue; + switch (_ctx.unresolvedSymbols()) { + case UnresolvedSymbols::IGNORE_ALL: + case UnresolvedSymbols::IGNORE_IN_OBJECT_FILES: + // IGNORE_ALL: skip over the undefined symbols for executable + // IGNORE_IN_OBJECT_FILES: if the unresolved symbol is from shared + // library report it but if it is from a regular object file then + // skip over it + if (!isa(undef->file())) + continue; + break; + + case UnresolvedSymbols::IGNORE_IN_SHARED_LIBS: + // if the unresolved symbol is from shared library skip over it + // But if it is from a regular object file then report it + if (isa(undef->file()) && _ctx.allowShlibUndefines()) + continue; + break; + + default: + break; + } + // If this is a library and undefined symbols are allowed on the // target platform, skip over it. if (isa(undef->file()) && _ctx.allowShlibUndefines()) Index: lib/Driver/GnuLdDriver.cpp =================================================================== --- lib/Driver/GnuLdDriver.cpp +++ lib/Driver/GnuLdDriver.cpp @@ -426,6 +426,48 @@ ctx->setAllowRemainingUndefines(true); } + // Handle --unresolved-symbols option + if (auto *arg = parsedArgs.getLastArg(OPT_unresolved_symbols)) { + StringRef val = arg->getValue(); + if (val.empty()) { + diag << "error: option --unresolved-symbols=" + " must take one of the following arguments:\n" + "\tignore-all, report-all, " + "ignore-in-shared-libs, ignore-in-object-files\n"; + return false; + } + else if (val.compare("ignore-all") && + val.compare("report-all") && + val.compare("ignore-in-object-files") && + val.compare("ignore-in-shared-libs")) { + + diag << "error: option --unresolved-symbols=" + << val + << " must take one of the following arguments:\n" + "\tignore-all, report-all, " + "ignore-in-shared-libs, ignore-in-object-files\n"; + return false; + } + + if (!val.compare("report-all")) { + ctx->setUnresolvedSymbols(UnresolvedSymbols::REPORT_ALL); + ctx->setAllowShlibUndefines(false); + } + else if (!val.compare("ignore-all")) { + ctx->setUnresolvedSymbols(UnresolvedSymbols::IGNORE_ALL); + } + else if (!val.compare("ignore-in-object-files")) { + ctx->setUnresolvedSymbols(UnresolvedSymbols::IGNORE_IN_OBJECT_FILES); + ctx->setAllowShlibUndefines(false); + } + else if (!val.compare("ignore-in-shared-libs")) { + ctx->setUnresolvedSymbols(UnresolvedSymbols::IGNORE_IN_SHARED_LIBS); + } + + ctx->setPrintRemainingUndefines(true); + ctx->setAllowRemainingUndefines(false); + } + // Handle --stats. if (parsedArgs.hasArg(OPT_stats)) { ctx->setCollectStats(true); Index: lib/Driver/GnuLdOptions.td =================================================================== --- lib/Driver/GnuLdOptions.td +++ lib/Driver/GnuLdOptions.td @@ -220,6 +220,11 @@ def allow_multiple_definition: Flag<["--"], "allow-multiple-definition">, HelpText<"Allow multiple definitions">, Group; +def unresolved_symbols: Joined<["--"], "unresolved-symbols=">, + HelpText<"control reporting unresolved symbols">, + Group; +def unresolved_symbols_alias : Joined<["--"], "unresolved-symbols">, + Alias; defm defsym : mDashEq<"defsym", "Create a global symbol in the output file " "containing the absolute address given by expression">, Index: test/elf/unresolved-symbols.test =================================================================== --- test/elf/unresolved-symbols.test +++ test/elf/unresolved-symbols.test @@ -0,0 +1,127 @@ +# +# This test creates a executable and tests the options that are used to +# to create an executable and a shared library +# +# This test will fail because there are unresolved symbols from the shared +# library and we are passing --no-allow-shlib-undefined +# Test if option is used in correct form +RUN: lld -flavor gnu -shared %p/Inputs/foo_unresolved-symbols.o -o %p/Inputs/libfoo_unresolved-symbols.so + +RUN: not lld -flavor gnu %p/Inputs/main_unresolved-symbols.o -o %t --unresolved-symbols 2> %t4 +RUN: FileCheck -check-prefix=ERROR %s < %t4 +RUN: FileCheck -check-prefix=OPTIONS %s < %t4 + +# Test if option is used in correct form +RUN: not lld -flavor gnu %p/Inputs/main_unresolved-symbols.o -o %t --unresolved-symbols= 2> %t4 +RUN: FileCheck -check-prefix=ERROR %s < %t4 +RUN: FileCheck -check-prefix=OPTIONS %s < %t4 + +# Test if option value used is correct +RUN: not lld -flavor gnu %p/Inputs/main_unresolved-symbols.o -o %t --unresolved-symbols=abcd 2> %t4 +RUN: FileCheck -check-prefix=ERROR1 %s < %t4 +RUN: FileCheck -check-prefix=OPTIONS %s < %t4 + +# Test behaviour of --unresolved-symbols=report-all +RUN: not lld -flavor gnu %p/Inputs/main_unresolved-symbols.o -e main \ +RUN: %p/Inputs/libfoo_unresolved-symbols.so -o %t --unresolved-symbols=report-all 2> %t1 +RUN: FileCheck -check-prefix=UNDEFINED-SHLIB %s < %t1 +RUN: FileCheck -check-prefix=UNDEFINED-EXEC %s < %t1 + +# Test behaviour of --unresolved-symbols=ignore-all +RUN: lld -flavor gnu %p/Inputs/main_unresolved-symbols.o -e main \ +RUN: %p/Inputs/libfoo_unresolved-symbols.so -o %t --unresolved-symbols=ignore-all 2> %t2 + +# Test behaviour of --unresolved-symbols=ignore-in-object-files +RUN: not lld -flavor gnu %p/Inputs/main_unresolved-symbols.o -e main \ +RUN: %p/Inputs/libfoo_unresolved-symbols.so -o %t --unresolved-symbols=ignore-in-object-files 2> %t2 +RUN: FileCheck -check-prefix=UNDEFINED-SHLIB %s < %t2 + +# Test behaviour of --unresolved-symbols=ignore-in-shared-libs +RUN: not lld -flavor gnu %p/Inputs/main_unresolved-symbols.o -e main \ +RUN: %p/Inputs/libfoo_unresolved-symbols.so -o %t --unresolved-symbols=ignore-in-shared-libs 2> %t3 +RUN: FileCheck -check-prefix=UNDEFINED-EXEC %s < %t3 + +# Test behaviour of --unresolved-symbols=report-all +# along with --allow-shlib-undefined +RUN: not lld -flavor gnu %p/Inputs/main_unresolved-symbols.o -e main \ +RUN: %p/Inputs/libfoo_unresolved-symbols.so -o %t --unresolved-symbols=report-all \ +RUN: --allow-shlib-undefined 2> %t1 +RUN: FileCheck -check-prefix=UNDEFINED-EXEC %s < %t1 + +# Test behaviour of --unresolved-symbols=ignore-all +# along with --allow-shlib-undefined +RUN: lld -flavor gnu %p/Inputs/main_unresolved-symbols.o -e main \ +RUN: %p/Inputs/libfoo_unresolved-symbols.so -o %t --unresolved-symbols=ignore-all \ +RUN: --allow-shlib-undefined 2> %t2 + +# Test behaviour of --unresolved-symbols=ignore-in-object-files +# along with --allow-shlib-undefined +RUN: lld -flavor gnu %p/Inputs/main_unresolved-symbols.o -e main \ +RUN: %p/Inputs/libfoo_unresolved-symbols.so -o %t --unresolved-symbols=ignore-in-object-files \ +RUN: --allow-shlib-undefined 2> %t2 + +# Test behaviour of --unresolved-symbols=ignore-in-shared-libs +# along with --allow-shlib-undefined +RUN: not lld -flavor gnu %p/Inputs/main_unresolved-symbols.o -e main \ +RUN: %p/Inputs/libfoo_unresolved-symbols.so -o %t --unresolved-symbols=ignore-in-shared-libs \ +RUN: --allow-shlib-undefined 2> %t3 +RUN: FileCheck -check-prefix=UNDEFINED-EXEC %s < %t3 + +# Test behaviour of --unresolved-symbols=report-all +# along with --no-allow-shlib-undefined +RUN: not lld -flavor gnu %p/Inputs/main_unresolved-symbols.o -e main \ +RUN: %p/Inputs/libfoo_unresolved-symbols.so -o %t --unresolved-symbols=report-all \ +RUN: --no-allow-shlib-undefined 2> %t1 +RUN: FileCheck -check-prefix=UNDEFINED-SHLIB %s < %t1 +RUN: FileCheck -check-prefix=UNDEFINED-EXEC %s < %t1 + +# Test behaviour of --unresolved-symbols=ignore-all +# along with --no-allow-shlib-undefined +RUN: not lld -flavor gnu %p/Inputs/main_unresolved-symbols.o -e main \ +RUN: %p/Inputs/libfoo_unresolved-symbols.so -o %t --unresolved-symbols=ignore-all \ +RUN: --no-allow-shlib-undefined 2> %t1 +RUN: FileCheck -check-prefix=UNDEFINED-SHLIB %s < %t1 + +# Test behaviour of --unresolved-symbols=ignore-in-object-files +# along with --no-allow-shlib-undefined +RUN: not lld -flavor gnu %p/Inputs/main_unresolved-symbols.o -e main %p/Inputs/libfoo_unresolved-symbols.so -o %t \ +RUN: --unresolved-symbols=ignore-in-object-files --no-allow-shlib-undefined 2> %t2 +RUN: FileCheck -check-prefix=UNDEFINED-SHLIB %s < %t2 + +# Test behaviour of --unresolved-symbols=ignore-in-shared-libs +# along with --no-allow-shlib-undefined +RUN: not lld -flavor gnu %p/Inputs/main_unresolved-symbols.o -e main \ +RUN: %p/Inputs/libfoo_unresolved-symbols.so -o %t --unresolved-symbols=ignore-in-shared-libs \ +RUN: --no-allow-shlib-undefined 2> %t3 +RUN: FileCheck -check-prefix=UNDEFINED-EXEC %s < %t3 +RUN: FileCheck -check-prefix=UNDEFINED-SHLIB %s < %t3 + +# Test behaviour of --unresolved-symbols=report-all +# along with -shared +RUN: not lld -flavor gnu -shared -fpic %p/Inputs/foo_unresolved-symbols.o -o %t \ +RUN: --unresolved-symbols=report-all 2> %t3 +RUN: FileCheck -check-prefix=UNDEFINED-OBJ %s < %t3 + +# Test behaviour of --unresolved-symbols=ignore-all +# along with -shared +RUN: lld -flavor gnu -shared -fpic %p/Inputs/foo_unresolved-symbols.o -o %t \ +RUN: --unresolved-symbols=ignore-all 2> %t3 + +# Test behaviour of --unresolved-symbols=ignore-in-object-files +# along with -shared +RUN: lld -flavor gnu -shared -fpic %p/Inputs/foo_unresolved-symbols.o -o %t \ +RUN: --unresolved-symbols=ignore-in-object-files 2> %t3 + +# Test behaviour of --unresolved-symbols=ignore-in-shared-libs +# along with -shared +RUN: not lld -flavor gnu -shared -fpic %p/Inputs/foo_unresolved-symbols.o -o %t \ +RUN: --unresolved-symbols=ignore-in-shared-libs 2> %t3 +RUN: FileCheck -check-prefix=UNDEFINED-OBJ %s < %t3 + +ERROR: error: option --unresolved-symbols= must take one of the following arguments: +ERROR1: error: option --unresolved-symbols=abcd must take one of the following arguments: +OPTIONS: ignore-all, report-all, ignore-in-shared-libs, ignore-in-object-files +UNDEFINED-SHLIB: Undefined symbol: {{.+[\\/]}}libfoo_unresolved-symbols.so: bar +UNDEFINED-OBJ: Undefined symbol: {{.+[\\/]}}foo_unresolved-symbols.o: bar +UNDEFINED-EXEC: Undefined symbol: {{.+[\\/]}}main_unresolved-symbols.o: goo +