summaryrefslogtreecommitdiffstats
path: root/lld/ELF/SymbolTable.cpp
diff options
context:
space:
mode:
authorFangrui Song <maskray@google.com>2018-12-27 22:24:45 +0000
committerFangrui Song <maskray@google.com>2018-12-27 22:24:45 +0000
commit50394f6e018fd347ae1ccb86f0ec0180ec5f7e33 (patch)
treed1f51a20a9f76e6ffcfb74b40d7e9c29bc5a0c56 /lld/ELF/SymbolTable.cpp
parent1ce7fccbc902779992f7d7b71944caeb4c16968d (diff)
downloadbcm5719-llvm-50394f6e018fd347ae1ccb86f0ec0180ec5f7e33.tar.gz
bcm5719-llvm-50394f6e018fd347ae1ccb86f0ec0180ec5f7e33.zip
[ELF] A shared object is needed if any of its occurrences is needed
Summary: If a DSO appears more than once with and without --as-needed, ld.bfd and gold consider --no-as-needed to takes precedence over --as-needed. lld didn't and this patch makes it do so. This makes it a bit away from the position-dependent behavior (how different occurrences of the same DSO interact) and protects us from some mysterious runtime errors: if some interceptor libraries add their own --no-as-needed dependencies (e.g. librt.so), and the user application specifies -Wl,--as-needed -lrt , the absence of the DT_NEEDED entry would make dlsym(RTLD_NEXT, "clock_gettime") return NULL and would break at runtime. Reviewers: ruiu, espindola Reviewed By: ruiu Subscribers: emaste, arichardson, llvm-commits Differential Revision: https://reviews.llvm.org/D56089 llvm-svn: 350105
Diffstat (limited to 'lld/ELF/SymbolTable.cpp')
-rw-r--r--lld/ELF/SymbolTable.cpp14
1 files changed, 13 insertions, 1 deletions
diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp
index ba746375e3e..7615e12199f 100644
--- a/lld/ELF/SymbolTable.cpp
+++ b/lld/ELF/SymbolTable.cpp
@@ -94,8 +94,20 @@ template <class ELFT> void SymbolTable::addFile(InputFile *File) {
if (auto *F = dyn_cast<SharedFile<ELFT>>(File)) {
// DSOs are uniquified not by filename but by soname.
F->parseSoName();
- if (errorCount() || !SoNames.insert(F->SoName).second)
+ if (errorCount())
return;
+
+ // If a DSO appears more than once on the command line with and without
+ // --as-needed, --no-as-needed takes precedence over --as-needed because a
+ // user can add an extra DSO with --no-as-needed to force it to be added to
+ // the dependency list.
+ DenseMap<StringRef, InputFile *>::iterator It;
+ bool WasInserted;
+ std::tie(It, WasInserted) = SoNames.try_emplace(F->SoName, F);
+ cast<SharedFile<ELFT>>(It->second)->IsNeeded |= F->IsNeeded;
+ if (!WasInserted)
+ return;
+
SharedFiles.push_back(F);
F->parseRest();
return;
OpenPOWER on IntegriCloud