diff options
Diffstat (limited to 'lld/ELF/Driver.cpp')
-rw-r--r-- | lld/ELF/Driver.cpp | 18 |
1 files changed, 18 insertions, 0 deletions
diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 4bfef2f4f8e..c14d6d31000 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -1119,6 +1119,23 @@ template <class ELFT> static void handleUndefined(StringRef Name) { Symtab->fetchLazy<ELFT>(Sym); } +// If all references to a DSO happen to be weak, the DSO is not added +// to DT_NEEDED. If that happens, we need to eliminate shared symbols +// created from the DSO. Otherwise, they become dangling references +// that point to a non-existent DSO. +template <class ELFT> static void demoteSharedSymbols() { + for (Symbol *Sym : Symtab->getSymbols()) { + if (auto *S = dyn_cast<SharedSymbol>(Sym)) { + if (!S->getFile<ELFT>().IsNeeded) { + bool Used = S->Used; + replaceSymbol<Undefined>(S, nullptr, S->getName(), STB_WEAK, S->StOther, + S->Type); + S->Used = Used; + } + } + } +} + // Do actual linking. Note that when this function is called, // all linker scripts have already been parsed. template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) { @@ -1279,6 +1296,7 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) { // Do size optimizations: garbage collection, merging of SHF_MERGE sections // and identical code folding. markLive<ELFT>(); + demoteSharedSymbols<ELFT>(); decompressSections(); mergeSections(); if (Config->ICF) |