From 8f51f0e6b21476d728efa5c34836ebe3f2bc8cc5 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Sat, 3 Nov 2018 10:11:56 +0100 Subject: [PATCH] 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. --- ELFLoader/ELFImage.cpp | 17 +++++++++++++++++ ELFLoader/ELFImage.h | 37 +++++++++++++++++++++++++++++++++++++ ELFLoader/ELFLoader.cpp | 9 +++++++++ 3 files changed, 63 insertions(+) diff --git a/ELFLoader/ELFImage.cpp b/ELFLoader/ELFImage.cpp index f42f1be771..33d4de35c7 100644 --- a/ELFLoader/ELFImage.cpp +++ b/ELFLoader/ELFImage.cpp @@ -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(rawData(0)); } +const Elf32_Phdr& ELFImage::program_header_internal(unsigned index) const +{ + ASSERT(index < header().e_phnum); + return *reinterpret_cast(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()); diff --git a/ELFLoader/ELFImage.h b/ELFLoader/ELFImage.h index 5181b637e2..287bdd0abf 100644 --- a/ELFLoader/ELFImage.h +++ b/ELFLoader/ELFImage.h @@ -8,6 +8,7 @@ #include #include #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 void forEachSection(F) const; template void forEachSectionOfType(unsigned, F) const; template void forEachSymbol(F) const; + template 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 +inline void ELFImage::for_each_program_header(F func) const +{ + for (unsigned i = 0; i < program_header_count(); ++i) { + func(program_header(i)); + } +} diff --git a/ELFLoader/ELFLoader.cpp b/ELFLoader/ELFLoader.cpp index 5bac37265e..5c3918b7fc 100644 --- a/ELFLoader/ELFLoader.cpp +++ b/ELFLoader/ELFLoader.cpp @@ -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;