aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm/tools
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-03-20 20:57:11 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-03-20 20:57:11 +0000
commitc3e6b9d390489e2b8ecba74f4732438c31806d22 (patch)
tree89b02879f8d7ce6afd3fc73bfe3617102f0283b5 /contrib/llvm/tools
parent7114b1763ca4da5a97b13b1244860b2efbb08735 (diff)
downloadsrc-c3e6b9d390489e2b8ecba74f4732438c31806d22.tar.gz
src-c3e6b9d390489e2b8ecba74f4732438c31806d22.zip
Notes
Diffstat (limited to 'contrib/llvm/tools')
-rw-r--r--contrib/llvm/tools/lld/ELF/Config.h1
-rw-r--r--contrib/llvm/tools/lld/ELF/Driver.cpp3
-rw-r--r--contrib/llvm/tools/lld/ELF/InputFiles.cpp12
-rw-r--r--contrib/llvm/tools/lld/ELF/InputFiles.h6
-rw-r--r--contrib/llvm/tools/lld/ELF/Options.td6
-rw-r--r--contrib/llvm/tools/lld/ELF/SymbolTable.cpp2
-rw-r--r--contrib/llvm/tools/lld/ELF/SymbolTable.h6
-rw-r--r--contrib/llvm/tools/lld/ELF/Writer.cpp21
-rw-r--r--contrib/llvm/tools/lld/docs/ld.lld.16
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