/** * @file elfload.cpp * @brief Loads ELF binary data into memory for execution. * * Copyright (C) 2021 Clyne Sullivan * * Distributed under the GNU GPL v3 or later. You should have received a copy of * the GNU General Public License along with this program. * If not, see . */ #include "elfload.hpp" #include "elf.h" #include #include __attribute__((section(".convdata"))) ELFManager::EntryFunc ELFManager::m_entry = nullptr; std::array ELFManager::m_file_buffer = {}; static const unsigned char elf_header[] = { '\177', 'E', 'L', 'F' }; __attribute__((section(".convcode"))) ELFManager::EntryFunc ELFManager::loadedElf() { return m_entry; } unsigned char *ELFManager::fileBuffer() { return m_file_buffer.data(); } void ELFManager::unload() { m_entry = nullptr; } template constexpr static auto ptr_from_offset(void *base, uint32_t offset) { return reinterpret_cast(reinterpret_cast(base) + offset); } bool ELFManager::loadFromInternalBuffer() { m_entry = nullptr; auto elf_data = m_file_buffer.data(); // Check the ELF's header signature auto ehdr = reinterpret_cast(elf_data); if (!std::equal(ehdr->e_ident, ehdr->e_ident + 4, elf_header)) return false; // Iterate through program header LOAD sections bool loaded = false; auto phdr = ptr_from_offset(elf_data, ehdr->e_phoff); for (Elf32_Half i = 0; i < ehdr->e_phnum; i++) { if (phdr->p_type == PT_LOAD) { if (phdr->p_filesz == 0) { std::memset(reinterpret_cast(phdr->p_vaddr), 0, phdr->p_memsz); } else { std::memcpy(reinterpret_cast(phdr->p_vaddr), ptr_from_offset(elf_data, phdr->p_offset), phdr->p_filesz); if (!loaded) loaded = true; } } phdr = ptr_from_offset(phdr, ehdr->e_phentsize); } if (loaded) m_entry = reinterpret_cast(ehdr->e_entry); return loaded; }