@@ -664,14 +664,14 @@ template<ElfFileParams>
664
664
void ElfFile<ElfFileParamNames>::writeReplacedSections(Elf_Off & curOff,
665
665
Elf_Addr startAddr, Elf_Off startOffset)
666
666
{
667
- /* Overwrite the old section contents with 'X 's. Do this
667
+ /* Overwrite the old section contents with 'Z 's. Do this
668
668
*before* writing the new section contents (below) to prevent
669
669
clobbering previously written new section contents. */
670
670
for (auto & i : replacedSections) {
671
671
const std::string & sectionName = i.first ;
672
672
const Elf_Shdr & shdr = findSectionHeader (sectionName);
673
673
if (rdi (shdr.sh_type ) != SHT_NOBITS)
674
- memset (fileContents->data () + rdi (shdr.sh_offset ), ' X ' , rdi (shdr.sh_size ));
674
+ memset (fileContents->data () + rdi (shdr.sh_offset ), ' Z ' , rdi (shdr.sh_size ));
675
675
}
676
676
677
677
std::set<unsigned int > noted_phdrs = {};
@@ -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 );
@@ -2293,6 +2308,42 @@ void ElfFile<ElfFileParamNames>::modifyExecstack(ExecstackMode op)
2293
2308
printf (" execstack: %c\n " , result);
2294
2309
}
2295
2310
2311
+ template <ElfFileParams>
2312
+ template <class StrIdxCallback >
2313
+ void ElfFile<ElfFileParamNames>::forAllStringReferences(const Elf_Shdr& strTabHdr, StrIdxCallback&& fn)
2314
+ {
2315
+ for (auto & sym : tryGetSectionSpan<Elf_Sym>(" .dynsym" ))
2316
+ fn (sym.st_name );
2317
+
2318
+ for (auto & dyn : tryGetSectionSpan<Elf_Dyn>(" .dynamic" ))
2319
+ switch (rdi (dyn.d_tag ))
2320
+ {
2321
+ case DT_NEEDED:
2322
+ case DT_SONAME:
2323
+ case DT_RPATH:
2324
+ case DT_RUNPATH: fn (dyn.d_un .d_val );
2325
+ default :;
2326
+ }
2327
+
2328
+ if (auto verdHdr = tryFindSectionHeader (" .gnu.version_d" ))
2329
+ {
2330
+ if (&shdrs.at (rdi (verdHdr->get ().sh_link )) == &strTabHdr)
2331
+ forAll_ElfVer (getSectionSpan<Elf_Verdef>(*verdHdr),
2332
+ [] (auto & /* vd*/ ) {},
2333
+ [&] (auto & vda) { fn (vda.vda_name ); }
2334
+ );
2335
+ }
2336
+
2337
+ if (auto vernHdr = tryFindSectionHeader (" .gnu.version_r" ))
2338
+ {
2339
+ if (&shdrs.at (rdi (vernHdr->get ().sh_link )) == &strTabHdr)
2340
+ forAll_ElfVer (getSectionSpan<Elf_Verneed>(*vernHdr),
2341
+ [&] (auto & vn) { fn (vn.vn_file ); },
2342
+ [&] (auto & vna) { fn (vna.vna_name ); }
2343
+ );
2344
+ }
2345
+ }
2346
+
2296
2347
static bool printInterpreter = false ;
2297
2348
static bool printOsAbi = false ;
2298
2349
static bool setOsAbi = false ;
@@ -2397,9 +2448,9 @@ static void patchElf()
2397
2448
const std::string & outputFileName2 = outputFileName.empty () ? fileName : outputFileName;
2398
2449
2399
2450
if (getElfType (fileContents).is32Bit )
2400
- patchElf2 (ElfFile<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Addr, Elf32_Off, Elf32_Dyn, Elf32_Sym, Elf32_Verneed, Elf32_Versym , Elf32_Rel, Elf32_Rela, 32 >(fileContents), fileContents, outputFileName2);
2451
+ patchElf2 (ElfFile<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Addr, Elf32_Off, Elf32_Dyn, Elf32_Sym, Elf32_Versym, Elf32_Verdef, Elf32_Verdaux, Elf32_Verneed, Elf32_Vernaux , Elf32_Rel, Elf32_Rela, 32 >(fileContents), fileContents, outputFileName2);
2401
2452
else
2402
- patchElf2 (ElfFile<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Addr, Elf64_Off, Elf64_Dyn, Elf64_Sym, Elf64_Verneed, Elf64_Versym , Elf64_Rel, Elf64_Rela, 64 >(fileContents), fileContents, outputFileName2);
2453
+ patchElf2 (ElfFile<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Addr, Elf64_Off, Elf64_Dyn, Elf64_Sym, Elf64_Versym, Elf64_Verdef, Elf64_Verdaux, Elf64_Verneed, Elf64_Vernaux , Elf64_Rel, Elf64_Rela, 64 >(fileContents), fileContents, outputFileName2);
2403
2454
}
2404
2455
}
2405
2456
0 commit comments