mirror of https://github.com/InoriRus/Kyty.git
286 lines
10 KiB
C
286 lines
10 KiB
C
![]() |
#ifndef EMULATOR_INCLUDE_EMULATOR_ELF_H_
|
||
|
#define EMULATOR_INCLUDE_EMULATOR_ELF_H_
|
||
|
|
||
|
#include "Kyty/Core/Common.h"
|
||
|
#include "Kyty/Core/String.h"
|
||
|
#include "Kyty/Core/Vector.h"
|
||
|
|
||
|
#include "Emulator/Common.h"
|
||
|
|
||
|
namespace Kyty::Core {
|
||
|
class File;
|
||
|
} // namespace Kyty::Core
|
||
|
|
||
|
#ifdef KYTY_EMU_ENABLED
|
||
|
|
||
|
namespace Kyty::Loader {
|
||
|
|
||
|
using Elf64_Addr = uint64_t; // Unsigned program address
|
||
|
using Elf64_Off = uint64_t; // Unsigned file offset
|
||
|
using Elf64_Half = uint16_t; // Unsigned medium integer
|
||
|
using Elf64_Word = uint32_t; // Unsigned integer
|
||
|
using Elf64_Sword = int32_t; // Signed integer
|
||
|
using Elf64_Xword = uint64_t; // Unsigned long integer
|
||
|
using Elf64_Sxword = int64_t; // Signed long integer
|
||
|
|
||
|
constexpr int EI_MAG0 = 0;
|
||
|
constexpr int EI_MAG1 = 1;
|
||
|
constexpr int EI_MAG2 = 2;
|
||
|
constexpr int EI_MAG3 = 3;
|
||
|
constexpr int EI_CLASS = 4;
|
||
|
constexpr int EI_DATA = 5;
|
||
|
constexpr int EI_VERSION = 6;
|
||
|
constexpr int EI_OSABI = 7;
|
||
|
constexpr int EI_ABIVERSION = 8;
|
||
|
constexpr int EI_PAD = 9;
|
||
|
constexpr int EI_NIDENT = 16;
|
||
|
|
||
|
constexpr char ELFCLASS64 = 2; // 64-bit objects
|
||
|
|
||
|
constexpr char ELFDATA2LSB = 1; // Object file data structures are little-endian
|
||
|
|
||
|
constexpr Elf64_Half EM_X86_64 = 62; /* AMD x86-64 architecture */
|
||
|
|
||
|
constexpr int EV_CURRENT = 1;
|
||
|
|
||
|
constexpr char ELFOSABI_FREEBSD = 9; // FreeBSD operating system
|
||
|
|
||
|
constexpr Elf64_Half ET_DYNEXEC = 0xfe10; // Executable file
|
||
|
constexpr Elf64_Half ET_DYNAMIC = 0xfe18; // Shared
|
||
|
|
||
|
//#define SHT_PROGBITS 1
|
||
|
|
||
|
constexpr Elf64_Word PT_LOAD = 1;
|
||
|
constexpr Elf64_Word PT_DYNAMIC = 2;
|
||
|
constexpr Elf64_Word PT_TLS = 7;
|
||
|
constexpr Elf64_Word PT_OS_DYNLIBDATA = 0x61000000;
|
||
|
constexpr Elf64_Word PT_OS_PROCPARAM = 0x61000001;
|
||
|
constexpr Elf64_Word PT_OS_RELRO = 0x61000010;
|
||
|
|
||
|
constexpr Elf64_Word PF_X = 0x1; // Execute
|
||
|
constexpr Elf64_Word PF_W = 0x2; // Write
|
||
|
constexpr Elf64_Word PF_R = 0x4; // Read
|
||
|
|
||
|
constexpr Elf64_Sxword DT_DEBUG = 0x00000015;
|
||
|
constexpr Elf64_Sxword DT_FINI = 0x0000000d;
|
||
|
constexpr Elf64_Sxword DT_FINI_ARRAY = 0x0000001a;
|
||
|
constexpr Elf64_Sxword DT_FINI_ARRAYSZ = 0x0000001c;
|
||
|
constexpr Elf64_Sxword DT_FLAGS = 0x0000001e;
|
||
|
constexpr Elf64_Sxword DT_INIT = 0x0000000c;
|
||
|
constexpr Elf64_Sxword DT_INIT_ARRAY = 0x00000019;
|
||
|
constexpr Elf64_Sxword DT_INIT_ARRAYSZ = 0x0000001b;
|
||
|
constexpr Elf64_Sxword DT_NEEDED = 0x00000001;
|
||
|
constexpr Elf64_Sxword DT_OS_EXPORT_LIB = 0x61000013;
|
||
|
constexpr Elf64_Sxword DT_OS_EXPORT_LIB_1 = 0x61000047;
|
||
|
constexpr Elf64_Sxword DT_OS_EXPORT_LIB_ATTR = 0x61000017;
|
||
|
constexpr Elf64_Sxword DT_OS_FINGERPRINT = 0x61000007;
|
||
|
constexpr Elf64_Sxword DT_OS_HASH = 0x61000025;
|
||
|
constexpr Elf64_Sxword DT_OS_HASHSZ = 0x6100003d;
|
||
|
constexpr Elf64_Sxword DT_OS_IMPORT_LIB = 0x61000015;
|
||
|
constexpr Elf64_Sxword DT_OS_IMPORT_LIB_1 = 0x61000049;
|
||
|
constexpr Elf64_Sxword DT_OS_IMPORT_LIB_ATTR = 0x61000019;
|
||
|
constexpr Elf64_Sxword DT_OS_JMPREL = 0x61000029;
|
||
|
constexpr Elf64_Sxword DT_OS_MODULE_ATTR = 0x61000011;
|
||
|
constexpr Elf64_Sxword DT_OS_MODULE_INFO = 0x6100000d;
|
||
|
constexpr Elf64_Sxword DT_OS_MODULE_INFO_1 = 0x61000043;
|
||
|
constexpr Elf64_Sxword DT_OS_NEEDED_MODULE = 0x6100000f;
|
||
|
constexpr Elf64_Sxword DT_OS_NEEDED_MODULE_1 = 0x61000045;
|
||
|
constexpr Elf64_Sxword DT_OS_ORIGINAL_FILENAME = 0x61000009;
|
||
|
constexpr Elf64_Sxword DT_OS_ORIGINAL_FILENAME_1 = 0x61000041;
|
||
|
constexpr Elf64_Sxword DT_OS_PLTGOT = 0x61000027;
|
||
|
constexpr Elf64_Sxword DT_OS_PLTREL = 0x6100002b;
|
||
|
constexpr Elf64_Sxword DT_OS_PLTRELSZ = 0x6100002d;
|
||
|
constexpr Elf64_Sxword DT_OS_RELA = 0x6100002f;
|
||
|
constexpr Elf64_Sxword DT_OS_RELAENT = 0x61000033;
|
||
|
constexpr Elf64_Sxword DT_OS_RELASZ = 0x61000031;
|
||
|
constexpr Elf64_Sxword DT_OS_STRSZ = 0x61000037;
|
||
|
constexpr Elf64_Sxword DT_OS_STRTAB = 0x61000035;
|
||
|
constexpr Elf64_Sxword DT_OS_SYMENT = 0x6100003b;
|
||
|
constexpr Elf64_Sxword DT_OS_SYMTAB = 0x61000039;
|
||
|
constexpr Elf64_Sxword DT_OS_SYMTABSZ = 0x6100003f;
|
||
|
constexpr Elf64_Sxword DT_PREINIT_ARRAY = 0x00000020;
|
||
|
constexpr Elf64_Sxword DT_PREINIT_ARRAYSZ = 0x00000021;
|
||
|
constexpr Elf64_Sxword DT_REL = 0x00000011;
|
||
|
constexpr Elf64_Sxword DT_RELA = 0x00000007;
|
||
|
constexpr Elf64_Sxword DT_SONAME = 0x0000000e;
|
||
|
constexpr Elf64_Sxword DT_TEXTREL = 0x00000016;
|
||
|
|
||
|
constexpr Elf64_Sxword DT_HASH = 0x00000004;
|
||
|
constexpr Elf64_Sxword DT_STRTAB = 0x00000005;
|
||
|
constexpr Elf64_Sxword DT_STRSZ = 0x0000000a;
|
||
|
constexpr Elf64_Sxword DT_SYMTAB = 0x00000006;
|
||
|
constexpr Elf64_Sxword DT_SYMENT = 0x0000000b;
|
||
|
constexpr Elf64_Sxword DT_PLTGOT = 0x00000003;
|
||
|
constexpr Elf64_Sxword DT_PLTREL = 0x00000014;
|
||
|
constexpr Elf64_Sxword DT_JMPREL = 0x00000017;
|
||
|
constexpr Elf64_Sxword DT_PLTRELSZ = 0x00000002;
|
||
|
constexpr Elf64_Sxword DT_RELASZ = 0x00000008;
|
||
|
constexpr Elf64_Sxword DT_RELAENT = 0x00000009;
|
||
|
constexpr Elf64_Sxword DT_RELACOUNT = 0x6ffffff9;
|
||
|
|
||
|
constexpr Elf64_Sxword DT_NULL = 0;
|
||
|
|
||
|
constexpr Elf64_Word R_X86_64_64 = 1;
|
||
|
constexpr Elf64_Word R_X86_64_GLOB_DAT = 6;
|
||
|
constexpr Elf64_Word R_X86_64_JUMP_SLOT = 7;
|
||
|
constexpr Elf64_Word R_X86_64_RELATIVE = 8;
|
||
|
constexpr Elf64_Word R_X86_64_DTPMOD64 = 16;
|
||
|
|
||
|
constexpr uint8_t STB_LOCAL = 0;
|
||
|
constexpr uint8_t STB_GLOBAL = 1;
|
||
|
constexpr uint8_t STB_WEAK = 2;
|
||
|
|
||
|
constexpr uint8_t STT_OBJECT = 1;
|
||
|
constexpr uint8_t STT_FUNC = 2;
|
||
|
|
||
|
#pragma pack(1)
|
||
|
|
||
|
struct Elf64_Ehdr // NOLINT(readability-identifier-naming)
|
||
|
{
|
||
|
unsigned char e_ident[EI_NIDENT]; /* ELF identification */
|
||
|
Elf64_Half e_type; /* Object file type */
|
||
|
Elf64_Half e_machine; /* Machine type */
|
||
|
Elf64_Word e_version; /* Object file version */
|
||
|
Elf64_Addr e_entry; /* Entry point address */
|
||
|
Elf64_Off e_phoff; /* Program header offset */
|
||
|
Elf64_Off e_shoff; /* Section header offset */
|
||
|
Elf64_Word e_flags; /* Processor-specific flags */
|
||
|
Elf64_Half e_ehsize; /* ELF header size */
|
||
|
Elf64_Half e_phentsize; /* Size of program header entry */
|
||
|
Elf64_Half e_phnum; /* Number of program header entries */
|
||
|
Elf64_Half e_shentsize; /* Size of section header entry */
|
||
|
Elf64_Half e_shnum; /* Number of section header entries */
|
||
|
Elf64_Half e_shstrndx; /* Section name string table index */
|
||
|
};
|
||
|
|
||
|
struct Elf64_Phdr // NOLINT(readability-identifier-naming)
|
||
|
{
|
||
|
Elf64_Word p_type; /* Type of segment */
|
||
|
Elf64_Word p_flags; /* Segment attributes */
|
||
|
Elf64_Off p_offset; /* Offset in file */
|
||
|
Elf64_Addr p_vaddr; /* Virtual address in memory */
|
||
|
Elf64_Addr p_paddr; /* Reserved */
|
||
|
Elf64_Xword p_filesz; /* Size of segment in file */
|
||
|
Elf64_Xword p_memsz; /* Size of segment in memory */
|
||
|
Elf64_Xword p_align; /* Alignment of segment */
|
||
|
};
|
||
|
|
||
|
struct Elf64_Shdr // NOLINT(readability-identifier-naming)
|
||
|
{
|
||
|
Elf64_Word sh_name; /* Section name */
|
||
|
Elf64_Word sh_type; /* Section type */
|
||
|
Elf64_Xword sh_flags; /* Section attributes */
|
||
|
Elf64_Addr sh_addr; /* Virtual address in memory */
|
||
|
Elf64_Off sh_offset; /* Offset in file */
|
||
|
Elf64_Xword sh_size; /* Size of section */
|
||
|
Elf64_Word sh_link; /* Link to other section */
|
||
|
Elf64_Word sh_info; /* Miscellaneous information */
|
||
|
Elf64_Xword sh_addralign; /* Address alignment boundary */
|
||
|
Elf64_Xword sh_entsize; /* Size of entries, if section has table */
|
||
|
};
|
||
|
|
||
|
struct Elf64_Dyn // NOLINT(readability-identifier-naming)
|
||
|
{
|
||
|
Elf64_Sxword d_tag;
|
||
|
union
|
||
|
{
|
||
|
Elf64_Xword d_val;
|
||
|
Elf64_Addr d_ptr;
|
||
|
} d_un;
|
||
|
};
|
||
|
|
||
|
struct Elf64_Sym // NOLINT(readability-identifier-naming)
|
||
|
{
|
||
|
[[nodiscard]] unsigned char GetBind() const { return st_info >> 4u; }
|
||
|
[[nodiscard]] unsigned char GetType() const { return st_info & 0xfu; }
|
||
|
|
||
|
Elf64_Word st_name;
|
||
|
unsigned char st_info;
|
||
|
unsigned char st_other;
|
||
|
Elf64_Half st_shndx;
|
||
|
Elf64_Addr st_value;
|
||
|
Elf64_Xword st_size;
|
||
|
};
|
||
|
|
||
|
// struct Elf64_Rel // NOLINT(readability-identifier-naming)
|
||
|
//{
|
||
|
// Elf64_Addr r_offset;
|
||
|
// Elf64_Xword r_info;
|
||
|
//};
|
||
|
|
||
|
struct Elf64_Rela // NOLINT(readability-identifier-naming)
|
||
|
{
|
||
|
[[nodiscard]] Elf64_Word GetSymbol() const { return static_cast<Elf64_Word>(r_info >> 32u); }
|
||
|
[[nodiscard]] Elf64_Word GetType() const { return static_cast<Elf64_Word>(r_info & 0xffffffff); }
|
||
|
|
||
|
Elf64_Addr r_offset;
|
||
|
Elf64_Xword r_info;
|
||
|
Elf64_Sxword r_addend;
|
||
|
};
|
||
|
|
||
|
struct tls_info_t // NOLINT(readability-identifier-naming)
|
||
|
{
|
||
|
uint64_t addr;
|
||
|
uint64_t filesz;
|
||
|
uint64_t memsz;
|
||
|
};
|
||
|
|
||
|
#pragma pack()
|
||
|
|
||
|
class Elf64
|
||
|
{
|
||
|
public:
|
||
|
Elf64() = default;
|
||
|
virtual ~Elf64();
|
||
|
|
||
|
void Open(const String& file_name);
|
||
|
|
||
|
void DbgDump(const String& folder);
|
||
|
|
||
|
const char* GetSectionName(int index) { return m_str_table + m_shdr[index].sh_name; }
|
||
|
|
||
|
[[nodiscard]] bool IsValid() const;
|
||
|
[[nodiscard]] bool IsShared() const;
|
||
|
[[nodiscard]] bool IsNextGen() const;
|
||
|
|
||
|
void LoadSegment(uint64_t vaddr, uint64_t file_offset, uint64_t size);
|
||
|
|
||
|
uint64_t GetEntry();
|
||
|
|
||
|
[[nodiscard]] const Elf64_Dyn* GetDynValue(Elf64_Sxword tag) const;
|
||
|
[[nodiscard]] Vector<const Elf64_Dyn*> GetDynList(Elf64_Sxword tag) const;
|
||
|
[[nodiscard]] bool HasDynValue(Elf64_Sxword tag) const { return GetDynValue(tag) != nullptr; }
|
||
|
|
||
|
KYTY_CLASS_NO_COPY(Elf64);
|
||
|
|
||
|
[[nodiscard]] const Elf64_Dyn* GetDynamic() const { return static_cast<Elf64_Dyn*>(m_dynamic); }
|
||
|
[[nodiscard]] const Elf64_Ehdr* GetEhdr() const { return m_ehdr; }
|
||
|
[[nodiscard]] const Elf64_Phdr* GetPhdr() const { return m_phdr; }
|
||
|
[[nodiscard]] const Elf64_Shdr* GetShdr() const { return m_shdr; }
|
||
|
[[nodiscard]] char* GetStrTable() const { return m_str_table; }
|
||
|
|
||
|
template <class T>
|
||
|
[[nodiscard]] T GetDynamicData(uint64_t offset) const
|
||
|
{
|
||
|
return (m_dynamic_data == nullptr ? nullptr : reinterpret_cast<T>(static_cast<uint8_t*>(m_dynamic_data) + offset));
|
||
|
}
|
||
|
|
||
|
private:
|
||
|
void Clear();
|
||
|
|
||
|
Core::File* m_f = nullptr;
|
||
|
Elf64_Ehdr* m_ehdr = nullptr;
|
||
|
Elf64_Phdr* m_phdr = nullptr;
|
||
|
Elf64_Shdr* m_shdr = nullptr;
|
||
|
void* m_dynamic = nullptr;
|
||
|
void* m_dynamic_data = nullptr;
|
||
|
char* m_str_table = nullptr;
|
||
|
// uint64_t m_base_vaddr = 0;
|
||
|
};
|
||
|
|
||
|
} // namespace Kyty::Loader
|
||
|
|
||
|
#endif // KYTY_EMU_ENABLED
|
||
|
|
||
|
#endif /* EMULATOR_INCLUDE_EMULATOR_ELF_H_ */
|