Index: lld/ELF/MarkLive.cpp =================================================================== --- lld/ELF/MarkLive.cpp +++ lld/ELF/MarkLive.cpp @@ -301,6 +301,15 @@ // Follow the graph to mark all live sections. doGcSections(); + // If all references to a DSO happen to be weak, the DSO is removed from + // DT_NEEDED, which creates dangling shared symbols to non-existent DSO. + // We'll replace such symbols with undefined ones to fix it. + for (Symbol *Sym : Symtab->getSymbols()) + if (auto *S = dyn_cast(Sym)) + if (S->isWeak() && !S->getFile().IsNeeded) + replaceSymbol(S, nullptr, S->getName(), STB_WEAK, S->StOther, + S->Type); + // Report garbage-collected sections. if (Config->PrintGcSections) for (InputSectionBase *Sec : InputSections) Index: lld/test/ELF/gc-sections-shared.s =================================================================== --- lld/test/ELF/gc-sections-shared.s +++ lld/test/ELF/gc-sections-shared.s @@ -9,11 +9,6 @@ # RUN: ld.lld --gc-sections --export-dynamic-symbol foo -o %t %t.o --as-needed %t2.so %t3.so %t4.so # RUN: llvm-readobj --dynamic-table --dyn-symbols %t | FileCheck %s -# This test the property that we have a needed line for every undefined. -# It would also be OK to keep bar2 and the need for %t2.so -# At the same time, weak symbols should not cause adding DT_NEEDED; -# this case is checked with symbol qux and %t4.so. - # CHECK: DynamicSymbols [ # CHECK-NEXT: Symbol { # CHECK-NEXT: Name: @@ -51,15 +46,6 @@ # CHECK-NEXT: Other: # CHECK-NEXT: Section: .text # CHECK-NEXT: } -# CHECK-NEXT: Symbol { -# CHECK-NEXT: Name: qux -# CHECK-NEXT: Value: -# CHECK-NEXT: Size: -# CHECK-NEXT: Binding: Weak -# CHECK-NEXT: Type: -# CHECK-NEXT: Other: -# CHECK-NEXT: Section: Undefined -# CHECK-NEXT: } # CHECK-NEXT: ] # CHECK-NOT: NEEDED @@ -99,15 +85,6 @@ # CHECK2-NEXT: Section: Undefined # CHECK2-NEXT: } # CHECK2-NEXT: Symbol { -# CHECK2-NEXT: Name: qux -# CHECK2-NEXT: Value: -# CHECK2-NEXT: Size: -# CHECK2-NEXT: Binding: Weak -# CHECK2-NEXT: Type: -# CHECK2-NEXT: Other: -# CHECK2-NEXT: Section: Undefined -# CHECK2-NEXT: } -# CHECK2-NEXT: Symbol { # CHECK2-NEXT: Name: foo # CHECK2-NEXT: Value: # CHECK2-NEXT: Size: