#pragma once
#include "common/heap_array.h"
#include "common/types.h"
#include <functional>
class Error;
class ELFFile
{
public:
using DataArray = DynamicHeapArray<u8>;
static constexpr u8 EI_NIDENT = 16;
static constexpr u16 ET_EXEC = 2;
static constexpr u16 ET_DYN = 3;
static constexpr u16 EM_MIPS = 8;
static constexpr u16 SHN_UNDEF = 0;
static constexpr u32 SHT_NULL = 0;
static constexpr u32 SHT_PROGBITS = 1;
static constexpr u32 SHT_SYMTAB = 2;
static constexpr u32 SHT_STRTAB = 3;
static constexpr u32 SHT_RELA = 4;
static constexpr u32 SHT_HASH = 5;
static constexpr u32 SHT_DYNAMIC = 6;
static constexpr u32 SHT_NOTE = 7;
static constexpr u32 SHT_NOBITS = 8;
static constexpr u32 SHT_REL = 9;
static constexpr u32 SHT_SHLIB = 10;
static constexpr u32 SHT_DYNSYM = 11;
static constexpr u32 SHT_NUM = 12;
static constexpr u32 PT_NULL = 0;
static constexpr u32 PT_LOAD = 1;
static constexpr u32 PT_DYNAMIC = 2;
static constexpr u32 PT_INTERP = 3;
static constexpr u32 PT_NOTE = 4;
static constexpr u32 PT_SHLIB = 5;
static constexpr u32 PT_PHDR = 6;
static constexpr u32 PT_TLS = 7;
struct Elf32_Ehdr
{
u8 e_ident[EI_NIDENT];
u16 e_type;
u16 e_machine;
u32 e_version;
u32 e_entry;
u32 e_phoff;
u32 e_shoff;
u32 e_flags;
u16 e_ehsize;
u16 e_phentsize;
u16 e_phnum;
u16 e_shentsize;
u16 e_shnum;
u16 e_shstrndx;
};
struct Elf32_Shdr
{
u32 sh_name;
u32 sh_type;
u32 sh_flags;
u32 sh_addr;
u32 sh_offset;
u32 sh_size;
u32 sh_link;
u32 sh_info;
u32 sh_addralign;
u32 sh_entsize;
};
struct Elf32_Phdr
{
u32 p_type;
u32 p_offset;
u32 p_vaddr;
u32 p_paddr;
u32 p_filesz;
u32 p_memsz;
u32 p_flags;
u32 p_align;
};
public:
ELFFile();
~ELFFile();
static bool IsValidElfHeader(const std::span<const u8> data, Error* error = nullptr);
static bool IsValidElfHeader(const Elf32_Ehdr& header, Error* error = nullptr);
const Elf32_Ehdr& GetELFHeader() const;
u32 GetEntryPoint() const;
const Elf32_Shdr* GetSectionHeader(u32 index) const;
std::string_view GetSectionName(const Elf32_Shdr& section) const;
u32 GetSectionCount() const;
const Elf32_Phdr* GetProgramHeader(u32 index) const;
u32 GetProgramHeaderCount() const;
bool Open(const char* path, Error* error);
bool Open(DataArray data, Error* error);
using LoadExecutableSectionCallback =
std::function<bool(std::span<const u8> data, u32 dest_vaddr, u32 dest_size, Error* error)>;
bool LoadExecutableSections(const LoadExecutableSectionCallback& callback, Error* error) const;
private:
DataArray m_data;
};