Add support for SELF format

This commit is contained in:
InoriRus 2021-12-30 14:34:17 +10:00
parent 435a26c591
commit bdbacbe7ad
7 changed files with 283 additions and 96 deletions

View file

@ -79,7 +79,7 @@ if (KYTY_LINKER STREQUAL LD)
set(KYTY_LD_OPTIONS "-Wl,--image-base=0x100000000000")
endif()
project(Kyty${KYTY_PROJECT_NAME}${CMAKE_BUILD_TYPE}${KYTY_COMPILER} VERSION 0.0.5)
project(Kyty${KYTY_PROJECT_NAME}${CMAKE_BUILD_TYPE}${KYTY_COMPILER} VERSION 0.0.6)
include(src_script.cmake)

View file

@ -130,27 +130,47 @@ constexpr uint8_t STB_LOCAL = 0;
constexpr uint8_t STB_GLOBAL = 1;
constexpr uint8_t STB_WEAK = 2;
constexpr uint8_t STT_NOTYPE = 0;
constexpr uint8_t STT_OBJECT = 1;
constexpr uint8_t STT_FUNC = 2;
#pragma pack(1)
struct SelfHeader
{
uint8_t ident[12];
uint16_t size1;
uint16_t size2;
uint64_t file_size;
uint16_t segments_num;
uint16_t unknown;
uint32_t pad;
};
struct SelfSegment
{
uint64_t type;
uint64_t offset;
uint64_t compressed_size;
uint64_t decompressed_size;
};
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 */
uint8_t 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)
@ -239,6 +259,7 @@ public:
const char* GetSectionName(int index) { return m_str_table + m_shdr[index].sh_name; }
[[nodiscard]] bool IsSelf() const;
[[nodiscard]] bool IsValid() const;
[[nodiscard]] bool IsShared() const;
[[nodiscard]] bool IsNextGen() const;
@ -268,13 +289,15 @@ public:
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;
Core::File* m_f = nullptr;
SelfHeader* m_self = nullptr;
SelfSegment* m_self_segments = 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;
};

View file

@ -17,7 +17,8 @@ enum class SymbolType
Unknown,
Func,
Object,
TlsModule
TlsModule,
NoType,
};
struct SymbolRecord

View file

