@@ -1538,7 +1538,7 @@ void ElfFile<ElfFileParamNames>::modifyRPath(RPathOp op,
15381538
15391539 /* !!! We assume that the virtual address in the DT_STRTAB entry
15401540 of the dynamic section corresponds to the .dynstr section. */
1541- auto shdrDynStr = findSectionHeader (" .dynstr" );
1541+ auto & shdrDynStr = findSectionHeader (" .dynstr" );
15421542 char * strTab = (char *) fileContents->data () + rdi (shdrDynStr.sh_offset );
15431543
15441544
@@ -1621,24 +1621,39 @@ void ElfFile<ElfFileParamNames>::modifyRPath(RPathOp op,
16211621 }
16221622 changed = true ;
16231623
1624- /* Zero out the previous rpath to prevent retained dependencies in
1625- Nix. */
1624+ bool rpathStrShared = false ;
16261625 size_t rpathSize = 0 ;
16271626 if (rpath) {
1628- rpathSize = strlen (rpath);
1627+ std::string_view rpathView {rpath};
1628+ rpathSize = rpathView.size ();
1629+
1630+ size_t rpathStrReferences = 0 ;
1631+ forAllStringReferences (shdrDynStr, [&] (auto refIdx) {
1632+ if (rpathView.end () == std::string_view (strTab + rdi (refIdx)).end ())
1633+ rpathStrReferences++;
1634+ });
1635+ assert (rpathStrReferences >= 1 );
1636+ debug (" Number of rpath references: %lu\n " , rpathStrReferences);
1637+ rpathStrShared = rpathStrReferences > 1 ;
1638+ }
1639+
1640+ /* Zero out the previous rpath to prevent retained dependencies in
1641+ Nix. */
1642+ if (rpath && !rpathStrShared) {
1643+ debug (" Tainting old rpath with Xs\n " );
16291644 memset (rpath, ' X' , rpathSize);
16301645 }
16311646
16321647 debug (" new rpath is '%s'\n " , newRPath.c_str ());
16331648
16341649
1635- if (newRPath.size () <= rpathSize) {
1650+ if (!rpathStrShared && newRPath.size () <= rpathSize) {
16361651 if (rpath) memcpy (rpath, newRPath.c_str (), newRPath.size () + 1 );
16371652 return ;
16381653 }
16391654
16401655 /* Grow the .dynstr section to make room for the new RPATH. */
1641- debug (" rpath is too long, resizing...\n " );
1656+ debug (" rpath is too long or shared , resizing...\n " );
16421657
16431658 std::string & newDynStr = replaceSection (" .dynstr" ,
16441659 rdi (shdrDynStr.sh_size ) + newRPath.size () + 1 );
@@ -2295,7 +2310,7 @@ void ElfFile<ElfFileParamNames>::modifyExecstack(ExecstackMode op)
22952310
22962311template <ElfFileParams>
22972312template <class StrIdxCallback >
2298- void ElfFile<ElfFileParamNames>::forAllStringReferences(Elf_Shdr& strTabHdr, StrIdxCallback&& fn)
2313+ void ElfFile<ElfFileParamNames>::forAllStringReferences(const Elf_Shdr& strTabHdr, StrIdxCallback&& fn)
22992314{
23002315 for (auto & sym : tryGetSectionSpan<Elf_Sym>(" .dynsym" ))
23012316 fn (sym.st_name );
0 commit comments