mirror of
https://github.com/RGBCube/serenity
synced 2025-05-31 10:28:10 +00:00
LibELF: Add ELFDynamicObject to dynamically load libaries
This patch also adds some missing relocation defines to exec_elf.h, and a few helper classes/methods to ELFImage so that we can use it for our dynamically loaded libs and not just main program images from the kernel :)
This commit is contained in:
parent
b6590b7f83
commit
a18b37880e
5 changed files with 941 additions and 5 deletions
|
@ -16,8 +16,13 @@ public:
|
|||
|
||||
class Section;
|
||||
class RelocationSection;
|
||||
class DynamicRelocationSection;
|
||||
class Symbol;
|
||||
class DynamicSymbol;
|
||||
class Relocation;
|
||||
class DynamicRelocation;
|
||||
class DynamicSection;
|
||||
class DynamicSectionEntry;
|
||||
|
||||
class Symbol {
|
||||
public:
|
||||
|
@ -45,6 +50,32 @@ public:
|
|||
const unsigned m_index;
|
||||
};
|
||||
|
||||
class DynamicSymbol {
|
||||
public:
|
||||
DynamicSymbol(const ELFImage& image, unsigned index, const Elf32_Sym& sym)
|
||||
: m_image(image)
|
||||
, m_sym(sym)
|
||||
, m_index(index)
|
||||
{
|
||||
}
|
||||
|
||||
~DynamicSymbol() {}
|
||||
|
||||
const char* name() const { return m_image.dynamic_table_string(m_sym.st_name); }
|
||||
unsigned section_index() const { return m_sym.st_shndx; }
|
||||
unsigned value() const { return m_sym.st_value; }
|
||||
unsigned size() const { return m_sym.st_size; }
|
||||
unsigned index() const { return m_index; }
|
||||
unsigned type() const { return ELF32_ST_TYPE(m_sym.st_info); }
|
||||
unsigned bind() const { return ELF32_ST_BIND(m_sym.st_info); }
|
||||
const Section section() const { return m_image.section(section_index()); }
|
||||
|
||||
private:
|
||||
const ELFImage& m_image;
|
||||
const Elf32_Sym& m_sym;
|
||||
const unsigned m_index;
|
||||
};
|
||||
|
||||
class ProgramHeader {
|
||||
public:
|
||||
ProgramHeader(const ELFImage& image, unsigned program_header_index)
|
||||
|
@ -67,6 +98,7 @@ public:
|
|||
bool is_writable() const { return flags() & PF_W; }
|
||||
bool is_executable() const { return flags() & PF_X; }
|
||||
const char* raw_data() const { return m_image.raw_data(m_program_header.p_offset); }
|
||||
Elf32_Phdr raw_header() const { return m_program_header; }
|
||||
|
||||
private:
|
||||
const ELFImage& m_image;
|
||||
|
@ -100,6 +132,8 @@ public:
|
|||
|
||||
protected:
|
||||
friend class RelocationSection;
|
||||
friend class DynamicSection;
|
||||
friend class DynamicRelocationSection;
|
||||
const ELFImage& m_image;
|
||||
const Elf32_Shdr& m_section_header;
|
||||
unsigned m_section_index;
|
||||
|
@ -117,6 +151,38 @@ public:
|
|||
void for_each_relocation(F) const;
|
||||
};
|
||||
|
||||
class DynamicRelocationSection : public Section {
|
||||
public:
|
||||
DynamicRelocationSection(const Section& section)
|
||||
: Section(section.m_image, section.m_section_index)
|
||||
{
|
||||
}
|
||||
unsigned relocation_count() const { return entry_count(); }
|
||||
const DynamicRelocation relocation(unsigned index) const;
|
||||
template<typename F>
|
||||
void for_each_relocation(F) const;
|
||||
};
|
||||
|
||||
class DynamicRelocation {
|
||||
public:
|
||||
DynamicRelocation(const ELFImage& image, const Elf32_Rel& rel)
|
||||
: m_image(image)
|
||||
, m_rel(rel)
|
||||
{
|
||||
}
|
||||
|
||||
~DynamicRelocation() {}
|
||||
|
||||
unsigned offset() const { return m_rel.r_offset; }
|
||||
unsigned type() const { return ELF32_R_TYPE(m_rel.r_info); }
|
||||
unsigned symbol_index() const { return ELF32_R_SYM(m_rel.r_info); }
|
||||
const DynamicSymbol symbol() const { return m_image.dynamic_symbol(symbol_index()); }
|
||||
|
||||
private:
|
||||
const ELFImage& m_image;
|
||||
const Elf32_Rel& m_rel;
|
||||
};
|
||||
|
||||
class Relocation {
|
||||
public:
|
||||
Relocation(const ELFImage& image, const Elf32_Rel& rel)
|
||||
|
@ -137,13 +203,48 @@ public:
|
|||
const Elf32_Rel& m_rel;
|
||||
};
|
||||
|
||||
class DynamicSection : public Section {
|
||||
public:
|
||||
DynamicSection(const Section& section)
|
||||
: Section(section.m_image, section.m_section_index)
|
||||
{
|
||||
ASSERT(type() == SHT_DYNAMIC);
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
void for_each_dynamic_entry(F) const;
|
||||
};
|
||||
|
||||
class DynamicSectionEntry {
|
||||
public:
|
||||
DynamicSectionEntry(const ELFImage& image, const Elf32_Dyn& dyn)
|
||||
: m_image(image)
|
||||
, m_dyn(dyn)
|
||||
{
|
||||
}
|
||||
|
||||
~DynamicSectionEntry() {}
|
||||
|
||||
Elf32_Sword tag() const { return m_dyn.d_tag; }
|
||||
Elf32_Addr ptr() const { return m_dyn.d_un.d_ptr; }
|
||||
Elf32_Word val() const { return m_dyn.d_un.d_val; }
|
||||
|
||||
private:
|
||||
const ELFImage& m_image;
|
||||
const Elf32_Dyn& m_dyn;
|
||||
};
|
||||
|
||||
unsigned symbol_count() const;
|
||||
unsigned dynamic_symbol_count() const;
|
||||
unsigned section_count() const;
|
||||
unsigned program_header_count() const;
|
||||
|
||||
const Symbol symbol(unsigned) const;
|
||||
const DynamicSymbol dynamic_symbol(unsigned) const;
|
||||
const Section section(unsigned) const;
|
||||
const ProgramHeader program_header(unsigned const) const;
|
||||
const DynamicSection dynamic_section() const;
|
||||
const DynamicRelocationSection dynamic_relocation_section() const;
|
||||
|
||||
template<typename F>
|
||||
void for_each_section(F) const;
|
||||
|
@ -152,6 +253,8 @@ public:
|
|||
template<typename F>
|
||||
void for_each_symbol(F) const;
|
||||
template<typename F>
|
||||
void for_each_dynamic_symbol(F) const;
|
||||
template<typename F>
|
||||
void for_each_program_header(F) const;
|
||||
|
||||
// NOTE: Returns section(0) if section with name is not found.
|
||||
|
@ -160,6 +263,7 @@ public:
|
|||
|
||||
bool is_executable() const { return header().e_type == ET_EXEC; }
|
||||
bool is_relocatable() const { return header().e_type == ET_REL; }
|
||||
bool is_dynamic() const { return header().e_type == ET_DYN; }
|
||||
|
||||
VirtualAddress entry() const { return VirtualAddress(header().e_entry); }
|
||||
|
||||
|
@ -172,12 +276,17 @@ private:
|
|||
const char* table_string(unsigned offset) const;
|
||||
const char* section_header_table_string(unsigned offset) const;
|
||||
const char* section_index_to_string(unsigned index) const;
|
||||
const char* dynamic_table_string(unsigned offset) const;
|
||||
|
||||
const u8* m_buffer { nullptr };
|
||||
HashMap<String, unsigned> m_sections;
|
||||
bool m_valid { false };
|
||||
unsigned m_symbol_table_section_index { 0 };
|
||||
unsigned m_string_table_section_index { 0 };
|
||||
unsigned m_dynamic_symbol_table_section_index { 0 }; // .dynsym
|
||||
unsigned m_dynamic_string_table_section_index { 0 }; // .dynstr
|
||||
unsigned m_dynamic_section_index { 0 }; // .dynamic
|
||||
unsigned m_dynamic_relocation_section_index { 0 }; // .rel.dyn
|
||||
};
|
||||
|
||||
template<typename F>
|
||||
|
@ -208,6 +317,15 @@ inline void ELFImage::RelocationSection::for_each_relocation(F func) const
|
|||
}
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
inline void ELFImage::DynamicRelocationSection::for_each_relocation(F func) const
|
||||
{
|
||||
for (unsigned i = 0; i < relocation_count(); ++i) {
|
||||
if (func(relocation(i)) == IterationDecision::Break)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
inline void ELFImage::for_each_symbol(F func) const
|
||||
{
|
||||
|
@ -217,9 +335,31 @@ inline void ELFImage::for_each_symbol(F func) const
|
|||
}
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
inline void ELFImage::for_each_dynamic_symbol(F func) const
|
||||
{
|
||||
for (unsigned i = 0; i < dynamic_symbol_count(); ++i) {
|
||||
if (func(symbol(i)) == IterationDecision::Break)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
inline void ELFImage::for_each_program_header(F func) const
|
||||
{
|
||||
for (unsigned i = 0; i < program_header_count(); ++i)
|
||||
func(program_header(i));
|
||||
}
|
||||
|
||||
template<typename F>
|
||||
inline void ELFImage::DynamicSection::for_each_dynamic_entry(F func) const
|
||||
{
|
||||
auto* dyns = reinterpret_cast<const Elf32_Dyn*>(m_image.raw_data(offset()));
|
||||
for (unsigned i = 0;; ++i) {
|
||||
auto&& dyn = DynamicSectionEntry(m_image, dyns[i]);
|
||||
if (dyn.tag() == DT_NULL)
|
||||
break;
|
||||
if (func(dyn) == IterationDecision::Break)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue