Index: include/lld/Core/Resolver.h =================================================================== --- include/lld/Core/Resolver.h +++ include/lld/Core/Resolver.h @@ -14,6 +14,7 @@ #include "lld/Core/SharedLibraryFile.h" #include "lld/Core/SymbolTable.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include @@ -105,6 +106,7 @@ std::set _deadStripRoots; llvm::DenseSet _liveAtoms; std::unique_ptr _result; + llvm::DenseMap> _reverseRef; }; } // namespace lld Index: lib/Core/Resolver.cpp =================================================================== --- lib/Core/Resolver.cpp +++ lib/Core/Resolver.cpp @@ -312,10 +312,18 @@ return; // Mark all atoms it references as live - if (const DefinedAtom *defAtom = dyn_cast(&atom)) + if (const DefinedAtom *defAtom = dyn_cast(&atom)) { for (const Reference *ref : *defAtom) if (const Atom *target = ref->target()) markLive(*target); + for (const Atom *target : _reverseRef[defAtom]) + markLive(*target); + } +} + +static bool isBackref(const Reference *ref) { + return ref->kindNamespace() == lld::Reference::KindNamespace::all && + ref->kindValue() == lld::Reference::kindLayoutBefore; } // remove all atoms not actually used @@ -324,7 +332,14 @@ // only do this optimization with -dead_strip if (!_context.deadStrip()) return; - assert(_liveAtoms.empty()); + + // Some type of references prevent referring atoms to be dead-striped. + // Make a reverse map of such references before traversing the graph. + for (const Atom *atom : _atoms) + if (const DefinedAtom *defAtom = dyn_cast(atom)) + for (const Reference *ref : *defAtom) + if (isBackref(ref)) + _reverseRef[ref->target()].insert(atom); // By default, shared libraries are built with all globals as dead strip roots if (_context.globalsAreDeadStripRoots()) Index: test/core/dead-strip-reverse.objtxt =================================================================== --- /dev/null +++ test/core/dead-strip-reverse.objtxt @@ -0,0 +1,25 @@ +# RUN: lld -core --dead-strip %s | FileCheck -check-prefix=CHECK1 %s +# RUN: lld -core %s | FileCheck -check-prefix=CHECK2 %s + +--- +defined-atoms: + - name: entry + dead-strip: never + scope: global + references: + - kind: layout-after + offset: 0 + target: def + - name: def + scope: global + - name: dead + scope: global +... + +# CHECK1: name: entry +# CHECK1: name: def +# CHECK1-NOT: name: dead + +# CHECK2: name: entry +# CHECK2: name: def +# CHECK2: name: dead