forked from OSchip/llvm-project
[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 llvm-svn: 274123
This commit is contained in:
parent
e5b3aebfb5
commit
e86dcd0cbd
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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">;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
.globl _shared
|
||||
_shared:
|
||||
callq undef@PLT
|
||||
|
|
@ -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:
|
||||
Loading…
Reference in New Issue