[lld] r350105 - [ELF] A shared object is needed if any of its occurrences is needed

Fangrui Song via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 27 14:24:45 PST 2018


Author: maskray
Date: Thu Dec 27 14:24:45 2018
New Revision: 350105

URL: http://llvm.org/viewvc/llvm-project?rev=350105&view=rev
Log:
[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

Modified:
    lld/trunk/ELF/SymbolTable.cpp
    lld/trunk/ELF/SymbolTable.h
    lld/trunk/test/ELF/as-needed-not-in-regular.s

Modified: lld/trunk/ELF/SymbolTable.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.cpp?rev=350105&r1=350104&r2=350105&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.cpp (original)
+++ lld/trunk/ELF/SymbolTable.cpp Thu Dec 27 14:24:45 2018
@@ -94,8 +94,20 @@ template <class ELFT> void SymbolTable::
   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;

Modified: lld/trunk/ELF/SymbolTable.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SymbolTable.h?rev=350105&r1=350104&r2=350105&view=diff
==============================================================================
--- lld/trunk/ELF/SymbolTable.h (original)
+++ lld/trunk/ELF/SymbolTable.h Thu Dec 27 14:24:45 2018
@@ -108,7 +108,7 @@ private:
   llvm::DenseSet<llvm::CachedHashStringRef> ComdatGroups;
 
   // Set of .so files to not link the same shared object file more than once.
-  llvm::DenseSet<StringRef> SoNames;
+  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

Modified: lld/trunk/test/ELF/as-needed-not-in-regular.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/as-needed-not-in-regular.s?rev=350105&r1=350104&r2=350105&view=diff
==============================================================================
--- lld/trunk/test/ELF/as-needed-not-in-regular.s (original)
+++ lld/trunk/test/ELF/as-needed-not-in-regular.s Thu Dec 27 14:24:45 2018
@@ -19,6 +19,12 @@
 # the reference to a2 is weak, don't add a DT_NEEDED entry for a.so.
 # CHECK-NOT: a.so
 
+# RUN: ld.lld %t.o %tb.so --as-needed %ta.so --no-as-needed %ta.so -o %t
+# RUN: llvm-readelf -d %t | FileCheck %s -check-prefix=NEEDED
+
+# a.so is needed because one of its occurrences is needed.
+# NEEDED: a.so
+
 .global _start
 .weak a2
 _start:




More information about the llvm-commits mailing list