@ -7,8 +7,36 @@
namespace Kyty::Loader {
static SelfHeader* load_self(Core::File& f)
{
if (f.Remaining() < sizeof(SelfHeader))
{
return nullptr;
}
auto* self = new SelfHeader;
f.Read(self, sizeof(SelfHeader));
return self;
}
static SelfSegment* load_self_segments(Core::File& f, uint16_t num)
{
auto* segs = new SelfSegment[num];
f.Read(segs, sizeof(SelfSegment) * num);
return segs;
}
static Elf64_Ehdr* load_ehdr_64(Core::File& f)
{
if (f.Remaining() < sizeof(Elf64_Ehdr))
{
return nullptr;
}
auto* ehdr = new Elf64_Ehdr;
f.Read(ehdr, sizeof(Elf64_Ehdr));
@ -41,12 +69,14 @@ static Elf64_Shdr* load_shdr_64(Core::File& f, uint64_t offset, Elf64_Half num)
return shdr;
}
static void* load_dynamic_64(Core::File& f, uint64_t offset, uint64_t size)
static void* load_dynamic_64(Elf64* f, uint64_t offset, uint64_t size)
{
void* dynamic_data = new uint8_t[size];
f.Seek(offset);
f.Read(dynamic_data, size);
// f.Seek(offset);
// f.Read(dynamic_data, size);
f->LoadSegment(reinterpret_cast<uint64_t>(dynamic_data), offset, size);
return dynamic_data;
}
@ -187,8 +217,51 @@ void Elf64::LoadSegment(uint64_t vaddr, uint64_t file_offset, uint64_t size)
{
EXIT_IF(m_f == nullptr);
m_f->Seek(file_offset);
m_f->Read(reinterpret_cast<void*>(static_cast<uintptr_t>(vaddr)), size);
if (m_self != nullptr)
{
EXIT_IF(m_self_segments == nullptr);
EXIT_IF(m_phdr == nullptr);
for (uint16_t i = 0; i < m_self->segments_num; i++)
{
const auto& seg = m_self_segments[i];
if ((seg.type & 0x800u) != 0)
{
auto phdr_id = ((seg.type >> 20u) & 0xFFFu);
const auto& phdr = m_phdr[phdr_id];
if (file_offset >= phdr.p_offset && file_offset < phdr.p_offset + phdr.p_filesz)
{
EXIT_NOT_IMPLEMENTED(seg.decompressed_size != phdr.p_filesz);
EXIT_NOT_IMPLEMENTED(seg.compressed_size != seg.decompressed_size);
auto offset = file_offset - phdr.p_offset;
EXIT_NOT_IMPLEMENTED(offset + size > seg.decompressed_size);
m_f->Seek(offset + seg.offset);
m_f->Read(reinterpret_cast<void*>(static_cast<uintptr_t>(vaddr)), size);
return;
}
}
}
if (m_f->Size() - m_self->file_size == size)
{
m_f->Seek(m_self->file_size);
m_f->Read(reinterpret_cast<void*>(static_cast<uintptr_t>(vaddr)), size);
return;
}
EXIT("missing self segment\n");
} else
{
m_f->Seek(file_offset);
m_f->Read(reinterpret_cast<void*>(static_cast<uintptr_t>(vaddr)), size);
}
}
const Elf64_Dyn* Elf64::GetDynValue(Elf64_Sxword tag) const
@ -233,19 +306,23 @@ void Elf64::Clear()
m_f->Close();
delete m_f;
}
delete m_self;
delete m_ehdr;
delete[] m_self_segments;
delete[] m_phdr;
delete[] m_shdr;
delete[] m_str_table;
delete[] static_cast<uint8_t*>(m_dynamic);
delete[] static_cast<uint8_t*>(m_dynamic_data);
m_ehdr = nullptr;
m_phdr = nullptr;
m_shdr = nullptr;
m_str_table = nullptr;
m_dynamic = nullptr;
m_dynamic_data = nullptr;
m_self = nullptr;
m_self_segments = nullptr;
m_ehdr = nullptr;
m_phdr = nullptr;
m_shdr = nullptr;
m_str_table = nullptr;
m_dynamic = nullptr;
m_dynamic_data = nullptr;
}
void Elf64::DbgDump(const String& folder)
@ -269,8 +346,11 @@ void Elf64::DbgDump(const String& folder)
auto* buf = new char[static_cast<uint32_t>(m_phdr[i].p_filesz)];
m_f->Seek(m_phdr[i].p_offset);
m_f->Read(buf, static_cast<uint32_t>(m_phdr[i].p_filesz));
// m_f->Seek(m_phdr[i].p_offset);
// m_f->Read(buf, static_cast<uint32_t>(m_phdr[i].p_filesz));
LoadSegment(reinterpret_cast<uint64_t>(buf), m_phdr[i].p_offset, m_phdr[i].p_filesz);
fout.Write(buf, static_cast<uint32_t>(m_phdr[i].p_filesz));
delete[] buf;
@ -337,10 +417,46 @@ uint64_t Elf64::GetEntry()
return m_ehdr->e_entry;
}
bool Elf64::IsSelf() const
{
if (m_f == nullptr || m_f->IsInvalid())
{
return false;
}
if (m_self == nullptr)
{
return false;
}
if (m_self->ident[0] != 0x4f || m_self->ident[1] != 0x15 || m_self->ident[2] != 0x3d || m_self->ident[3] != 0x1d)
{
return false;
}
if (m_self->ident[4] != 0x00 || m_self->ident[5] != 0x01 || m_self->ident[6] != 0x01 || m_self->ident[7] != 0x12)
{
printf("Unknown SELF file\n");
return false;
}
if (m_self->ident[8] != 0x01 || m_self->ident[9] != 0x01 || m_self->ident[10] != 0x00 || m_self->ident[11] != 0x00)
{
printf("Unknown SELF file\n");
return false;
}
if (m_self->unknown != 0x22)
{
printf("Unknown SELF file\n");
return false;
}
return true;
}
bool Elf64::IsValid() const
{
bool ret = true;
if (m_f == nullptr || m_f->IsInvalid())
{
return false;
@ -418,7 +534,7 @@ bool Elf64::IsValid() const
return false;
}
return ret;
return true;
}
void Elf64::Open(const String& file_name)
@ -433,25 +549,52 @@ void Elf64::Open(const String& file_name)
EXIT("Can't open %s\n", file_name.C_Str());
}
m_ehdr = load_ehdr_64(*m_f);
m_phdr = load_phdr_64(*m_f, m_ehdr->e_phoff, m_ehdr->e_phnum);
m_shdr = load_shdr_64(*m_f, m_ehdr->e_shoff, m_ehdr->e_shnum);
m_self = load_self(*m_f);
if (m_shdr != nullptr)
if (!IsSelf())
{
m_str_table = load_str_table(*m_f, m_shdr[m_ehdr->e_shstrndx].sh_offset, static_cast<uint32_t>(m_shdr[m_ehdr->e_shstrndx].sh_size));
delete m_self;
m_self = nullptr;
m_f->Seek(0);
} else
{
m_self_segments = load_self_segments(*m_f, m_self->segments_num);
}
for (Elf64_Half i = 0; i < m_ehdr->e_phnum; i++)
auto ehdr_pos = m_f->Tell();
m_ehdr = load_ehdr_64(*m_f);
if (!IsValid())
{
if (m_phdr[i].p_type == PT_DYNAMIC)
delete m_ehdr;
m_ehdr = nullptr;
}
if (m_ehdr != nullptr /*&& m_self == nullptr*/)
{
m_phdr = load_phdr_64(*m_f, ehdr_pos + m_ehdr->e_phoff, m_ehdr->e_phnum);
m_shdr = load_shdr_64(*m_f, ehdr_pos + m_ehdr->e_shoff, m_ehdr->e_shnum);
EXIT_NOT_IMPLEMENTED(m_shdr != nullptr && m_self != nullptr);
if (m_shdr != nullptr)
{
m_dynamic = load_dynamic_64(*m_f, m_phdr[i].p_offset, m_phdr[i].p_filesz);
m_str_table =
load_str_table(*m_f, m_shdr[m_ehdr->e_shstrndx].sh_offset, static_cast<uint32_t>(m_shdr[m_ehdr->e_shstrndx].sh_size));
}
if (m_phdr[i].p_type == PT_OS_DYNLIBDATA)
for (Elf64_Half i = 0; i < m_ehdr->e_phnum; i++)
{
m_dynamic_data = load_dynamic_64(*m_f, m_phdr[i].p_offset, m_phdr[i].p_filesz);
if (m_phdr[i].p_type == PT_DYNAMIC)
{
m_dynamic = load_dynamic_64(this, m_phdr[i].p_offset, m_phdr[i].p_filesz);
}
if (m_phdr[i].p_type == PT_OS_DYNLIBDATA)
{
m_dynamic_data = load_dynamic_64(this, m_phdr[i].p_offset, m_phdr[i].p_filesz);
}
}
}
}

