diff options
author | James Henderson <jh7370@my.bristol.ac.uk> | 2018-02-14 13:36:22 +0000 |
---|---|---|
committer | James Henderson <jh7370@my.bristol.ac.uk> | 2018-02-14 13:36:22 +0000 |
commit | de300e66bbff85c70a9e69d536f10488c899ef9f (patch) | |
tree | 815619f88fe8daa2cda95dac6ccca2ec54382ce4 | |
parent | 9ce703335623db8c6ff7c039a951ca6572e11eb3 (diff) | |
download | bcm5719-llvm-de300e66bbff85c70a9e69d536f10488c899ef9f.tar.gz bcm5719-llvm-de300e66bbff85c70a9e69d536f10488c899ef9f.zip |
[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
llvm-svn: 325125
-rw-r--r-- | lld/ELF/Config.h | 1 | ||||
-rw-r--r-- | lld/ELF/Driver.cpp | 15 | ||||
-rw-r--r-- | lld/ELF/Options.td | 4 | ||||
-rw-r--r-- | lld/ELF/Writer.cpp | 47 | ||||
-rw-r--r-- | lld/test/ELF/Inputs/symbol-ordering-file-warnings1.s | 19 | ||||
-rw-r--r-- | lld/test/ELF/Inputs/symbol-ordering-file-warnings2.s | 6 | ||||
-rw-r--r-- | lld/test/ELF/symbol-ordering-file-warnings.s | 140 |
7 files changed, 224 insertions, 8 deletions
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index 21e81e48201..e759a19c550 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -152,6 +152,7 @@ struct Configuration { bool UndefinedVersion; bool WarnCommon; bool WarnMissingEntry; + bool WarnSymbolOrdering; bool WriteAddends; bool ZCombreloc; bool ZExecstack; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 25740a6863e..e1bac230b8d 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -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::Arg *Arg) { 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::InputArgList &Args) { 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::InputArgList &Args) { 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. diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td index e92c6af646f..56fda2294a1 100644 --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -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">; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 0e7b877fa0c..bc21c59e78c 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -1022,25 +1022,58 @@ static DenseMap<const InputSectionBase *, int> buildSectionOrder() { 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; } diff --git a/lld/test/ELF/Inputs/symbol-ordering-file-warnings1.s b/lld/test/ELF/Inputs/symbol-ordering-file-warnings1.s new file mode 100644 index 00000000000..9250a6d4270 --- /dev/null +++ b/lld/test/ELF/Inputs/symbol-ordering-file-warnings1.s @@ -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",@progbits,comdat,comdat +.weak comdat +comdat: + ret + +.section .text.glob_or_wk,"ax",@progbits +.global glob_or_wk +glob_or_wk: + ret diff --git a/lld/test/ELF/Inputs/symbol-ordering-file-warnings2.s b/lld/test/ELF/Inputs/symbol-ordering-file-warnings2.s new file mode 100644 index 00000000000..4d914b240f1 --- /dev/null +++ b/lld/test/ELF/Inputs/symbol-ordering-file-warnings2.s @@ -0,0 +1,6 @@ +.text +.global missing +missing: + callq undefined + # This is a "bad" (undefined) instance of the symbol + callq multi diff --git a/lld/test/ELF/symbol-ordering-file-warnings.s b/lld/test/ELF/symbol-ordering-file-warnings.s new file mode 100644 index 00000000000..788707f4abb --- /dev/null +++ b/lld/test/ELF/symbol-ordering-file-warnings.s @@ -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",@progbits +.global gc +gc: + nop + +.section .text.discard,"ax",@progbits +.global discard +discard: + nop + +.section .text.comdat,"axG",@progbits,comdat,comdat +.weak comdat +comdat: + nop + +.section .text.glob_or_wk,"ax",@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 |