diff --git a/elf.cc b/elf.cc index 78e99af867fa4b1b31bf20765e2ebca0c346f422..f2abbe78febdd82f02c2111c843af534937cec5b 100644 --- a/elf.cc +++ b/elf.cc @@ -348,12 +348,31 @@ namespace elf { } } + void elf_object::relocate_pltgot() + { + auto rel = dynamic_ptr<Elf64_Rela>(DT_JMPREL); + auto nrel = dynamic_val(DT_PLTRELSZ) / sizeof(*rel); + for (auto p = rel; p < rel + nrel; ++p) { + auto info = p->r_info; + u32 sym = info >> 32; + u32 type = info & 0xffffffff; + assert(type = R_X86_64_JUMP_SLOT); + void *addr = _base + p->r_offset; + // The JUMP_SLOT entry already points back to the PLT, just + // make sure it is relocated relative to the object base. + *static_cast<u64*>(addr) += reinterpret_cast<u64>(_base); + } + } + void elf_object::relocate() { assert(!dynamic_exists(DT_REL)); if (dynamic_exists(DT_RELA)) { relocate_rela(); } + if (dynamic_exists(DT_JMPREL)) { + relocate_pltgot(); + } } unsigned long diff --git a/elf.hh b/elf.hh index ece9af995ae08b6f4606873e428247b6d3d876ce..bb6a37f33ea2f8cb5b9ab8ef716459db5a55cf99 100644 --- a/elf.hh +++ b/elf.hh @@ -272,6 +272,7 @@ namespace elf { symbol_module symbol(unsigned idx); Elf64_Xword symbol_tls_module(unsigned idx); void relocate_rela(); + void relocate_pltgot(); protected: program& _prog; Elf64_Ehdr _ehdr;