View file

@ -34,6 +34,8 @@ namespace LuaFunc {
static void load_symbols(const String& id, Loader::RuntimeLinker* rt)
{
KYTY_PROFILER_FUNCTION();
EXIT_IF(rt == nullptr);
if (!Libs::Init(id, rt->Symbols()))
{

View file

@ -126,10 +126,11 @@ static void dbg_dump_rela(const String& folder, Elf64_Rela* records, uint64_t si
for (auto* r = records; reinterpret_cast<uint8_t*>(r) < reinterpret_cast<uint8_t*>(records) + size; r++)
{
f.Printf("----\n");
f.Printf("r_offset = 0x%016" PRIx64 "\n", r->r_offset);
f.Printf("r_info = 0x%016" PRIx64 "\n", r->r_info);
f.Printf("r_addend = %" PRId64 "\n", r->r_addend);
f.Printf("----\n"
"r_offset = 0x%016" PRIx64 "\n"
"r_info = 0x%016" PRIx64 "\n"
"r_addend = %" PRId64 "\n",
r->r_offset, r->r_info, r->r_addend);
}
f.Close();
@ -270,8 +271,16 @@ static void get_dyn_libs(Elf64* elf, T* out, const char* names, Elf64_Sxword tag
static RelocationInfo GetRelocationInfo(Elf64_Rela* r, Program* program)
{
KYTY_PROFILER_FUNCTION();
// KYTY_PROFILER_BLOCK("1");
RelocationInfo ret;
SymbolRecord sr {};
// SymbolRecord sr {};
// KYTY_PROFILER_END_BLOCK;
// KYTY_PROFILER_BLOCK("2");
auto type = r->GetType();
auto symbol = r->GetSymbol();
@ -282,18 +291,24 @@ static RelocationInfo GetRelocationInfo(Elf64_Rela* r, Program* program)
ret.vaddr = ret.base_vaddr + r->r_offset;
ret.bind_self = false;
// KYTY_PROFILER_END_BLOCK;
// KYTY_PROFILER_BLOCK("3");
switch (type)
{
case R_X86_64_GLOB_DAT:
case R_X86_64_JUMP_SLOT: addend = 0; [[fallthrough]];
case R_X86_64_64:
{
auto sym = symbols[symbol];
auto bind = sym.GetBind();
auto sym_type = sym.GetType();
uint64_t symbol_vaddr = 0;
auto sym = symbols[symbol];
auto bind = sym.GetBind();
auto sym_type = sym.GetType();
uint64_t symbol_vaddr = 0;
SymbolRecord sr {};
switch (sym_type)
{
case STT_NOTYPE: ret.type = SymbolType::NoType; break;
case STT_FUNC: ret.type = SymbolType::Func; break;
case STT_OBJECT: ret.type = SymbolType::Object; break;
default: EXIT("unknown symbol type: %d\n", (int)sym_type);
@ -334,19 +349,22 @@ static RelocationInfo GetRelocationInfo(Elf64_Rela* r, Program* program)
break;
default: EXIT("unknown type: %d\n", (int)type);
}
// KYTY_PROFILER_END_BLOCK;
return ret;
}
static void relocate(uint32_t index, Elf64_Rela* r, Program* program, bool jmprela_table)
{
KYTY_PROFILER_FUNCTION();
auto ri = GetRelocationInfo(r, program);
auto dbg_str = String::FromPrintf("[%016" PRIx64 "] <- %s%016" PRIx64 "%s, %s, %s, %s, %s", ri.vaddr,
ri.value == 0 ? FG_BRIGHT_RED : FG_BRIGHT_GREEN, ri.value, DEFAULT, ri.name.C_Str(),
Core::EnumName(ri.type).C_Str(), Core::EnumName(ri.bind).C_Str(), ri.dbg_name.C_Str());
[[maybe_unused]] bool patched = false;
// KYTY_PROFILER_BLOCK("patch");
if (ri.resolved)
{
patched = VirtualMemory::PatchReplace(ri.vaddr, ri.value);
@ -367,7 +385,7 @@ static void relocate(uint32_t index, Elf64_Rela* r, Program* program, bool jmpre
{
value = RuntimeLinker::ReadFromElf(program, ri.vaddr) + ri.base_vaddr;
}
} else if (ri.type == SymbolType::Func && !jmprela_table && weak)
} else if ((ri.type == SymbolType::Func && !jmprela_table && weak) || (ri.type == SymbolType::NoType && weak))
{
value = RuntimeLinker::ReadFromElf(program, ri.vaddr) + ri.base_vaddr;
}
@ -377,15 +395,25 @@ static void relocate(uint32_t index, Elf64_Rela* r, Program* program, bool jmpre
patched = VirtualMemory::PatchReplace(ri.vaddr, value);
} else
{
auto dbg_str = String::FromPrintf("[%016" PRIx64 "] <- %s%016" PRIx64 "%s, %s, %s, %s, %s", ri.vaddr,
ri.value == 0 ? FG_BRIGHT_RED : FG_BRIGHT_GREEN, ri.value, DEFAULT, ri.name.C_Str(),
Core::EnumName(ri.type).C_Str(), Core::EnumName(ri.bind).C_Str(), ri.dbg_name.C_Str());
EXIT("Can't resolve: %s\n", (Log::IsColoredPrintf() ? dbg_str : Log::RemoveColors(dbg_str)).C_Str());
}
}
// KYTY_PROFILER_END_BLOCK;
if (program->dbg_print_reloc)
{
if (/* !dbg_str.ContainsStr(U"libc_") && */ patched && !ri.bind_self &&
(ri.bind == BindType::Global || ri.bind == BindType::Weak || ri.type == SymbolType::TlsModule))
{
auto dbg_str = String::FromPrintf("[%016" PRIx64 "] <- %s%016" PRIx64 "%s, %s, %s, %s, %s", ri.vaddr,
ri.value == 0 ? FG_BRIGHT_RED : FG_BRIGHT_GREEN, ri.value, DEFAULT, ri.name.C_Str(),
Core::EnumName(ri.type).C_Str(), Core::EnumName(ri.bind).C_Str(), ri.dbg_name.C_Str());
printf("Relocate: %s\n", dbg_str.C_Str());
}
}
@ -393,6 +421,8 @@ static void relocate(uint32_t index, Elf64_Rela* r, Program* program, bool jmpre
static void relocate_all(Elf64_Rela* records, uint64_t size, Program* program, bool jmprela_table)
{
KYTY_PROFILER_FUNCTION();
uint32_t index = 0;
for (auto* r = records; reinterpret_cast<uint8_t*>(r) < reinterpret_cast<uint8_t*>(records) + size; r++, index++)
{
@ -500,6 +530,8 @@ uint64_t RuntimeLinker::GetProcParam()
void RuntimeLinker::DbgDump(const String& folder)
{
KYTY_PROFILER_FUNCTION();
EXIT_NOT_IMPLEMENTED(!Core::Thread::IsMainThread());
Core::LockGuard lock(m_mutex);
@ -598,7 +630,7 @@ RuntimeLinker::~RuntimeLinker()
Program* RuntimeLinker::LoadProgram(const String& elf_name)
{
// EXIT_NOT_IMPLEMENTED(!Core::Thread::IsMainThread());
KYTY_PROFILER_FUNCTION();
Core::LockGuard lock(m_mutex);
@ -698,7 +730,7 @@ void RuntimeLinker::Execute()
void RuntimeLinker::Resolve(const String& name, SymbolType type, Program* program, SymbolRecord* out_info, bool* bind_self)
{
// EXIT_NOT_IMPLEMENTED(!Core::Thread::IsMainThread());
KYTY_PROFILER_FUNCTION();
Core::LockGuard lock(m_mutex);
@ -770,8 +802,6 @@ void RuntimeLinker::Resolve(const String& name, SymbolType type, Program* progra
uint64_t RuntimeLinker::ReadFromElf(Program* program, uint64_t vaddr)
{
// EXIT_NOT_IMPLEMENTED(!Core::Thread::IsMainThread());
EXIT_IF(program == nullptr);
EXIT_IF(program->base_vaddr == 0 || program->base_size == 0);
EXIT_IF(program->elf == nullptr);
@ -963,6 +993,8 @@ static uint64_t calc_base_size(const Elf64_Ehdr* ehdr, const Elf64_Phdr* phdr)
void RuntimeLinker::LoadProgramToMemory(Program* program)
{
KYTY_PROFILER_FUNCTION();
EXIT_IF(program == nullptr || program->base_vaddr != 0 || program->base_size != 0 || program->elf == nullptr ||
program->exception_handler != nullptr);
@ -981,16 +1013,16 @@ void RuntimeLinker::LoadProgramToMemory(Program* program)
uint64_t exception_handler_size = VirtualMemory::ExceptionHandler::GetSize();
uint64_t tls_handler_size = is_shared ? 0 : Jit::SafeCall::GetSize();
uint64_t alloc_size = program->base_size_aligned + exception_handler_size + tls_handler_size;
program->base_vaddr = VirtualMemory::Alloc(desired_base_addr, program->base_size_aligned + exception_handler_size + tls_handler_size,
VirtualMemory::Mode::ExecuteReadWrite);
program->base_vaddr = VirtualMemory::Alloc(desired_base_addr, alloc_size, VirtualMemory::Mode::ExecuteReadWrite);
if (!is_shared)
{
program->tls.handler_vaddr = program->base_vaddr + program->base_size_aligned + exception_handler_size;
}
desired_base_addr += DESIRED_BASE_ADDR;
desired_base_addr += DESIRED_BASE_ADDR * (1 + alloc_size / DESIRED_BASE_ADDR);
EXIT_IF(program->base_vaddr == 0);
EXIT_IF(program->base_size_aligned < program->base_size);
@ -1107,34 +1139,10 @@ void RuntimeLinker::DeleteProgram(Program* p)
delete p;
}
// void RuntimeLinker::Initialize() const
//{
// EXIT_NOT_IMPLEMENTED(m_program.dynamic_info != nullptr && m_program.dynamic_info->init_array_size != 0);
// EXIT_NOT_IMPLEMENTED(m_program.dynamic_info != nullptr && m_program.dynamic_info->preinit_array_size != 0);
//
// if (auto addr = GetInit(); addr != 0)
// {
// run_init(addr);
// }
//}
// static void KYTY_SYSV_ABI ProgramFunctionNotFoundHandler()
//{
// EXIT("Function not found\n");
//}
// void RuntimeLinker::Terminate() const
//{
// EXIT_NOT_IMPLEMENTED(m_program.dynamic_info != nullptr && m_program.dynamic_info->fini_array_size != 0);
//
// if (auto addr = GetFini(); addr != 0)
// {
// run_fini(addr);
// }
//}
void RuntimeLinker::ParseProgramDynamicInfo(Program* program)
{
KYTY_PROFILER_FUNCTION();
EXIT_IF(program == nullptr);
EXIT_IF(program->elf == nullptr);
EXIT_IF(program->dynamic_info != nullptr);
@ -1236,6 +1244,8 @@ void RuntimeLinker::ParseProgramDynamicInfo(Program* program)
static void InstallRelocateHandler(Program* program)
{
KYTY_PROFILER_FUNCTION();
uint64_t pltgot_vaddr = program->dynamic_info->pltgot_vaddr + program->base_vaddr;
uint64_t pltgot_size = 3 * 8;
void** pltgot = reinterpret_cast<void**>(pltgot_vaddr);
@ -1268,6 +1278,8 @@ static void InstallRelocateHandler(Program* program)
void RuntimeLinker::Relocate(Program* program)
{
KYTY_PROFILER_FUNCTION();
EXIT_IF(program == nullptr);
printf("--- Relocate program: " FG_WHITE BOLD "%s" DEFAULT " ---\n", program->file_name.C_Str());
@ -1344,6 +1356,8 @@ const LibraryId* RuntimeLinker::FindLibrary(const Program& program, const String
void RuntimeLinker::CreateSymbolDatabase(Program* program)
{
KYTY_PROFILER_FUNCTION();
EXIT_IF(program == nullptr);
EXIT_IF(program->export_symbols != nullptr);
EXIT_IF(program->import_symbols != nullptr);
@ -1385,6 +1399,7 @@ void RuntimeLinker::CreateSymbolDatabase(Program* program)
sr.module_version_minor = m->version_minor;
switch (type)
{
case STT_NOTYPE: sr.type = SymbolType::NoType; break;
case STT_FUNC: sr.type = SymbolType::Func; break;
case STT_OBJECT: sr.type = SymbolType::Object; break;
default: sr.type = SymbolType::Unknown; break;

View file

@ -4,6 +4,7 @@
#include "Emulator/Common.h"
#include "Emulator/Jit.h"
#include "Emulator/Profiler.h"
#include <new>
@ -315,6 +316,8 @@ bool FlushInstructionCache(uint64_t address, uint64_t size)
bool PatchReplace(uint64_t vaddr, uint64_t value)
{
KYTY_PROFILER_FUNCTION();
VirtualMemory::Mode old_mode {};
VirtualMemory::Protect(vaddr, 8, VirtualMemory::Mode::ReadWrite, &old_mode);