@@ -1689,6 +1689,73 @@ void ElfFile<ElfFileParamNames>::addDebugTag()
16891689 changed = true ;
16901690}
16911691
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+
16921759template <ElfFileParams>
16931760void ElfFile<ElfFileParamNames>::clearSymbolVersions(const std::set<std::string> & syms)
16941761{
@@ -1714,6 +1781,10 @@ void ElfFile<ElfFileParamNames>::clearSymbolVersions(const std::set<std::string>
17141781 wri (versyms[i], 1 );
17151782 }
17161783 }
1784+
1785+ /* Remove entries in the .gnu.versions_r table which are no;-longer required. */
1786+ cleanDependencySymbolVersions ();
1787+
17171788 changed = true ;
17181789 this ->rewriteSections ();
17191790}
@@ -1797,9 +1868,9 @@ static void patchElf()
17971868 const std::string & outputFileName2 = outputFileName.empty () ? fileName : outputFileName;
17981869
17991870 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);
18011872 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);
18031874 }
18041875}
18051876
0 commit comments