|
28 | 28 | #include <string>
|
29 | 29 | #include <unordered_map>
|
30 | 30 | #include <unordered_set>
|
| 31 | +#include <variant> |
31 | 32 | #include <vector>
|
32 | 33 |
|
33 | 34 | #include <cassert>
|
@@ -1855,7 +1856,78 @@ void ElfFile<ElfFileParamNames>::noDefaultLib()
|
1855 | 1856 | template<ElfFileParams>
|
1856 | 1857 | void ElfFile<ElfFileParamNames>::cleanStrTab()
|
1857 | 1858 | {
|
| 1859 | + std::unordered_map<std::string, unsigned> requiredStrs2Idx {{"",0}}; |
1858 | 1860 |
|
| 1861 | + // A collection of pointers to the fields that refer to str indices |
| 1862 | + // and a pointer to the new index value to be calculated |
| 1863 | + using StrIndexPtr = std::variant<Elf32_Word*, Elf64_Xword*>; |
| 1864 | + std::vector<std::pair<StrIndexPtr, unsigned*>> strRefs; |
| 1865 | + |
| 1866 | + auto& strTabHdr = findSectionHeader(".dynstr"); |
| 1867 | + auto strTab = getSectionSpan<char>(strTabHdr); |
| 1868 | + |
| 1869 | + // Utility to collect a string index field from any table |
| 1870 | + auto collect = [&] (auto& idx) { |
| 1871 | + auto [it, _] = requiredStrs2Idx.emplace(&strTab[rdi(idx)], 0); |
| 1872 | + strRefs.emplace_back(&idx, &it->second); |
| 1873 | + }; |
| 1874 | + |
| 1875 | + // Iterate on tables known to store references to .dynstr |
| 1876 | + for (auto& sym : tryGetSectionSpan<Elf_Sym>(".dynsym")) |
| 1877 | + collect(sym.st_name); |
| 1878 | + |
| 1879 | + for (auto& dyn : tryGetSectionSpan<Elf_Dyn>(".dynamic")) |
| 1880 | + switch (rdi(dyn.d_tag)) |
| 1881 | + { |
| 1882 | + case DT_NEEDED: |
| 1883 | + case DT_SONAME: |
| 1884 | + case DT_RPATH: |
| 1885 | + case DT_RUNPATH: collect(dyn.d_un.d_val); |
| 1886 | + default:; |
| 1887 | + } |
| 1888 | + |
| 1889 | + if (auto verdHdr = tryFindSectionHeader(".gnu.version_d")) |
| 1890 | + { |
| 1891 | + // Only collect fields if they use the strtab we are cleaning |
| 1892 | + if (&shdrs.at(rdi(verdHdr->get().sh_link)) == &strTabHdr) |
| 1893 | + forAll_ElfVer(getSectionSpan<Elf_Verdef>(*verdHdr), |
| 1894 | + [] (auto& vd) {}, |
| 1895 | + [&] (auto& vda) { collect(vda.vda_name); } |
| 1896 | + ); |
| 1897 | + } |
| 1898 | + |
| 1899 | + if (auto vernHdr = tryFindSectionHeader(".gnu.version_r")) |
| 1900 | + { |
| 1901 | + // Only collect fields if they use the strtab we are cleaning |
| 1902 | + if (&shdrs.at(rdi(vernHdr->get().sh_link)) == &strTabHdr) |
| 1903 | + forAll_ElfVer(getSectionSpan<Elf_Verneed>(*vernHdr), |
| 1904 | + [&] (auto& vn) { collect(vn.vn_file); }, |
| 1905 | + [&] (auto& vna) { collect(vna.vna_name); } |
| 1906 | + ); |
| 1907 | + } |
| 1908 | + |
| 1909 | + // Iterate on all required strings calculating the new position |
| 1910 | + size_t curIdx = 1; |
| 1911 | + for (auto& [str,idx] : requiredStrs2Idx) |
| 1912 | + { |
| 1913 | + idx = curIdx; |
| 1914 | + curIdx += str.size()+1; |
| 1915 | + } |
| 1916 | + |
| 1917 | + // Add required strings to the new dynstr section |
| 1918 | + auto& newStrSec = replaceSection(".dynstr", curIdx); |
| 1919 | + for (auto& [str,idx] : requiredStrs2Idx) |
| 1920 | + std::copy(str.begin(), str.end()+1, newStrSec.begin()+idx); |
| 1921 | + |
| 1922 | + // Iterate on all fields on all tables setting the new index value |
| 1923 | + for (auto& [oldIndexPtr, newIdxPtr] : strRefs) |
| 1924 | + std::visit( |
| 1925 | + [&] (auto* ptr) { wri(*ptr, *newIdxPtr); }, |
| 1926 | + oldIndexPtr |
| 1927 | + ); |
| 1928 | + |
| 1929 | + changed = true; |
| 1930 | + this->rewriteSections(); |
1859 | 1931 | }
|
1860 | 1932 |
|
1861 | 1933 | template<ElfFileParams>
|
@@ -2230,9 +2302,9 @@ static void patchElf()
|
2230 | 2302 | const std::string & outputFileName2 = outputFileName.empty() ? fileName : outputFileName;
|
2231 | 2303 |
|
2232 | 2304 | if (getElfType(fileContents).is32Bit)
|
2233 |
| - 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); |
| 2305 | + 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); |
2234 | 2306 | else
|
2235 |
| - 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); |
| 2307 | + 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); |
2236 | 2308 | }
|
2237 | 2309 | }
|
2238 | 2310 |
|
|
0 commit comments