@@ -1538,7 +1538,7 @@ void ElfFile<ElfFileParamNames>::modifyRPath(RPathOp op,
1538
1538
1539
1539
/* !!! We assume that the virtual address in the DT_STRTAB entry
1540
1540
of the dynamic section corresponds to the .dynstr section. */
1541
- auto shdrDynStr = findSectionHeader (" .dynstr" );
1541
+ auto & shdrDynStr = findSectionHeader (" .dynstr" );
1542
1542
char * strTab = (char *) fileContents->data () + rdi (shdrDynStr.sh_offset );
1543
1543
1544
1544
@@ -1621,24 +1621,39 @@ void ElfFile<ElfFileParamNames>::modifyRPath(RPathOp op,
1621
1621
}
1622
1622
changed = true ;
1623
1623
1624
- /* Zero out the previous rpath to prevent retained dependencies in
1625
- Nix. */
1624
+ bool rpathStrShared = false ;
1626
1625
size_t rpathSize = 0 ;
1627
1626
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 " );
1629
1644
memset (rpath, ' X' , rpathSize);
1630
1645
}
1631
1646
1632
1647
debug (" new rpath is '%s'\n " , newRPath.c_str ());
1633
1648
1634
1649
1635
- if (newRPath.size () <= rpathSize) {
1650
+ if (!rpathStrShared && newRPath.size () <= rpathSize) {
1636
1651
if (rpath) memcpy (rpath, newRPath.c_str (), newRPath.size () + 1 );
1637
1652
return ;
1638
1653
}
1639
1654
1640
1655
/* 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 " );
1642
1657
1643
1658
std::string & newDynStr = replaceSection (" .dynstr" ,
1644
1659
rdi (shdrDynStr.sh_size ) + newRPath.size () + 1 );
@@ -2295,7 +2310,7 @@ void ElfFile<ElfFileParamNames>::modifyExecstack(ExecstackMode op)
2295
2310
2296
2311
template <ElfFileParams>
2297
2312
template <class StrIdxCallback >
2298
- void ElfFile<ElfFileParamNames>::forAllStringReferences(Elf_Shdr& strTabHdr, StrIdxCallback&& fn)
2313
+ void ElfFile<ElfFileParamNames>::forAllStringReferences(const Elf_Shdr& strTabHdr, StrIdxCallback&& fn)
2299
2314
{
2300
2315
for (auto & sym : tryGetSectionSpan<Elf_Sym>(" .dynsym" ))
2301
2316
fn (sym.st_name );
0 commit comments