diff options
author | Gunnar Beutner <gbeutner@serenityos.org> | 2021-07-01 02:24:11 +0200 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-07-01 10:50:00 +0200 |
commit | f9a8c6f0535bf46b78a068b9cec35be47ff0350a (patch) | |
tree | 939fe1e7e96c11b6ccd0f98c35f7415106df2073 | |
parent | 1f93ffcd729d778c68f6ed8cca161cd4907e1c66 (diff) | |
download | serenity-f9a8c6f0535bf46b78a068b9cec35be47ff0350a.zip |
LibELF: Implement support for RELA relocations
-rw-r--r-- | Userland/Libraries/LibELF/DynamicLoader.cpp | 10 | ||||
-rw-r--r-- | Userland/Libraries/LibELF/DynamicObject.cpp | 14 | ||||
-rw-r--r-- | Userland/Libraries/LibELF/DynamicObject.h | 20 |
3 files changed, 33 insertions, 11 deletions
diff --git a/Userland/Libraries/LibELF/DynamicLoader.cpp b/Userland/Libraries/LibELF/DynamicLoader.cpp index 7065b60380..b09621490b 100644 --- a/Userland/Libraries/LibELF/DynamicLoader.cpp +++ b/Userland/Libraries/LibELF/DynamicLoader.cpp @@ -422,7 +422,10 @@ DynamicLoader::RelocationResult DynamicLoader::do_relocation(const ELF::DynamicO return RelocationResult::Failed; } auto symbol_address = res.value().address; - *patch_ptr += symbol_address.get(); + if (relocation.addend_used()) + *patch_ptr = symbol_address.get() + relocation.addend(); + else + *patch_ptr += symbol_address.get(); break; } #ifndef __LP64__ @@ -466,7 +469,10 @@ DynamicLoader::RelocationResult DynamicLoader::do_relocation(const ELF::DynamicO // FIXME: According to the spec, R_386_relative ones must be done first. // We could explicitly do them first using m_number_of_relocations from DT_RELCOUNT // However, our compiler is nice enough to put them at the front of the relocations for us :) - *patch_ptr += (FlatPtr)m_dynamic_object->base_address().as_ptr(); // + addend for RelA (addend for Rel is stored at addr) + if (relocation.addend_used()) + *patch_ptr = (FlatPtr)m_dynamic_object->base_address().as_ptr() + relocation.addend(); + else + *patch_ptr += (FlatPtr)m_dynamic_object->base_address().as_ptr(); break; } #ifndef __LP64__ diff --git a/Userland/Libraries/LibELF/DynamicObject.cpp b/Userland/Libraries/LibELF/DynamicObject.cpp index 65b10d7bab..c79cd5f04b 100644 --- a/Userland/Libraries/LibELF/DynamicObject.cpp +++ b/Userland/Libraries/LibELF/DynamicObject.cpp @@ -120,6 +120,8 @@ void DynamicObject::parse() m_plt_relocation_offset_location = entry.ptr() - (FlatPtr)m_elf_base_address.as_ptr(); break; case DT_RELA: + m_addend_used = true; + [[fallthrough]]; case DT_REL: m_relocation_table_offset = entry.ptr() - (FlatPtr)m_elf_base_address.as_ptr(); break; @@ -189,15 +191,15 @@ DynamicObject::Relocation DynamicObject::RelocationSection::relocation(unsigned { VERIFY(index < entry_count()); unsigned offset_in_section = index * entry_size(); - auto relocation_address = (ElfW(Rel)*)address().offset(offset_in_section).as_ptr(); - return Relocation(m_dynamic, *relocation_address, offset_in_section); + auto relocation_address = (ElfW(Rela)*)address().offset(offset_in_section).as_ptr(); + return Relocation(m_dynamic, *relocation_address, offset_in_section, m_addend_used); } DynamicObject::Relocation DynamicObject::RelocationSection::relocation_at_offset(unsigned offset) const { VERIFY(offset <= (m_section_size_bytes - m_entry_size)); - auto relocation_address = (ElfW(Rel)*)address().offset(offset).as_ptr(); - return Relocation(m_dynamic, *relocation_address, offset); + auto relocation_address = (ElfW(Rela)*)address().offset(offset).as_ptr(); + return Relocation(m_dynamic, *relocation_address, offset, m_addend_used); } DynamicObject::Symbol DynamicObject::symbol(unsigned index) const @@ -229,12 +231,12 @@ DynamicObject::Section DynamicObject::fini_array_section() const DynamicObject::RelocationSection DynamicObject::relocation_section() const { - return RelocationSection(Section(*this, m_relocation_table_offset, m_size_of_relocation_table, m_size_of_relocation_entry, "DT_REL"sv)); + return RelocationSection(Section(*this, m_relocation_table_offset, m_size_of_relocation_table, m_size_of_relocation_entry, "DT_REL"sv), m_addend_used); } DynamicObject::RelocationSection DynamicObject::plt_relocation_section() const { - return RelocationSection(Section(*this, m_plt_relocation_offset_location, m_size_of_plt_relocation_entry_list, m_size_of_relocation_entry, "DT_JMPREL"sv)); + return RelocationSection(Section(*this, m_plt_relocation_offset_location, m_size_of_plt_relocation_entry_list, m_size_of_relocation_entry, "DT_JMPREL"sv), false); } ElfW(Half) DynamicObject::program_header_count() const diff --git a/Userland/Libraries/LibELF/DynamicObject.h b/Userland/Libraries/LibELF/DynamicObject.h index 0be9bdb3d4..8c89b4214a 100644 --- a/Userland/Libraries/LibELF/DynamicObject.h +++ b/Userland/Libraries/LibELF/DynamicObject.h @@ -133,8 +133,9 @@ public: class RelocationSection : public Section { public: - explicit RelocationSection(const Section& section) + explicit RelocationSection(const Section& section, bool addend_used) : Section(section.m_dynamic, section.m_section_offset, section.m_section_size_bytes, section.m_entry_size, section.m_name) + , m_addend_used(addend_used) { } unsigned relocation_count() const { return entry_count(); } @@ -145,14 +146,18 @@ public: void for_each_relocation(F) const; template<VoidFunction<DynamicObject::Relocation&> F> void for_each_relocation(F func) const; + + private: + const bool m_addend_used; }; class Relocation { public: - Relocation(const DynamicObject& dynamic, const ElfW(Rel) & rel, unsigned offset_in_section) + Relocation(const DynamicObject& dynamic, const ElfW(Rela) & rel, unsigned offset_in_section, bool addend_used) : m_dynamic(dynamic) , m_rel(rel) , m_offset_in_section(offset_in_section) + , m_addend_used(addend_used) { } @@ -173,6 +178,13 @@ public: } unsigned symbol_index() const { return ELF64_R_SYM(m_rel.r_info); } #endif + unsigned addend() const + { + VERIFY(m_addend_used); + return m_rel.r_addend; + } + bool addend_used() const { return m_addend_used; } + Symbol symbol() const { return m_dynamic.symbol(symbol_index()); @@ -186,8 +198,9 @@ public: private: const DynamicObject& m_dynamic; - const ElfW(Rel) & m_rel; + const ElfW(Rela) & m_rel; const unsigned m_offset_in_section; + const bool m_addend_used; }; enum class HashType { @@ -357,6 +370,7 @@ private: size_t m_number_of_relocations { 0 }; size_t m_size_of_relocation_entry { 0 }; size_t m_size_of_relocation_table { 0 }; + bool m_addend_used { false }; FlatPtr m_relocation_table_offset { 0 }; bool m_is_elf_dynamic { false }; |