diff options
Diffstat (limited to '.github/calcrom/ElfFile.cpp')
-rw-r--r-- | .github/calcrom/ElfFile.cpp | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/.github/calcrom/ElfFile.cpp b/.github/calcrom/ElfFile.cpp new file mode 100644 index 00000000..52ad2d06 --- /dev/null +++ b/.github/calcrom/ElfFile.cpp @@ -0,0 +1,130 @@ +#include <iostream> +#include <cassert> +#include <algorithm> +#include <cstring> +#include "ElfFile.h" + +void Elf32File::ReadElfHeaderAndVerify() { + handle.seekg(0); + handle.read((char *)ehdr.e_ident, EI_NIDENT); + assert(memcmp(ehdr.e_ident, ELFMAG, SELFMAG) == 0); + assert(ehdr.e_ident[EI_CLASS] == ELFCLASS32); + assert(ehdr.e_ident[EI_DATA] == ELFDATA2LSB); + assert(ehdr.e_ident[EI_VERSION] == EV_CURRENT); + handle.read((char*)&ehdr + EI_NIDENT, sizeof(ehdr) - EI_NIDENT); + assert(ehdr.e_shentsize == sizeof(Elf32_Shdr)); +} + +void Elf32File::ReadSectionHeaders() { + assert(shdr.empty()); + shdr.resize(ehdr.e_shnum); + handle.seekg(ehdr.e_shoff); + handle.read((char*)shdr.data(), ehdr.e_shnum * ehdr.e_shentsize); +} + +void Elf32File::ReadProgramHeaders() { + assert(phdr.empty()); + phdr.resize(ehdr.e_phnum); + handle.seekg(ehdr.e_phoff); + handle.read((char*)phdr.data(), ehdr.e_phnum * ehdr.e_phentsize); +} + +void Elf32File::ReadShstrtab() { + assert(shstrtab.empty()); + shstrtab.resize(shdr[ehdr.e_shstrndx].sh_size); + handle.seekg(shdr[ehdr.e_shstrndx].sh_offset); + handle.read((char*)shstrtab.data(), shdr[ehdr.e_shstrndx].sh_size); +} + +void Elf32File::ReadStrtab() { + assert(strtab.empty()); + int i; + for (i = 1; i < ehdr.e_shnum; i++) { + if (i == ehdr.e_shstrndx) continue; + if (shdr[i].sh_type == SHT_STRTAB) break; + } + assert(i != ehdr.e_shnum); + strtab.resize(shdr[i].sh_size); + handle.seekg(shdr[i].sh_offset); + handle.read((char*)strtab.data(), shdr[i].sh_size); +} + +void Elf32File::ReadSymtab() { + assert(symtab.empty()); + auto sec = find_if(shdr.begin(), shdr.end(), [](Elf32_Shdr const& candidate) { return candidate.sh_type == SHT_SYMTAB; }); + assert(sec != shdr.end()); + symtab.resize(sec->sh_size); + handle.seekg(sec->sh_offset); + handle.read((char*)symtab.data(), sec->sh_size); +} + +Elf32File::Elf32File(path const& filename, elfload load) { + open(filename, load); +} + +void Elf32File::open(path const& filename, elfload load) { + assert(!is_open()); + handle.open(filename, ios::binary); + assert(handle.good()); + ReadElfHeaderAndVerify(); + if (load & sections) { + ReadSectionHeaders(); + ReadShstrtab(); + } + if (load & programs) { + ReadProgramHeaders(); + } + if (load & symbols) { + assert(load & sections); + ReadStrtab(); + ReadSymtab(); + } +} + +void Elf32File::close() { + if (is_open()) { + handle.close(); + } + memset(&ehdr, 0, sizeof(ehdr)); + shdr.clear(); + symtab.clear(); + phdr.clear(); + shstrtab.clear(); + strtab.clear(); +} + +bool Elf32File::is_open() const { + return handle.is_open(); +} + +Elf32File::~Elf32File() { + close(); +} + +vector<Elf32_Shdr> &Elf32File::GetSectionHeaders() { + return shdr; +} + +vector<Elf32_Phdr> &Elf32File::GetProgramHeaders() { + return phdr; +} + +string Elf32File::GetSectionName(const Elf32_Shdr §ion) const { + return string(shstrtab.data() + section.sh_name); +} + +string Elf32File::GetSymbolName(const Elf32_Sym &symbol) const { + return string(strtab.data() + symbol.st_name); +} + +Elf32_Sym &Elf32File::operator[](const string &name) { + return *find_if(symtab.begin(), symtab.end(), [&](Elf32_Sym const &sym) { return name == GetSymbolName(sym); }); +} + +Elf32_Sym &Elf32File::at(const string &name) { + auto ret = find_if(symtab.begin(), symtab.end(), [&](Elf32_Sym const &sym) { return name == GetSymbolName(sym); }); + if (ret == symtab.end()) { + throw runtime_error("no symbol named " + name); + } + return *ret; +} |