From 81906c271aa38bcfce59589e3b8a7cf3e3b205a6 Mon Sep 17 00:00:00 2001 From: georgemoralis Date: Tue, 11 Jul 2023 18:50:29 +0300 Subject: [PATCH] resolving relocate function and patching them (successfully done one :D) --- src/Core/PS4/Linker.cpp | 166 ++++++++++++++++-------- src/Core/PS4/Linker.h | 4 + src/Core/PS4/Loader/SymbolsResolver.cpp | 23 +++- src/Core/PS4/Loader/SymbolsResolver.h | 3 + 4 files changed, 137 insertions(+), 59 deletions(-) diff --git a/src/Core/PS4/Linker.cpp b/src/Core/PS4/Linker.cpp index d1922c52..aed80637 100644 --- a/src/Core/PS4/Linker.cpp +++ b/src/Core/PS4/Linker.cpp @@ -70,6 +70,7 @@ static std::string encodeId(u64 nVal) Module* Linker::LoadModule(const std::string& elf_name) { auto* m = new Module; + m->linker = this; m->elf = new Elf; m->elf->Open(elf_name);//load elf @@ -497,68 +498,78 @@ void Linker::LoadSymbols(Module* m) } } } -static void relocate(u32 idx, elf_relocation* rel, Module* m, bool isJmpRel) -{ - auto type = rel->GetType(); - auto symbol = rel->GetSymbol(); - auto addend = rel->rel_addend; - auto* symbolsTlb = m->dynamic_info->symbol_table; - auto* namesTlb = m->dynamic_info->str_table; +static void relocate(u32 idx, elf_relocation* rel, Module* m, bool isJmpRel) { + auto type = rel->GetType(); + auto symbol = rel->GetSymbol(); + auto addend = rel->rel_addend; + auto* symbolsTlb = m->dynamic_info->symbol_table; + auto* namesTlb = m->dynamic_info->str_table; - u64 rel_value = 0; - u64 rel_base_virtual_addr = m->base_virtual_addr; - u64 rel_virtual_addr = m->base_virtual_addr + rel->rel_offset; - bool rel_isResolved = false; - u08 rel_sym_type = 0; - std::string rel_name; - u08 rel_bind_type = -1;//-1 means it didn't resolve + u64 rel_value = 0; + u64 rel_base_virtual_addr = m->base_virtual_addr; + u64 rel_virtual_addr = m->base_virtual_addr + rel->rel_offset; + bool rel_isResolved = false; + u08 rel_sym_type = 0; + std::string rel_name; + u08 rel_bind_type = -1; //-1 means it didn't resolve - switch (type) - { - case R_X86_64_RELATIVE: - if (symbol != 0)//should be always zero - { - LOG_INFO_IF(debug_loader, "R_X86_64_RELATIVE symbol not zero = {:#010x}\n", type, symbol); - } - rel_value = rel_base_virtual_addr + addend; - rel_isResolved = true; - break; - case R_X86_64_64: - case R_X86_64_JUMP_SLOT://similar but addend is not take into account - { - auto sym = symbolsTlb[symbol]; - auto sym_bind = sym.GetBind(); - auto sym_type = sym.GetType(); - auto sym_visibility = sym.GetVisibility(); - u64 symbol_vitrual_addr = 0; - switch (sym_type) - { - case STT_FUN: rel_sym_type = 2; break; - case STT_OBJECT: rel_sym_type = 1; break; - default: - LOG_INFO_IF(debug_loader, "unknown symbol type {}\n",sym_type); - } - if (sym_visibility != 0)//should be zero log if else - { - LOG_INFO_IF(debug_loader, "symbol visilibity !=0"); - } - switch (sym_bind) - { - case STB_GLOBAL: + switch (type) { + case R_X86_64_RELATIVE: + if (symbol != 0) // should be always zero + { + LOG_INFO_IF(debug_loader, "R_X86_64_RELATIVE symbol not zero = {:#010x}\n", type, symbol); + } + rel_value = rel_base_virtual_addr + addend; + rel_isResolved = true; + break; + case R_X86_64_64: + case R_X86_64_JUMP_SLOT: // similar but addend is not take into account + { + auto sym = symbolsTlb[symbol]; + auto sym_bind = sym.GetBind(); + auto sym_type = sym.GetType(); + auto sym_visibility = sym.GetVisibility(); + u64 symbol_vitrual_addr = 0; + SymbolRecord symrec{}; + switch (sym_type) { + case STT_FUN: rel_sym_type = 2; break; + case STT_OBJECT: rel_sym_type = 1; break; + default: LOG_INFO_IF(debug_loader, "unknown symbol type {}\n", sym_type); + } + if (sym_visibility != 0) // should be zero log if else + { + LOG_INFO_IF(debug_loader, "symbol visilibity !=0\n"); + } + switch (sym_bind) { + case STB_GLOBAL: rel_bind_type = STB_GLOBAL; rel_name = namesTlb + sym.st_name; + m->linker->Resolve(rel_name, rel_sym_type, m, &symrec); + symbol_vitrual_addr = symrec.virtual_address; + rel_isResolved = (symbol_vitrual_addr != 0); + + rel_name = symrec.name; if (type == R_X86_64_JUMP_SLOT) { - addend = 0; + addend = 0; } - LOG_INFO_IF(debug_loader, "R_X86_64_64-R_X86_64_JUMP_SLOT sym_type {} bind STB_GLOBAL symbol : {:#010x}\n", sym_type, symbol); - break; - default: - LOG_INFO_IF(debug_loader, "UNK bind {}\n", sym_bind); - } - } - break; - default: - LOG_INFO_IF(debug_loader, "UNK type {:#010x} rel symbol : {:#010x}\n", type, symbol); + rel_value = (rel_isResolved ? symbol_vitrual_addr + addend : 0); + if (!rel_isResolved) { + LOG_INFO_IF(debug_loader, "R_X86_64_64-R_X86_64_JUMP_SLOT sym_type {} bind STB_GLOBAL symbol : {:#010x}\n", sym_type, symbol); + } + break; + default: LOG_INFO_IF(debug_loader, "UNK bind {}\n", sym_bind); + } + + } break; + default: LOG_INFO_IF(debug_loader, "UNK type {:#010x} rel symbol : {:#010x}\n", type, symbol); + } + + if (rel_isResolved) { + Memory::VirtualMemory::memory_patch(rel_virtual_addr, rel_value); + } + else + { + LOG_INFO_IF(debug_loader, "function not patched!\n"); } } @@ -574,4 +585,47 @@ void Linker::Relocate(Module* m) { relocate(idx, rel, m, true); } +} + + +void Linker::Resolve(const std::string& name, int Symtype, Module* m, SymbolRecord* return_info) { + auto ids = StringUtil::split(name, '#'); + + if (ids.size() == 3) // symbols are 3 parts name , library , module + { + const auto* library = FindLibrary(*m, ids.at(1)); + const auto* module = FindModule(*m, ids.at(2)); + + if (library != nullptr && module != nullptr) { + SymbolRes sr{}; + sr.name = ids.at(0); + sr.library = library->name; + sr.library_version = library->version; + sr.module = module->name; + sr.module_version_major = module->version_major; + sr.module_version_minor = module->version_minor; + sr.type = Symtype; + + const SymbolRecord* rec = nullptr; + + if (m_HLEsymbols != nullptr) { + rec = m_HLEsymbols->FindSymbol(sr); + } + if (rec != nullptr) { + *return_info = *rec; + } else { + return_info->virtual_address = 0; + return_info->name = "Unresolved!!!"; + } + } + else + { + __debugbreak();//den tha prepei na ftasoume edo + } + } + else + { + __debugbreak();//oute edo mallon + } + } \ No newline at end of file diff --git a/src/Core/PS4/Linker.h b/src/Core/PS4/Linker.h index 4763bdf6..e2e33019 100644 --- a/src/Core/PS4/Linker.h +++ b/src/Core/PS4/Linker.h @@ -5,6 +5,7 @@ #include "Loader/SymbolsResolver.h" struct DynamicModuleInfo; +class Linker; /*this struct keeps neccesary info about loaded modules.Main executeable is included too as well*/ struct Module @@ -13,6 +14,8 @@ struct Module u64 aligned_base_size = 0; u64 base_virtual_addr = 0; //base virtual address + Linker* linker = nullptr; + void* m_dynamic = nullptr; void* m_dynamic_data = nullptr; DynamicModuleInfo* dynamic_info = nullptr; @@ -111,6 +114,7 @@ public: void LoadSymbols(Module* m); SymbolsResolver* getHLESymbols() { return m_HLEsymbols; } void Relocate(Module* m); + void Resolve(const std::string& name, int Symtype, Module* m, SymbolRecord* return_info); private: const ModuleInfo* FindModule(const Module& m, const std::string& id); diff --git a/src/Core/PS4/Loader/SymbolsResolver.cpp b/src/Core/PS4/Loader/SymbolsResolver.cpp index 3dc4e1c3..de28a99a 100644 --- a/src/Core/PS4/Loader/SymbolsResolver.cpp +++ b/src/Core/PS4/Loader/SymbolsResolver.cpp @@ -5,9 +5,26 @@ void SymbolsResolver::AddSymbol(const SymbolRes& s, u64 virtual_addr) { SymbolRecord r{}; - char str[256]; - sprintf(str, "%s (%s)[%s_v%d][%s_v%d.%d]", s.name.c_str(),s.nidName.c_str(), s.library.c_str(), s.library_version, s.module.c_str(),s.module_version_major, s.module_version_minor); - r.name = std::string(str); + r.name = GenerateName(s); r.virtual_address = virtual_addr; m_symbols.push_back(r); +} + +std::string SymbolsResolver::GenerateName(const SymbolRes& s) { + char str[256]; + sprintf(str, "%s lib[%s_v%d]mod[%s_v%d.%d]", s.name.c_str(),s.library.c_str(), s.library_version, s.module.c_str(), + s.module_version_major, s.module_version_minor); + return std::string(str); +} + +const SymbolRecord* SymbolsResolver::FindSymbol(const SymbolRes& s) const { + std::string name = GenerateName(s); + int index = 0; + for (auto symbol : m_symbols) { + if (symbol.name.compare(name) == 0) { + return &m_symbols.at(index); + } + index++; + } + return nullptr; } \ No newline at end of file diff --git a/src/Core/PS4/Loader/SymbolsResolver.h b/src/Core/PS4/Loader/SymbolsResolver.h index 4abdd5b5..9932e050 100644 --- a/src/Core/PS4/Loader/SymbolsResolver.h +++ b/src/Core/PS4/Loader/SymbolsResolver.h @@ -31,6 +31,9 @@ public: virtual ~SymbolsResolver() = default; void AddSymbol(const SymbolRes& s, u64 virtual_addr); + const SymbolRecord* FindSymbol(const SymbolRes& s) const; + + static std::string GenerateName(const SymbolRes& s); private: std::vector m_symbols;