resolving relocate function and patching them (successfully done one :D)

This commit is contained in:
georgemoralis 2023-07-11 18:50:29 +03:00
parent 42dc535638
commit 81906c271a
4 changed files with 137 additions and 59 deletions

View File

@ -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");
}
}
@ -575,3 +586,46 @@ 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
}
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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<SymbolRecord> m_symbols;