mirror of
https://github.com/InoriRus/Kyty.git
synced 2024-06-15 11:06:56 -04:00
Add support for SELF format
This commit is contained in:
parent
435a26c591
commit
bdbacbe7ad
|
@ -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)
|
||||
|
||||
|
|
|
@ -130,14 +130,34 @@ 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 */
|
||||
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 */
|
||||
|
@ -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;
|
||||
|
@ -269,6 +290,8 @@ private:
|
|||
void Clear();
|
||||
|
||||
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;
|
||||
|
|
|
@ -17,7 +17,8 @@ enum class SymbolType
|
|||
Unknown,
|
||||
Func,
|
||||
Object,
|
||||
TlsModule
|
||||
TlsModule,
|
||||
NoType,
|
||||
};
|
||||
|
||||
struct SymbolRecord
|
||||
|
|
|
@ -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);
|
||||
|
||||
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,13 +306,17 @@ 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_self = nullptr;
|
||||
m_self_segments = nullptr;
|
||||
m_ehdr = nullptr;
|
||||
m_phdr = nullptr;
|
||||
m_shdr = nullptr;
|
||||
|
@ -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_self = load_self(*m_f);
|
||||
|
||||
if (!IsSelf())
|
||||
{
|
||||
delete m_self;
|
||||
m_self = nullptr;
|
||||
m_f->Seek(0);
|
||||
} else
|
||||
{
|
||||
m_self_segments = load_self_segments(*m_f, m_self->segments_num);
|
||||
}
|
||||
|
||||
auto ehdr_pos = m_f->Tell();
|
||||
|
||||
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);
|
||||
|
||||
if (!IsValid())
|
||||
{
|
||||
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_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));
|
||||
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));
|
||||
}
|
||||
|
||||
for (Elf64_Half i = 0; i < m_ehdr->e_phnum; i++)
|
||||
{
|
||||
if (m_phdr[i].p_type == PT_DYNAMIC)
|
||||
{
|
||||
m_dynamic = load_dynamic_64(*m_f, m_phdr[i].p_offset, m_phdr[i].p_filesz);
|
||||
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(*m_f, m_phdr[i].p_offset, m_phdr[i].p_filesz);
|
||||
m_dynamic_data = load_dynamic_64(this, m_phdr[i].p_offset, m_phdr[i].p_filesz);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()))
|
||||
{
|
||||
|
|
|
@ -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,6 +291,10 @@ 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:
|
||||
|
@ -292,8 +305,10 @@ static RelocationInfo GetRelocationInfo(Elf64_Rela* r, Program* program)
|
|||
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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue