summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBreno Rodrigues Guimaraes <brenorg@gmail.com>2023-03-17 17:55:32 -0300
committerBreno Rodrigues Guimaraes <brenorg@gmail.com>2023-03-17 19:06:57 -0300
commit75e4daaf29f10d2b31be4991507bfa0673b4e9e4 (patch)
tree0b437b6f76a9a9894890a4e05f46e13925e091f8
parentc749f6760d69f6594a8b84ba8ab195d838766d89 (diff)
downloadpatchelf-75e4daaf29f10d2b31be4991507bfa0673b4e9e4.tar.gz
Add infrastructure to iterate on all objects that are string indexes
-rw-r--r--src/patchelf.cc40
-rw-r--r--src/patchelf.h38
2 files changed, 74 insertions, 4 deletions
diff --git a/src/patchelf.cc b/src/patchelf.cc
index 37e6479..f2f9043 100644
--- a/src/patchelf.cc
+++ b/src/patchelf.cc
@@ -2293,6 +2293,42 @@ void ElfFile<ElfFileParamNames>::modifyExecstack(ExecstackMode op)
printf("execstack: %c\n", result);
}
+template<ElfFileParams>
+template<class StrIdxCallback>
+void ElfFile<ElfFileParamNames>::forAllStringReferences(Elf_Shdr& strTabHdr, StrIdxCallback&& fn)
+{
+ for (auto& sym : tryGetSectionSpan<Elf_Sym>(".dynsym"))
+ fn(sym.st_name);
+
+ for (auto& dyn : tryGetSectionSpan<Elf_Dyn>(".dynamic"))
+ switch (rdi(dyn.d_tag))
+ {
+ case DT_NEEDED:
+ case DT_SONAME:
+ case DT_RPATH:
+ case DT_RUNPATH: fn(dyn.d_un.d_val);
+ default:;
+ }
+
+ if (auto verdHdr = tryFindSectionHeader(".gnu.version_d"))
+ {
+ if (&shdrs.at(rdi(verdHdr->get().sh_link)) == &strTabHdr)
+ forAll_ElfVer(getSectionSpan<Elf_Verdef>(*verdHdr),
+ [] (auto& /*vd*/) {},
+ [&] (auto& vda) { fn(vda.vda_name); }
+ );
+ }
+
+ if (auto vernHdr = tryFindSectionHeader(".gnu.version_r"))
+ {
+ if (&shdrs.at(rdi(vernHdr->get().sh_link)) == &strTabHdr)
+ forAll_ElfVer(getSectionSpan<Elf_Verneed>(*vernHdr),
+ [&] (auto& vn) { fn(vn.vn_file); },
+ [&] (auto& vna) { fn(vna.vna_name); }
+ );
+ }
+}
+
static bool printInterpreter = false;
static bool printOsAbi = false;
static bool setOsAbi = false;
@@ -2397,9 +2433,9 @@ static void patchElf()
const std::string & outputFileName2 = outputFileName.empty() ? fileName : outputFileName;
if (getElfType(fileContents).is32Bit)
- 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);
+ 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);
else
- 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);
+ 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);
}
}
diff --git a/src/patchelf.h b/src/patchelf.h
index 9fab18c..4e229d6 100644
--- a/src/patchelf.h
+++ b/src/patchelf.h
@@ -10,8 +10,8 @@
using FileContents = std::shared_ptr<std::vector<unsigned char>>;
-#define ElfFileParams class Elf_Ehdr, class Elf_Phdr, class Elf_Shdr, class Elf_Addr, class Elf_Off, class Elf_Dyn, class Elf_Sym, class Elf_Verneed, class Elf_Versym, class Elf_Rel, class Elf_Rela, unsigned ElfClass
-#define ElfFileParamNames Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Addr, Elf_Off, Elf_Dyn, Elf_Sym, Elf_Verneed, Elf_Versym, Elf_Rel, Elf_Rela, ElfClass
+#define ElfFileParams class Elf_Ehdr, class Elf_Phdr, class Elf_Shdr, class Elf_Addr, class Elf_Off, class Elf_Dyn, class Elf_Sym, class Elf_Versym, class Elf_Verdef, class Elf_Verdaux, class Elf_Verneed, class Elf_Vernaux, class Elf_Rel, class Elf_Rela, unsigned ElfClass
+#define ElfFileParamNames Elf_Ehdr, Elf_Phdr, Elf_Shdr, Elf_Addr, Elf_Off, Elf_Dyn, Elf_Sym, Elf_Versym, Elf_Verdef, Elf_Verdaux, Elf_Verneed, Elf_Vernaux, Elf_Rel, Elf_Rela, ElfClass
template<class T>
struct span
@@ -237,6 +237,40 @@ private:
}
}
+ template<class StrIdxCallback>
+ void forAllStringReferences(const Elf_Shdr& strTabHdr, StrIdxCallback&& fn);
+
+ template<class T, class U>
+ auto follow(U* ptr, size_t offset) -> T* {
+ return offset ? (T*)(((char*)ptr)+offset) : nullptr;
+ };
+
+ template<class VdFn, class VaFn>
+ void forAll_ElfVer(span<Elf_Verdef> vdspan, VdFn&& vdfn, VaFn&& vafn)
+ {
+ auto* vd = vdspan.begin();
+ for (; vd; vd = follow<Elf_Verdef>(vd, rdi(vd->vd_next)))
+ {
+ vdfn(*vd);
+ auto va = follow<Elf_Verdaux>(vd, rdi(vd->vd_aux));
+ for (; va; va = follow<Elf_Verdaux>(va, rdi(va->vda_next)))
+ vafn(*va);
+ }
+ }
+
+ template<class VnFn, class VaFn>
+ void forAll_ElfVer(span<Elf_Verneed> vnspan, VnFn&& vnfn, VaFn&& vafn)
+ {
+ auto* vn = vnspan.begin();
+ for (; vn; vn = follow<Elf_Verneed>(vn, rdi(vn->vn_next)))
+ {
+ vnfn(*vn);
+ auto va = follow<Elf_Vernaux>(vn, rdi(vn->vn_aux));
+ for (; va; va = follow<Elf_Vernaux>(va, rdi(va->vna_next)))
+ vafn(*va);
+ }
+ }
+
/* Convert an integer in big or little endian representation (as
specified by the ELF header) to this platform's integer
representation. */