mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 05:07:34 +00:00
LibELF: Implement support for RELA relocations
This commit is contained in:
parent
1f93ffcd72
commit
f9a8c6f053
3 changed files with 33 additions and 11 deletions
|
@ -422,7 +422,10 @@ DynamicLoader::RelocationResult DynamicLoader::do_relocation(const ELF::DynamicO
|
||||||
return RelocationResult::Failed;
|
return RelocationResult::Failed;
|
||||||
}
|
}
|
||||||
auto symbol_address = res.value().address;
|
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;
|
break;
|
||||||
}
|
}
|
||||||
#ifndef __LP64__
|
#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.
|
// 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
|
// 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 :)
|
// 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;
|
break;
|
||||||
}
|
}
|
||||||
#ifndef __LP64__
|
#ifndef __LP64__
|
||||||
|
|
|
@ -120,6 +120,8 @@ void DynamicObject::parse()
|
||||||
m_plt_relocation_offset_location = entry.ptr() - (FlatPtr)m_elf_base_address.as_ptr();
|
m_plt_relocation_offset_location = entry.ptr() - (FlatPtr)m_elf_base_address.as_ptr();
|
||||||
break;
|
break;
|
||||||
case DT_RELA:
|
case DT_RELA:
|
||||||
|
m_addend_used = true;
|
||||||
|
[[fallthrough]];
|
||||||
case DT_REL:
|
case DT_REL:
|
||||||
m_relocation_table_offset = entry.ptr() - (FlatPtr)m_elf_base_address.as_ptr();
|
m_relocation_table_offset = entry.ptr() - (FlatPtr)m_elf_base_address.as_ptr();
|
||||||
break;
|
break;
|
||||||
|
@ -189,15 +191,15 @@ DynamicObject::Relocation DynamicObject::RelocationSection::relocation(unsigned
|
||||||
{
|
{
|
||||||
VERIFY(index < entry_count());
|
VERIFY(index < entry_count());
|
||||||
unsigned offset_in_section = index * entry_size();
|
unsigned offset_in_section = index * entry_size();
|
||||||
auto relocation_address = (ElfW(Rel)*)address().offset(offset_in_section).as_ptr();
|
auto relocation_address = (ElfW(Rela)*)address().offset(offset_in_section).as_ptr();
|
||||||
return Relocation(m_dynamic, *relocation_address, offset_in_section);
|
return Relocation(m_dynamic, *relocation_address, offset_in_section, m_addend_used);
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicObject::Relocation DynamicObject::RelocationSection::relocation_at_offset(unsigned offset) const
|
DynamicObject::Relocation DynamicObject::RelocationSection::relocation_at_offset(unsigned offset) const
|
||||||
{
|
{
|
||||||
VERIFY(offset <= (m_section_size_bytes - m_entry_size));
|
VERIFY(offset <= (m_section_size_bytes - m_entry_size));
|
||||||
auto relocation_address = (ElfW(Rel)*)address().offset(offset).as_ptr();
|
auto relocation_address = (ElfW(Rela)*)address().offset(offset).as_ptr();
|
||||||
return Relocation(m_dynamic, *relocation_address, offset);
|
return Relocation(m_dynamic, *relocation_address, offset, m_addend_used);
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicObject::Symbol DynamicObject::symbol(unsigned index) const
|
DynamicObject::Symbol DynamicObject::symbol(unsigned index) const
|
||||||
|
@ -229,12 +231,12 @@ DynamicObject::Section DynamicObject::fini_array_section() const
|
||||||
|
|
||||||
DynamicObject::RelocationSection DynamicObject::relocation_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
|
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
|
ElfW(Half) DynamicObject::program_header_count() const
|
||||||
|
|
|
@ -133,8 +133,9 @@ public:
|
||||||
|
|
||||||
class RelocationSection : public Section {
|
class RelocationSection : public Section {
|
||||||
public:
|
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)
|
: 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(); }
|
unsigned relocation_count() const { return entry_count(); }
|
||||||
|
@ -145,14 +146,18 @@ public:
|
||||||
void for_each_relocation(F) const;
|
void for_each_relocation(F) const;
|
||||||
template<VoidFunction<DynamicObject::Relocation&> F>
|
template<VoidFunction<DynamicObject::Relocation&> F>
|
||||||
void for_each_relocation(F func) const;
|
void for_each_relocation(F func) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const bool m_addend_used;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Relocation {
|
class Relocation {
|
||||||
public:
|
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_dynamic(dynamic)
|
||||||
, m_rel(rel)
|
, m_rel(rel)
|
||||||
, m_offset_in_section(offset_in_section)
|
, 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); }
|
unsigned symbol_index() const { return ELF64_R_SYM(m_rel.r_info); }
|
||||||
#endif
|
#endif
|
||||||
|
unsigned addend() const
|
||||||
|
{
|
||||||
|
VERIFY(m_addend_used);
|
||||||
|
return m_rel.r_addend;
|
||||||
|
}
|
||||||
|
bool addend_used() const { return m_addend_used; }
|
||||||
|
|
||||||
Symbol symbol() const
|
Symbol symbol() const
|
||||||
{
|
{
|
||||||
return m_dynamic.symbol(symbol_index());
|
return m_dynamic.symbol(symbol_index());
|
||||||
|
@ -186,8 +198,9 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const DynamicObject& m_dynamic;
|
const DynamicObject& m_dynamic;
|
||||||
const ElfW(Rel) & m_rel;
|
const ElfW(Rela) & m_rel;
|
||||||
const unsigned m_offset_in_section;
|
const unsigned m_offset_in_section;
|
||||||
|
const bool m_addend_used;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class HashType {
|
enum class HashType {
|
||||||
|
@ -357,6 +370,7 @@ private:
|
||||||
size_t m_number_of_relocations { 0 };
|
size_t m_number_of_relocations { 0 };
|
||||||
size_t m_size_of_relocation_entry { 0 };
|
size_t m_size_of_relocation_entry { 0 };
|
||||||
size_t m_size_of_relocation_table { 0 };
|
size_t m_size_of_relocation_table { 0 };
|
||||||
|
bool m_addend_used { false };
|
||||||
FlatPtr m_relocation_table_offset { 0 };
|
FlatPtr m_relocation_table_offset { 0 };
|
||||||
bool m_is_elf_dynamic { false };
|
bool m_is_elf_dynamic { false };
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue