@@ -1689,6 +1689,73 @@ void ElfFile<ElfFileParamNames>::addDebugTag()
1689
1689
changed = true ;
1690
1690
}
1691
1691
1692
+ /* Remove any unused dependency symbol versions from .gnu.version_r */
1693
+ template <ElfFileParams>
1694
+ void ElfFile<ElfFileParamNames>::cleanDependencySymbolVersions()
1695
+ {
1696
+ auto shdrVersym = findSectionHeader (" .gnu.version" );
1697
+ auto shdrVersymR = findSectionHeader (" .gnu.version_r" );
1698
+
1699
+ auto versyms = (Elf_Versym *)(fileContents->data () + rdi (shdrVersym.sh_offset ));
1700
+ size_t count = rdi (shdrVersym.sh_size ) / sizeof (Elf_Versym);
1701
+
1702
+ /* Set of versions actually used. */
1703
+ std::set<Elf_Versym> allVersions;
1704
+
1705
+ for (size_t i = 0 ; i < count; i++) {
1706
+ allVersions.insert (versyms[i]);
1707
+ }
1708
+
1709
+ /* Strings associated with .gnu_version_r section: used for debug only. */
1710
+ Elf_Shdr & shdrVersionRStrings = shdrs.at (rdi (shdrVersymR.sh_link ));
1711
+ char * verStrTab = (char *) fileContents->data () + rdi (shdrVersionRStrings.sh_offset );
1712
+
1713
+
1714
+ auto ver_r = (Elf_Verneed *)(fileContents->data () + rdi (shdrVersymR.sh_offset ));
1715
+ while (true ) {
1716
+ auto prev = (Elf_Vernaux *)nullptr ;
1717
+ auto vern_aux = (Elf_Vernaux *)((char *)ver_r + rdi (ver_r->vn_aux ));
1718
+ char * file = verStrTab + rdi (ver_r->vn_file );
1719
+ for (size_t j = 0 ; j < ver_r->vn_cnt ; j++) {
1720
+ char * ver_name = verStrTab + rdi (vern_aux->vna_name );
1721
+ auto next = (Elf_Vernaux *)((char *)vern_aux + rdi (vern_aux->vna_next ));
1722
+
1723
+ if (!allVersions.count (rdi (vern_aux->vna_other ) & ~0x8000 )) {
1724
+ debug (" Removing version identifier %d %s@%s\n " , rdi (vern_aux->vna_other ), file, ver_name);
1725
+ /* Symbol version is no longer used, unlink it. */
1726
+ if (!prev) {
1727
+ auto next_off = (intptr_t )(vern_aux) + rdi (vern_aux->vna_next ) - (intptr_t )(ver_r);
1728
+ wri (ver_r->vn_aux , next_off);
1729
+ } else {
1730
+ auto next_off = (intptr_t )(vern_aux) + rdi (vern_aux->vna_next ) - (intptr_t )(prev);
1731
+ wri (prev->vna_next , next_off);
1732
+ }
1733
+ wri (ver_r->vn_cnt , rdi (ver_r->vn_cnt ) - 1 );
1734
+ } else {
1735
+ prev = vern_aux;
1736
+ }
1737
+
1738
+ if (vern_aux == next) {
1739
+ if (j != rdi (ver_r->vn_cnt )) {
1740
+ debug (" Section missing elements! Ended on element %d, expected %d\n " , j, rdi (ver_r->vn_cnt ));
1741
+ }
1742
+ break ;
1743
+ }
1744
+ vern_aux = next;
1745
+ }
1746
+
1747
+ /* If this was the last entry, we're done. */
1748
+ if (!rdi (ver_r->vn_next )) {
1749
+ break ;
1750
+ }
1751
+
1752
+ ver_r = (Elf_Verneed *) (((char *) ver_r) + rdi (ver_r->vn_next ));
1753
+ }
1754
+
1755
+ changed = true ;
1756
+ this ->rewriteSections ();
1757
+ }
1758
+
1692
1759
template <ElfFileParams>
1693
1760
void ElfFile<ElfFileParamNames>::clearSymbolVersions(const std::set<std::string> & syms)
1694
1761
{
@@ -1714,6 +1781,10 @@ void ElfFile<ElfFileParamNames>::clearSymbolVersions(const std::set<std::string>
1714
1781
wri (versyms[i], 1 );
1715
1782
}
1716
1783
}
1784
+
1785
+ /* Remove entries in the .gnu.versions_r table which are no;-longer required. */
1786
+ cleanDependencySymbolVersions ();
1787
+
1717
1788
changed = true ;
1718
1789
this ->rewriteSections ();
1719
1790
}
@@ -1797,9 +1868,9 @@ static void patchElf()
1797
1868
const std::string & outputFileName2 = outputFileName.empty () ? fileName : outputFileName;
1798
1869
1799
1870
if (getElfType (fileContents).is32Bit )
1800
- patchElf2 (ElfFile<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Addr, Elf32_Off, Elf32_Dyn, Elf32_Sym, Elf32_Verneed, Elf32_Versym>(fileContents), fileContents, outputFileName2);
1871
+ patchElf2 (ElfFile<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Addr, Elf32_Off, Elf32_Dyn, Elf32_Sym, Elf32_Verneed, Elf32_Vernaux, Elf32_Versym>(fileContents), fileContents, outputFileName2);
1801
1872
else
1802
- patchElf2 (ElfFile<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Addr, Elf64_Off, Elf64_Dyn, Elf64_Sym, Elf64_Verneed, Elf64_Versym>(fileContents), fileContents, outputFileName2);
1873
+ patchElf2 (ElfFile<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Addr, Elf64_Off, Elf64_Dyn, Elf64_Sym, Elf64_Verneed, Elf64_Vernaux, Elf64_Versym>(fileContents), fileContents, outputFileName2);
1803
1874
}
1804
1875
}
1805
1876
0 commit comments