@@ -1709,6 +1709,73 @@ void ElfFile<ElfFileParamNames>::addDebugTag()
17091709 changed = true ;
17101710}
17111711
1712+ /* Remove any unused dependency symbol versions from .gnu.version_r */
1713+ template <ElfFileParams>
1714+ void ElfFile<ElfFileParamNames>::cleanDependencySymbolVersions()
1715+ {
1716+ auto shdrVersym = findSectionHeader (" .gnu.version" );
1717+ auto shdrVersymR = findSectionHeader (" .gnu.version_r" );
1718+
1719+ auto versyms = (Elf_Versym *)(fileContents->data () + rdi (shdrVersym.sh_offset ));
1720+ size_t count = rdi (shdrVersym.sh_size ) / sizeof (Elf_Versym);
1721+
1722+ /* Set of versions actually used. */
1723+ std::set<Elf_Versym> allVersions;
1724+
1725+ for (size_t i = 0 ; i < count; i++) {
1726+ allVersions.insert (versyms[i]);
1727+ }
1728+
1729+ /* Strings associated with .gnu_version_r section: used for debug only. */
1730+ Elf_Shdr & shdrVersionRStrings = shdrs.at (rdi (shdrVersymR.sh_link ));
1731+ char * verStrTab = (char *) fileContents->data () + rdi (shdrVersionRStrings.sh_offset );
1732+
1733+
1734+ auto ver_r = (Elf_Verneed *)(fileContents->data () + rdi (shdrVersymR.sh_offset ));
1735+ while (true ) {
1736+ auto prev = (Elf_Vernaux *)nullptr ;
1737+ auto vern_aux = (Elf_Vernaux *)((char *)ver_r + rdi (ver_r->vn_aux ));
1738+ char * file = verStrTab + rdi (ver_r->vn_file );
1739+ for (size_t j = 0 ; j < ver_r->vn_cnt ; j++) {
1740+ char * ver_name = verStrTab + rdi (vern_aux->vna_name );
1741+ auto next = (Elf_Vernaux *)((char *)vern_aux + rdi (vern_aux->vna_next ));
1742+
1743+ if (!allVersions.count (rdi (vern_aux->vna_other ) & ~0x8000 )) {
1744+ debug (" Removing version identifier %d %s@%s\n " , rdi (vern_aux->vna_other ), file, ver_name);
1745+ /* Symbol version is no longer used, unlink it. */
1746+ if (!prev) {
1747+ auto next_off = (intptr_t )(vern_aux) + rdi (vern_aux->vna_next ) - (intptr_t )(ver_r);
1748+ wri (ver_r->vn_aux , next_off);
1749+ } else {
1750+ auto next_off = (intptr_t )(vern_aux) + rdi (vern_aux->vna_next ) - (intptr_t )(prev);
1751+ wri (prev->vna_next , next_off);
1752+ }
1753+ wri (ver_r->vn_cnt , rdi (ver_r->vn_cnt ) - 1 );
1754+ } else {
1755+ prev = vern_aux;
1756+ }
1757+
1758+ if (vern_aux == next) {
1759+ if (j != rdi (ver_r->vn_cnt )) {
1760+ debug (" Section missing elements! Ended on element %d, expected %d\n " , j, rdi (ver_r->vn_cnt ));
1761+ }
1762+ break ;
1763+ }
1764+ vern_aux = next;
1765+ }
1766+
1767+ /* If this was the last entry, we're done. */
1768+ if (!rdi (ver_r->vn_next )) {
1769+ break ;
1770+ }
1771+
1772+ ver_r = (Elf_Verneed *) (((char *) ver_r) + rdi (ver_r->vn_next ));
1773+ }
1774+
1775+ changed = true ;
1776+ this ->rewriteSections ();
1777+ }
1778+
17121779template <ElfFileParams>
17131780void ElfFile<ElfFileParamNames>::clearSymbolVersions(const std::set<std::string> & syms)
17141781{
@@ -1734,6 +1801,10 @@ void ElfFile<ElfFileParamNames>::clearSymbolVersions(const std::set<std::string>
17341801 wri (versyms[i], 1 );
17351802 }
17361803 }
1804+
1805+ /* Remove entries in the .gnu.versions_r table which are no;-longer required. */
1806+ cleanDependencySymbolVersions ();
1807+
17371808 changed = true ;
17381809 this ->rewriteSections ();
17391810}
@@ -1817,9 +1888,9 @@ static void patchElf()
18171888 const std::string & outputFileName2 = outputFileName.empty () ? fileName : outputFileName;
18181889
18191890 if (getElfType (fileContents).is32Bit )
1820- patchElf2 (ElfFile<Elf32_Ehdr, Elf32_Phdr, Elf32_Shdr, Elf32_Addr, Elf32_Off, Elf32_Dyn, Elf32_Sym, Elf32_Verneed, Elf32_Versym>(fileContents), fileContents, outputFileName2);
1891+ 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);
18211892 else
1822- patchElf2 (ElfFile<Elf64_Ehdr, Elf64_Phdr, Elf64_Shdr, Elf64_Addr, Elf64_Off, Elf64_Dyn, Elf64_Sym, Elf64_Verneed, Elf64_Versym>(fileContents), fileContents, outputFileName2);
1893+ 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);
18231894 }
18241895}
18251896
0 commit comments