100 lines
2.6 KiB
C++
Raw Normal View History

2024-09-07 22:56:20 +06:00
#include "image.h"
#include "elf.h"
#include "xex.h"
#include <cassert>
#include <cstring>
2024-09-07 22:56:20 +06:00
void Image::Map(const std::string_view& name, size_t base, uint32_t size, uint8_t flags, uint8_t* data)
{
2024-12-13 18:31:55 +03:00
sections.insert({ std::string(name), this->base + base,
size, static_cast<SectionFlags>(flags), data });
2024-09-07 22:56:20 +06:00
}
const void* Image::Find(size_t address) const
{
2024-09-22 19:58:22 +03:00
const auto section = std::prev(sections.upper_bound(address));
2024-09-08 08:32:31 +06:00
return section->data + (address - section->base);
2024-09-07 22:56:20 +06:00
}
2024-09-11 21:21:23 +06:00
const Section* Image::Find(const std::string_view& name) const
{
for (const auto& section : sections)
{
if (section.name == name)
{
return &section;
}
}
return nullptr;
}
2024-12-13 18:31:55 +03:00
Image Image::ParseImage(const uint8_t* data, size_t size)
2024-09-07 22:56:20 +06:00
{
if (data[0] == ELFMAG0 && data[1] == ELFMAG1 && data[2] == ELFMAG2 && data[3] == ELFMAG3)
{
return ElfLoadImage(data, size);
}
2024-09-08 18:18:18 +06:00
else if (data[0] == 'X' && data[1] == 'E' && data[2] == 'X' && data[3] == '2')
2024-09-07 22:56:20 +06:00
{
return Xex2LoadImage(data, size);
2024-09-07 22:56:20 +06:00
}
2024-12-13 18:31:55 +03:00
return {};
2024-09-07 22:56:20 +06:00
}
Image ElfLoadImage(const uint8_t* data, size_t size)
{
const auto* header = (elf32_hdr*)data;
assert(header->e_ident[EI_DATA] == 2);
Image image{};
image.size = size;
image.data = std::make_unique<uint8_t[]>(size);
2024-12-13 18:31:55 +03:00
image.entry_point = ByteSwap(header->e_entry);
2024-09-07 22:56:20 +06:00
memcpy(image.data.get(), data, size);
2024-12-13 18:31:55 +03:00
auto stringTableIndex = ByteSwap(header->e_shstrndx);
2024-09-07 22:56:20 +06:00
2024-12-13 18:31:55 +03:00
const auto numSections = ByteSwap(header->e_shnum);
const auto numpSections = ByteSwap(header->e_phnum);
2024-09-07 22:56:20 +06:00
2024-12-13 18:31:55 +03:00
const auto* sections = (elf32_shdr*)(data + ByteSwap(header->e_shoff));
const auto* psections = (elf32_phdr*)(data + ByteSwap(header->e_phoff));
2024-09-07 22:56:20 +06:00
for (size_t i = 0; i < numpSections; i++)
{
2024-12-13 18:31:55 +03:00
if (psections[i].p_type == ByteSwap((Elf32_Word)PT_LOAD))
2024-09-07 22:56:20 +06:00
{
2024-12-13 18:31:55 +03:00
image.base = ByteSwap(psections[i].p_vaddr);
2024-09-07 22:56:20 +06:00
break;
}
}
2024-12-13 18:31:55 +03:00
auto* stringTable = reinterpret_cast<const char*>(data + ByteSwap(sections[stringTableIndex].sh_offset));
2024-09-07 22:56:20 +06:00
for (size_t i = 0; i < numSections; i++)
{
const auto& section = sections[i];
2024-09-21 21:47:34 +03:00
if (section.sh_type == 0)
2024-09-07 22:56:20 +06:00
{
continue;
}
uint8_t flags{};
2024-12-13 18:31:55 +03:00
if (section.sh_flags & ByteSwap(SHF_EXECINSTR))
2024-09-07 22:56:20 +06:00
{
flags |= SectionFlags_Code;
}
2024-12-13 18:31:55 +03:00
auto* name = section.sh_name != 0 ? stringTable + ByteSwap(section.sh_name) : nullptr;
const auto rva = ByteSwap(section.sh_addr) - image.base;
const auto size = ByteSwap(section.sh_size);
2024-09-07 22:56:20 +06:00
2024-12-13 18:31:55 +03:00
image.Map(name, rva, size, flags, image.data.get() + ByteSwap(section.sh_offset));
2024-09-07 22:56:20 +06:00
}
return image;
}