diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-03-20 20:57:11 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-03-20 20:57:11 +0000 |
commit | c3e6b9d390489e2b8ecba74f4732438c31806d22 (patch) | |
tree | 89b02879f8d7ce6afd3fc73bfe3617102f0283b5 /contrib/llvm/tools | |
parent | 7114b1763ca4da5a97b13b1244860b2efbb08735 (diff) | |
download | src-c3e6b9d390489e2b8ecba74f4732438c31806d22.tar.gz src-c3e6b9d390489e2b8ecba74f4732438c31806d22.zip |
Notes
Diffstat (limited to 'contrib/llvm/tools')
-rw-r--r-- | contrib/llvm/tools/lld/ELF/Config.h | 1 | ||||
-rw-r--r-- | contrib/llvm/tools/lld/ELF/Driver.cpp | 3 | ||||
-rw-r--r-- | contrib/llvm/tools/lld/ELF/InputFiles.cpp | 12 | ||||
-rw-r--r-- | contrib/llvm/tools/lld/ELF/InputFiles.h | 6 | ||||
-rw-r--r-- | contrib/llvm/tools/lld/ELF/Options.td | 6 | ||||
-rw-r--r-- | contrib/llvm/tools/lld/ELF/SymbolTable.cpp | 2 | ||||
-rw-r--r-- | contrib/llvm/tools/lld/ELF/SymbolTable.h | 6 | ||||
-rw-r--r-- | contrib/llvm/tools/lld/ELF/Writer.cpp | 21 | ||||
-rw-r--r-- | contrib/llvm/tools/lld/docs/ld.lld.1 | 6 |
9 files changed, 52 insertions, 11 deletions
diff --git a/contrib/llvm/tools/lld/ELF/Config.h b/contrib/llvm/tools/lld/ELF/Config.h index fb29396926bf..e8bb6bf70ee0 100644 --- a/contrib/llvm/tools/lld/ELF/Config.h +++ b/contrib/llvm/tools/lld/ELF/Config.h @@ -122,6 +122,7 @@ struct Configuration { uint64_t> CallGraphProfile; bool AllowMultipleDefinition; + bool AllowShlibUndefined; bool AndroidPackDynRelocs; bool ARMHasBlx = false; bool ARMHasMovtMovw = false; diff --git a/contrib/llvm/tools/lld/ELF/Driver.cpp b/contrib/llvm/tools/lld/ELF/Driver.cpp index 407f1734f143..3e565bcb8732 100644 --- a/contrib/llvm/tools/lld/ELF/Driver.cpp +++ b/contrib/llvm/tools/lld/ELF/Driver.cpp @@ -758,6 +758,9 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) { Args.hasFlag(OPT_allow_multiple_definition, OPT_no_allow_multiple_definition, false) || hasZOption(Args, "muldefs"); + Config->AllowShlibUndefined = + Args.hasFlag(OPT_allow_shlib_undefined, OPT_no_allow_shlib_undefined, + Args.hasArg(OPT_shared)); Config->AuxiliaryList = args::getStrings(Args, OPT_auxiliary); Config->Bsymbolic = Args.hasArg(OPT_Bsymbolic); Config->BsymbolicFunctions = Args.hasArg(OPT_Bsymbolic_functions); diff --git a/contrib/llvm/tools/lld/ELF/InputFiles.cpp b/contrib/llvm/tools/lld/ELF/InputFiles.cpp index bc7e61072e64..c5922d3155d9 100644 --- a/contrib/llvm/tools/lld/ELF/InputFiles.cpp +++ b/contrib/llvm/tools/lld/ELF/InputFiles.cpp @@ -865,7 +865,7 @@ SharedFile<ELFT>::SharedFile(MemoryBufferRef M, StringRef DefaultSoName) // Partially parse the shared object file so that we can call // getSoName on this object. -template <class ELFT> void SharedFile<ELFT>::parseSoName() { +template <class ELFT> void SharedFile<ELFT>::parseDynamic() { const Elf_Shdr *DynamicSec = nullptr; const ELFFile<ELFT> Obj = this->getObj(); ArrayRef<Elf_Shdr> Sections = CHECK(Obj.sections(), this); @@ -902,12 +902,16 @@ template <class ELFT> void SharedFile<ELFT>::parseSoName() { ArrayRef<Elf_Dyn> Arr = CHECK(Obj.template getSectionContentsAsArray<Elf_Dyn>(DynamicSec), this); for (const Elf_Dyn &Dyn : Arr) { - if (Dyn.d_tag == DT_SONAME) { + if (Dyn.d_tag == DT_NEEDED) { + uint64_t Val = Dyn.getVal(); + if (Val >= this->StringTable.size()) + fatal(toString(this) + ": invalid DT_NEEDED entry"); + DtNeeded.push_back(this->StringTable.data() + Val); + } else if (Dyn.d_tag == DT_SONAME) { uint64_t Val = Dyn.getVal(); if (Val >= this->StringTable.size()) fatal(toString(this) + ": invalid DT_SONAME entry"); SoName = this->StringTable.data() + Val; - return; } } } @@ -975,7 +979,7 @@ uint32_t SharedFile<ELFT>::getAlignment(ArrayRef<Elf_Shdr> Sections, return (Ret > UINT32_MAX) ? 0 : Ret; } -// Fully parse the shared object file. This must be called after parseSoName(). +// Fully parse the shared object file. This must be called after parseDynamic(). // // This function parses symbol versions. If a DSO has version information, // the file has a ".gnu.version_d" section which contains symbol version diff --git a/contrib/llvm/tools/lld/ELF/InputFiles.h b/contrib/llvm/tools/lld/ELF/InputFiles.h index d7cbbc67a365..db9097fb868e 100644 --- a/contrib/llvm/tools/lld/ELF/InputFiles.h +++ b/contrib/llvm/tools/lld/ELF/InputFiles.h @@ -323,6 +323,7 @@ template <class ELFT> class SharedFile : public ELFFileBase<ELFT> { public: std::vector<const Elf_Verdef *> Verdefs; + std::vector<StringRef> DtNeeded; std::string SoName; static bool classof(const InputFile *F) { @@ -331,7 +332,7 @@ public: SharedFile(MemoryBufferRef M, StringRef DefaultSoName); - void parseSoName(); + void parseDynamic(); void parseRest(); uint32_t getAlignment(ArrayRef<Elf_Shdr> Sections, const Elf_Sym &Sym); std::vector<const Elf_Verdef *> parseVerdefs(); @@ -349,6 +350,9 @@ public: // data structures in the output file. std::map<const Elf_Verdef *, NeededVer> VerdefMap; + // Used for --no-allow-shlib-undefined. + bool AllNeededIsKnown; + // Used for --as-needed bool IsNeeded; }; diff --git a/contrib/llvm/tools/lld/ELF/Options.td b/contrib/llvm/tools/lld/ELF/Options.td index 439fe341644c..3a19b230780a 100644 --- a/contrib/llvm/tools/lld/ELF/Options.td +++ b/contrib/llvm/tools/lld/ELF/Options.td @@ -63,6 +63,10 @@ defm allow_multiple_definition: B<"allow-multiple-definition", "Allow multiple definitions", "Do not allow multiple definitions (default)">; +defm allow_shlib_undefined: B<"allow-shlib-undefined", + "Allow unresolved references in shared libraries (default when linking a shared library)", + "Do not allow unresolved references in shared libraries (default when linking an executable)">; + defm apply_dynamic_relocs: B<"apply-dynamic-relocs", "Apply link-time values for dynamic relocations", "Do not apply link-time values for dynamic relocations (default)">; @@ -492,12 +496,10 @@ def plugin_opt_thinlto: J<"plugin-opt=thinlto">; def plugin_opt_slash: J<"plugin-opt=/">; // Options listed below are silently ignored for now for compatibility. -def: F<"allow-shlib-undefined">; def: F<"detect-odr-violations">; def: Flag<["-"], "g">; def: F<"long-plt">; def: F<"no-add-needed">; -def: F<"no-allow-shlib-undefined">; def: F<"no-copy-dt-needed-entries">; def: F<"no-ctors-in-init-array">; def: F<"no-keep-memory">; diff --git a/contrib/llvm/tools/lld/ELF/SymbolTable.cpp b/contrib/llvm/tools/lld/ELF/SymbolTable.cpp index 7615e12199fa..bf1bf4511e96 100644 --- a/contrib/llvm/tools/lld/ELF/SymbolTable.cpp +++ b/contrib/llvm/tools/lld/ELF/SymbolTable.cpp @@ -93,7 +93,7 @@ template <class ELFT> void SymbolTable::addFile(InputFile *File) { // .so file if (auto *F = dyn_cast<SharedFile<ELFT>>(File)) { // DSOs are uniquified not by filename but by soname. - F->parseSoName(); + F->parseDynamic(); if (errorCount()) return; diff --git a/contrib/llvm/tools/lld/ELF/SymbolTable.h b/contrib/llvm/tools/lld/ELF/SymbolTable.h index 898185fc9612..675a4915598f 100644 --- a/contrib/llvm/tools/lld/ELF/SymbolTable.h +++ b/contrib/llvm/tools/lld/ELF/SymbolTable.h @@ -80,6 +80,9 @@ public: void handleDynamicList(); + // Set of .so files to not link the same shared object file more than once. + llvm::DenseMap<StringRef, InputFile *> SoNames; + private: std::pair<Symbol *, bool> insertName(StringRef Name); @@ -107,9 +110,6 @@ private: // is used to uniquify them. llvm::DenseSet<llvm::CachedHashStringRef> ComdatGroups; - // Set of .so files to not link the same shared object file more than once. - llvm::DenseMap<StringRef, InputFile *> SoNames; - // A map from demangled symbol names to their symbol objects. // This mapping is 1:N because two symbols with different versions // can have the same name. We use this map to handle "extern C++ {}" diff --git a/contrib/llvm/tools/lld/ELF/Writer.cpp b/contrib/llvm/tools/lld/ELF/Writer.cpp index 5c987ca5a813..dcabf52e64f3 100644 --- a/contrib/llvm/tools/lld/ELF/Writer.cpp +++ b/contrib/llvm/tools/lld/ELF/Writer.cpp @@ -1668,6 +1668,27 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { if (In.Iplt && !In.Iplt->empty()) In.Iplt->addSymbols(); + if (!Config->AllowShlibUndefined) { + // Error on undefined symbols in a shared object, if all of its DT_NEEDED + // entires are seen. These cases would otherwise lead to runtime errors + // reported by the dynamic linker. + // + // ld.bfd traces all DT_NEEDED to emulate the logic of the dynamic linker to + // catch more cases. That is too much for us. Our approach resembles the one + // used in ld.gold, achieves a good balance to be useful but not too smart. + for (InputFile *File : SharedFiles) { + SharedFile<ELFT> *F = cast<SharedFile<ELFT>>(File); + F->AllNeededIsKnown = llvm::all_of(F->DtNeeded, [&](StringRef Needed) { + return Symtab->SoNames.count(Needed); + }); + } + for (Symbol *Sym : Symtab->getSymbols()) + if (Sym->isUndefined() && !Sym->isWeak()) + if (auto *F = dyn_cast_or_null<SharedFile<ELFT>>(Sym->File)) + if (F->AllNeededIsKnown) + error(toString(F) + ": undefined reference to " + toString(*Sym)); + } + // Now that we have defined all possible global symbols including linker- // synthesized ones. Visit all symbols to give the finishing touches. for (Symbol *Sym : Symtab->getSymbols()) { diff --git a/contrib/llvm/tools/lld/docs/ld.lld.1 b/contrib/llvm/tools/lld/docs/ld.lld.1 index 04bf19d6b23c..6fd746f030dd 100644 --- a/contrib/llvm/tools/lld/docs/ld.lld.1 +++ b/contrib/llvm/tools/lld/docs/ld.lld.1 @@ -56,6 +56,9 @@ option. .It Fl -allow-multiple-definition Do not error if a symbol is defined multiple times. The first definition will be used. +.It Fl -allow-shlib-undefined +Allow unresolved references in shared libraries. +This option is enabled by default when linking a shared library. .It Fl -apply-dynamic-relocs Apply link-time values for dynamic relocations. .It Fl -as-needed @@ -252,6 +255,9 @@ Set target emulation. .It Fl -Map Ns = Ns Ar file , Fl M Ar file Print a link map to .Ar file . +.It Fl -no-allow-shlib-undefined +Do not allow unresolved references in shared libraries. +This option is enabled by default when linking an executable. .It Fl -no-as-needed Always set .Dv DT_NEEDED |