Also demote lazy symbols.
authorRafael Espindola <rafael.espindola@gmail.com>
Wed, 25 Apr 2018 20:46:08 +0000 (20:46 +0000)
committerRafael Espindola <rafael.espindola@gmail.com>
Wed, 25 Apr 2018 20:46:08 +0000 (20:46 +0000)
This is not a big simplification right now, but the special cases for
lazy symbols have been a common source of bugs in the past.

llvm-svn: 330869

lld/ELF/Driver.cpp
lld/ELF/Symbols.cpp
lld/ELF/Symbols.h

index c14d6d3..208649f 100644 (file)
@@ -1119,19 +1119,27 @@ 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() {
+template <class ELFT> static bool shouldDemote(Symbol &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.
+  if (auto *S = dyn_cast<SharedSymbol>(&Sym))
+    return !S->getFile<ELFT>().IsNeeded;
+
+  // We are done processing archives, so lazy symbols that were used but not
+  // found can be converted to undefined. We could also just delete the other
+  // lazy symbols, but that seems to be more work than it is worth.
+  return Sym.isLazy() && Sym.IsUsedInRegularObj;
+}
+
+template <class ELFT> static void demoteSymbols() {
   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;
-      }
+    if (shouldDemote<ELFT>(*Sym)) {
+      bool Used = Sym->Used;
+      replaceSymbol<Undefined>(Sym, nullptr, Sym->getName(), Sym->Binding,
+                               Sym->StOther, Sym->Type);
+      Sym->Used = Used;
     }
   }
 }
@@ -1296,7 +1304,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>();
+  demoteSymbols<ELFT>();
   decompressSections();
   mergeSections();
   if (Config->ICF)
index 77155b9..d3935f6 100644 (file)
@@ -109,8 +109,7 @@ static uint64_t getSymVA(const Symbol &Sym, int64_t &Addend) {
     return 0;
   case Symbol::LazyArchiveKind:
   case Symbol::LazyObjectKind:
-    assert(Sym.IsUsedInRegularObj && "lazy symbol reached writer");
-    return 0;
+    llvm_unreachable("lazy symbol reached writer");
   }
   llvm_unreachable("invalid symbol kind");
 }
index cab32dc..5a2c65d 100644 (file)
@@ -95,12 +95,8 @@ public:
     return SymbolKind == LazyArchiveKind || SymbolKind == LazyObjectKind;
   }
 
-  // True if this is an undefined weak symbol. This only works once
-  // all input files have been added.
-  bool isUndefWeak() const {
-    // See comment on lazy symbols for details.
-    return isWeak() && (isUndefined() || isLazy());
-  }
+  // True if this is an undefined weak symbol.
+  bool isUndefWeak() const { return isWeak() && isUndefined(); }
 
   StringRef getName() const { return Name; }
   void parseSymbolVersion();