1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 14:38:11 +00:00

ELFLoader: Add program header support.

We don't do anything useful with the data yet, but I'm gonna rewrite
the layout code to run off of the program header table instead.
This will allow us to map .text and .rodata sections in read-only memory.
This commit is contained in:
Andreas Kling 2018-11-03 10:11:56 +01:00
parent 20fb1fc377
commit 8f51f0e6b2
3 changed files with 63 additions and 0 deletions

View file

@ -91,6 +91,11 @@ unsigned ELFImage::sectionCount() const
return header().e_shnum;
}
unsigned ELFImage::program_header_count() const
{
return header().e_phnum;
}
bool ELFImage::parse()
{
// We only support i386.
@ -148,6 +153,12 @@ const Elf32_Ehdr& ELFImage::header() const
return *reinterpret_cast<const Elf32_Ehdr*>(rawData(0));
}
const Elf32_Phdr& ELFImage::program_header_internal(unsigned index) const
{
ASSERT(index < header().e_phnum);
return *reinterpret_cast<const Elf32_Phdr*>(rawData(header().e_phoff + (index * sizeof(Elf32_Phdr))));
}
const Elf32_Shdr& ELFImage::sectionHeader(unsigned index) const
{
ASSERT(index < header().e_shnum);
@ -167,6 +178,12 @@ const ELFImage::Section ELFImage::section(unsigned index) const
return Section(*this, index);
}
const ELFImage::ProgramHeader ELFImage::program_header(unsigned index) const
{
ASSERT(index < program_header_count());
return ProgramHeader(*this, index);
}
const ELFImage::Relocation ELFImage::RelocationSection::relocation(unsigned index) const
{
ASSERT(index < relocationCount());

View file

@ -8,6 +8,7 @@
#include <AK/HashMap.h>
#include <AK/String.h>
#include "elf.h"
#include "types.h"
class ELFImage {
public:
@ -51,6 +52,31 @@ public:
const unsigned m_index;
};
class ProgramHeader {
public:
ProgramHeader(const ELFImage& image, unsigned program_header_index)
: m_program_header(image.program_header_internal(program_header_index))
, m_program_header_index(program_header_index)
{
}
~ProgramHeader() { }
unsigned index() const { return m_program_header_index; }
dword type() const { return m_program_header.p_type; }
dword flags() const { return m_program_header.p_flags; }
dword offset() const { return m_program_header.p_offset; }
LinearAddress laddr() const { return LinearAddress(m_program_header.p_vaddr); }
dword size_in_memory() const { return m_program_header.p_memsz; }
dword size_in_image() const { return m_program_header.p_filesz; }
dword alignment() const { return m_program_header.p_align; }
bool is_readable() const { return flags() & PF_R; }
bool is_writable() const { return flags() & PF_W; }
bool is_executable() const { return flags() & PF_X; }
private:
const Elf32_Phdr& m_program_header;
unsigned m_program_header_index { 0 };
};
class Section {
public:
Section(const ELFImage& image, unsigned sectionIndex)
@ -112,13 +138,16 @@ public:
unsigned symbolCount() const;
unsigned sectionCount() const;
unsigned program_header_count() const;
const Symbol symbol(unsigned) const;
const Section section(unsigned) const;
const ProgramHeader program_header(unsigned const) const;
template<typename F> void forEachSection(F) const;
template<typename F> void forEachSectionOfType(unsigned, F) const;
template<typename F> void forEachSymbol(F) const;
template<typename F> void for_each_program_header(F) const;
// NOTE: Returns section(0) if section with name is not found.
// FIXME: I don't love this API.
@ -132,6 +161,7 @@ private:
const char* rawData(unsigned offset) const;
const Elf32_Ehdr& header() const;
const Elf32_Shdr& sectionHeader(unsigned) const;
const Elf32_Phdr& program_header_internal(unsigned) const;
const char* tableString(unsigned offset) const;
const char* sectionHeaderTableString(unsigned offset) const;
const char* sectionIndexToString(unsigned index);
@ -184,3 +214,10 @@ inline void ELFImage::forEachSymbol(F func) const
}
}
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));
}
}

View file

@ -39,6 +39,15 @@ bool ELFLoader::layout()
#ifdef ELFLOADER_DEBUG
kprintf("ELFLoader: Layout\n");
#endif
m_image->for_each_program_header([&] (const ELFImage::ProgramHeader& program_header) {
if (program_header.type() != PT_LOAD)
return;
#ifdef ELFLOADER_DEBUG
kprintf("PH: L%x %u r:%u w:%u\n", program_header.laddr().get(), program_header.size_in_memory(), program_header.is_readable(), program_header.is_writable());
#endif
});
bool failed = false;
dword highestOffset = 0;
dword sizeNeeded = 0;