rpcsx/rpcs3/Emu/SysCalls/Modules.cpp
Arkaran99 3caff5a107 Change ModuleManager::init function.
First step to help refactor Module management.
Add every module in the static ModuleInfo list. Module without id are assigned
to 0xffff.
The init function is called after constructor and take a pointer to Module
as an input.
This pointer is used to set the Module's global pointer in its file.
2014-09-13 22:00:17 +02:00

234 lines
5 KiB
C++

#include "stdafx.h"
#include "Emu/Memory/Memory.h"
#include "Emu/System.h"
#include "Emu/SysCalls/Modules.h"
#include "Emu/SysCalls/Static.h"
#include "Crypto/sha1.h"
#include "ModuleManager.h"
u32 getFunctionId(const char* name)
{
const char* suffix = "\x67\x59\x65\x99\x04\x25\x04\x90\x56\x64\x27\x49\x94\x89\x74\x1A"; // Symbol name suffix
u8 output[20];
// Compute SHA-1 hash
sha1_context ctx;
sha1_starts(&ctx);
sha1_update(&ctx, (const u8*)name, strlen(name));
sha1_update(&ctx, (const u8*)suffix, strlen(suffix));
sha1_finish(&ctx, output);
return (u32&)output[0];
}
Module::Module(u16 id, const char* name, void(*load)(), void(*unload)())
: m_is_loaded(false)
, m_name(name)
, m_id(id)
, m_load_func(load)
, m_unload_func(unload)
{
Emu.GetModuleManager().SetModule(m_id, this);
}
Module::Module(Module &&other)
: m_is_loaded(false)
, m_id(0)
, m_load_func(nullptr)
, m_unload_func(nullptr)
{
std::swap(this->m_name,other.m_name);
std::swap(this->m_id, other.m_id);
std::swap(this->m_is_loaded, other.m_is_loaded);
std::swap(this->m_load_func, other.m_load_func);
std::swap(this->m_unload_func, other.m_unload_func);
std::swap(this->m_funcs_list, other.m_funcs_list);
}
Module &Module::operator =(Module &&other)
{
std::swap(this->m_name, other.m_name);
std::swap(this->m_id, other.m_id);
std::swap(this->m_is_loaded, other.m_is_loaded);
std::swap(this->m_load_func, other.m_load_func);
std::swap(this->m_unload_func, other.m_unload_func);
std::swap(this->m_funcs_list, other.m_funcs_list);
return *this;
}
Module::~Module()
{
UnLoad();
for (int i = 0; i < m_funcs_list.size(); i++)
{
delete m_funcs_list[i];
}
}
void Module::Load()
{
if(IsLoaded())
return;
if(m_load_func) m_load_func();
for(u32 i=0; i<m_funcs_list.size(); ++i)
{
Emu.GetModuleManager().AddFunc(m_funcs_list[i]);
}
SetLoaded(true);
}
void Module::UnLoad()
{
if(!IsLoaded())
return;
if(m_unload_func) m_unload_func();
for(u32 i=0; i<m_funcs_list.size(); ++i)
{
Emu.GetModuleManager().UnloadFunc(m_funcs_list[i]->id);
}
SetLoaded(false);
}
bool Module::Load(u32 id)
{
if(Emu.GetModuleManager().IsLoadedFunc(id))
return false;
for(u32 i=0; i<m_funcs_list.size(); ++i)
{
if(m_funcs_list[i]->id == id)
{
Emu.GetModuleManager().AddFunc(m_funcs_list[i]);
return true;
}
}
return false;
}
bool Module::UnLoad(u32 id)
{
return Emu.GetModuleManager().UnloadFunc(id);
}
void Module::SetLoaded(bool loaded)
{
m_is_loaded = loaded;
}
bool Module::IsLoaded() const
{
return m_is_loaded;
}
u16 Module::GetID() const
{
return m_id;
}
const std::string& Module::GetName() const
{
return m_name;
}
void Module::SetName(const std::string& name)
{
m_name = name;
}
bool Module::CheckID(u32 id) const
{
return Emu.GetIdManager().CheckID(id) && Emu.GetIdManager().GetID(id).m_name == GetName();
}
bool Module::CheckID(u32 id, ID*& _id) const
{
return Emu.GetIdManager().CheckID(id) && (_id = &Emu.GetIdManager().GetID(id))->m_name == GetName();
}
bool Module::RemoveId(u32 id)
{
return Emu.GetIdManager().RemoveID(id);
}
IdManager& Module::GetIdManager() const
{
return Emu.GetIdManager();
}
void Module::PushNewFuncSub(SFunc* func)
{
Emu.GetSFuncManager().push_back(func);
}
void fix_import(Module* module, u32 func, u32 addr)
{
vm::write32(addr + 0x0, 0x3d600000 | (func >> 16)); /* lis r11, (func_id >> 16) */
vm::write32(addr + 0x4, 0x616b0000 | (func & 0xffff)); /* ori r11, (func_id & 0xffff) */
vm::write32(addr + 0x8, 0x60000000); /* nop */
// leave rtoc saving at 0xC
vm::write64(addr + 0x10, 0x440000024e800020ull); /* sc + blr */
vm::write64(addr + 0x18, 0x6000000060000000ull); /* nop + nop */
module->Load(func);
}
void fix_relocs(Module* module, u32 lib, u32 start, u32 end, u32 seg2)
{
// start of table:
// addr = (u64) addr - seg2, (u32) 1, (u32) 1, (u64) ptr
// addr = (u64) addr - seg2, (u32) 0x101, (u32) 1, (u64) ptr - seg2 (???)
// addr = (u64) addr, (u32) 0x100, (u32) 1, (u64) ptr - seg2 (???)
// addr = (u64) addr, (u32) 0, (u32) 1, (u64) ptr (???)
for (u32 i = lib + start; i < lib + end; i += 24)
{
u64 addr = vm::read64(i);
const u64 flag = vm::read64(i + 8);
if (flag == 0x10100000001ull)
{
addr = addr + seg2 + lib;
u32 value = vm::read32(addr);
assert(value == vm::read64(i + 16) + seg2);
vm::write32(addr, value + lib);
}
else if (flag == 0x100000001ull)
{
addr = addr + seg2 + lib;
u32 value = vm::read32(addr);
assert(value == vm::read64(i + 16));
vm::write32(addr, value + lib);
}
else if (flag == 0x10000000001ull)
{
addr = addr + lib;
u32 value = vm::read32(addr);
assert(value == vm::read64(i + 16) + seg2);
vm::write32(addr, value + lib);
}
else if (flag == 1)
{
addr = addr + lib;
u32 value = vm::read32(addr);
assert(value == vm::read64(i + 16));
vm::write32(addr, value + lib);
}
else if (flag == 0x10000000004ull || flag == 0x10000000006ull)
{
// seems to be instruction modifiers for imports (done in other way in FIX_IMPORT)
}
else
{
module->Notice("fix_relocs(): 0x%x : 0x%llx", i - lib, flag);
}
}
}