mirror of
https://github.com/cemu-project/Cemu.git
synced 2026-09-27 11:36:29 -05:00
Refactor ELF reader class
also properly interpet the mmap failure condition
This commit is contained in:
@@ -5,31 +5,19 @@
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
uint16 ELFSymbolTable::FindSection(int type, const std::string_view& name)
|
||||
template <typename T>
|
||||
std::span<T> ELFSymbolTable::SectionAsArray(const Elf64_Shdr* section)
|
||||
{
|
||||
if (!shTable || !shStrTable)
|
||||
return 0;
|
||||
if (section == nullptr)
|
||||
return {};
|
||||
if (section->sh_size < sizeof(T))
|
||||
return {};
|
||||
if (section->sh_entsize != 0 && section->sh_entsize != sizeof(T))
|
||||
return {};
|
||||
|
||||
for (uint16 i = 0; i < header->e_shnum; ++i)
|
||||
{
|
||||
auto& entry = shTable[i];
|
||||
if(entry.sh_type == type && std::string_view{&shStrTable[entry.sh_name]} == name)
|
||||
{
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
return {(T*)(mappedExecutable + section->sh_offset), section->sh_size / sizeof(T)};
|
||||
}
|
||||
|
||||
void* ELFSymbolTable::SectionPointer(uint16 index)
|
||||
{
|
||||
return SectionPointer(shTable[index]);
|
||||
}
|
||||
|
||||
void* ELFSymbolTable::SectionPointer(const Elf64_Shdr& section)
|
||||
{
|
||||
return (void*)(mappedExecutable + section.sh_offset);
|
||||
}
|
||||
|
||||
ELFSymbolTable::ELFSymbolTable()
|
||||
{
|
||||
@@ -40,7 +28,7 @@ ELFSymbolTable::ELFSymbolTable()
|
||||
|
||||
// retrieve file size.
|
||||
struct stat filestats;
|
||||
if (fstat(fd, &filestats))
|
||||
if (fstat(fd, &filestats) != 0)
|
||||
{
|
||||
close(fd);
|
||||
return;
|
||||
@@ -48,9 +36,9 @@ ELFSymbolTable::ELFSymbolTable()
|
||||
mappedExecutableSize = filestats.st_size;
|
||||
|
||||
// attempt to map the file
|
||||
mappedExecutable = (uint8*)(mmap(nullptr, mappedExecutableSize, PROT_READ, MAP_PRIVATE, fd, 0));
|
||||
mappedExecutable = static_cast<uint8*>(mmap(nullptr, mappedExecutableSize, PROT_READ, MAP_PRIVATE, fd, 0));
|
||||
close(fd);
|
||||
if (!mappedExecutable)
|
||||
if (mappedExecutable == MAP_FAILED)
|
||||
return;
|
||||
|
||||
// verify signature
|
||||
@@ -64,19 +52,11 @@ ELFSymbolTable::ELFSymbolTable()
|
||||
}
|
||||
}
|
||||
|
||||
shTable = (Elf64_Shdr*)(mappedExecutable + header->e_shoff);
|
||||
shTable = {(Elf64_Shdr*)(mappedExecutable + header->e_shoff), header->e_shnum};
|
||||
|
||||
Elf64_Shdr& shStrn = shTable[header->e_shstrndx];
|
||||
shStrTable = (char*)(mappedExecutable + shStrn.sh_offset);
|
||||
|
||||
strTable = (char*)SectionPointer(FindSection(SHT_STRTAB, ".strtab"));
|
||||
|
||||
Elf64_Shdr& symTabShdr = shTable[FindSection(SHT_SYMTAB, ".symtab")];
|
||||
if (symTabShdr.sh_entsize == 0)
|
||||
return;
|
||||
|
||||
symTableLen = symTabShdr.sh_size / symTabShdr.sh_entsize;
|
||||
symTable = (Elf64_Sym*)(SectionPointer(symTabShdr));
|
||||
shStrTable = SectionAsArray<char>(&shTable[header->e_shstrndx]);
|
||||
strTable = SectionAsArray<char>(FindSection(SHT_STRTAB, ".strtab"));
|
||||
symTable = SectionAsArray<Elf64_Sym>(FindSection(SHT_SYMTAB, ".symtab"));
|
||||
}
|
||||
|
||||
ELFSymbolTable::~ELFSymbolTable()
|
||||
@@ -85,15 +65,30 @@ ELFSymbolTable::~ELFSymbolTable()
|
||||
munmap(mappedExecutable, mappedExecutableSize);
|
||||
}
|
||||
|
||||
Elf64_Shdr* ELFSymbolTable::FindSection(Elf64_Word type, const std::string_view& name)
|
||||
{
|
||||
if (shTable.empty() || shStrTable.empty())
|
||||
return nullptr;
|
||||
|
||||
for (auto& entry : shTable)
|
||||
{
|
||||
if(entry.sh_type == type && std::string_view{&shStrTable[entry.sh_name]} == name)
|
||||
{
|
||||
return &entry;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::string_view ELFSymbolTable::OffsetToSymbol(uint64 ptr, uint64& fromStart) const
|
||||
{
|
||||
if(!symTable || !strTable)
|
||||
if(symTable.empty() || strTable.empty())
|
||||
{
|
||||
fromStart = -1;
|
||||
return {};
|
||||
}
|
||||
|
||||
for (auto entry = symTable+1; entry < symTable+symTableLen; ++entry)
|
||||
for (auto entry = symTable.begin()+1; entry != symTable.end(); ++entry)
|
||||
{
|
||||
if (ELF64_ST_TYPE(entry->st_info) != STT_FUNC)
|
||||
continue;
|
||||
|
||||
@@ -15,17 +15,16 @@ private:
|
||||
|
||||
Elf64_Ehdr* header = nullptr;
|
||||
|
||||
Elf64_Shdr* shTable = nullptr;
|
||||
char* shStrTable = nullptr;
|
||||
std::span<Elf64_Shdr> shTable{};
|
||||
std::span<char> shStrTable{};
|
||||
|
||||
Elf64_Sym* symTable = nullptr;
|
||||
uint64 symTableLen = 0;
|
||||
char* strTable = nullptr;
|
||||
std::span<Elf64_Sym> symTable{};
|
||||
std::span<char> strTable{};
|
||||
|
||||
uint16 FindSection(int type, const std::string_view& name);
|
||||
Elf64_Shdr* FindSection(Elf64_Word type, const std::string_view& name);
|
||||
|
||||
void* SectionPointer (uint16 index);
|
||||
void* SectionPointer(const Elf64_Shdr& section);
|
||||
template <typename T>
|
||||
std::span<T> SectionAsArray(const Elf64_Shdr* section);
|
||||
|
||||
// ownership of mapped memory, cannot copy.
|
||||
ELFSymbolTable(const ELFSymbolTable&) = delete;
|
||||
|
||||
Reference in New Issue
Block a user