Implement _sys_prx_register_module loading imports/exports functionality

This commit is contained in:
Eladash 2021-04-02 18:33:22 +03:00 committed by Ivan
parent 878da3b474
commit 32116086b3
3 changed files with 91 additions and 3 deletions

View file

@ -699,6 +699,16 @@ static auto ppu_load_imports(std::vector<ppu_reloc>& relocs, ppu_linkage_info* l
return result;
}
// For _sys_prx_register_module
void ppu_manual_load_imports_exports(u32 imports_start, u32 imports_size, u32 exports_start, u32 exports_size)
{
auto& _main = g_fxo->get<ppu_module>();
auto& link = g_fxo->get<ppu_linkage_info>();
ppu_load_exports(&link, exports_start, exports_start + exports_size);
ppu_load_imports(_main.relocs, &link, imports_start, imports_start + imports_size);
}
static void ppu_check_patch_spu_images(const ppu_segment& seg)
{
const std::string_view seg_view{vm::get_super_ptr<char>(seg.addr), seg.size};

View file

@ -608,11 +608,64 @@ error_code _sys_prx_unload_module(ppu_thread& ppu, u32 id, u64 flags, vm::ptr<sy
return CELL_OK;
}
error_code _sys_prx_register_module(ppu_thread& ppu)
void ppu_manual_load_imports_exports(u32 imports_start, u32 imports_size, u32 exports_start, u32 exports_size);
error_code _sys_prx_register_module(ppu_thread& ppu, vm::cptr<char> name, vm::ptr<void> opt)
{
ppu.state += cpu_flag::wait;
sys_prx.todo("_sys_prx_register_module()");
sys_prx.todo("_sys_prx_register_module(name=%s, opt=*0x%x)", name, opt);
if (!opt)
{
return CELL_EINVAL;
}
sys_prx_register_module_0x30_type_1_t info{};
switch (const u64 size_struct = vm::read64(opt.addr()))
{
case 0x1c:
case 0x20:
{
const auto _info = vm::static_ptr_cast<sys_prx_register_module_0x20_t>(opt);
sys_prx.todo("_sys_prx_register_module(): opt size is 0x%x", size_struct);
// Rebuild info with corresponding members of old structures
// Weird that type is set to 0 because 0 means NO-OP in this syscall
info.size = 0x30;
info.lib_stub_size = _info->stubs_size;
info.lib_stub_ea = _info->stubs_ea;
info.error_handler = _info->error_handler;
info.type = 0;
break;
}
case 0x30:
{
std::memcpy(&info, opt.get_ptr(), sizeof(info));
break;
}
default: return CELL_EINVAL;
}
sys_prx.warning("opt: size=0x%x, type=0x%x, unk3=0x%x, unk4=0x%x, lib_entries_ea=%s, lib_entries_size=0x%x"
", lib_stub_ea=%s, lib_stub_size=0x%x, error_handler=%s", info.size, info.type, info.unk3, info.unk4
, info.lib_entries_ea, info.lib_entries_size, info.lib_stub_ea, info.lib_stub_size, info.error_handler);
if (info.type & 0x1)
{
if (g_ps3_process_info.get_cellos_appname() == "vsh.self"sv)
{
ppu_manual_load_imports_exports(info.lib_stub_ea.addr(), info.lib_stub_size, info.lib_entries_ea.addr(), info.lib_entries_size);
}
else
{
// Only VSH is allowed to load it manually
return not_an_error(CELL_PRX_ERROR_ELF_IS_REGISTERED);
}
}
return CELL_OK;
}

View file

@ -118,6 +118,31 @@ struct sys_prx_get_module_list_option_t
be_t<u32> unk; // 0
};
struct sys_prx_register_module_0x20_t
{
be_t<u64> size; // 0x0
be_t<u32> toc; // 0x8
be_t<u32> toc_size; // 0xC
vm::bptr<void> stubs_ea; // 0x10
be_t<u32> stubs_size; // 0x14
vm::bptr<void> error_handler; // 0x18
char pad[4]; // 0x1C
};
struct sys_prx_register_module_0x30_type_1_t
{
be_t<u64> size; // 0x0
be_t<u64> type; // 0x8
be_t<u32> unk3; // 0x10
be_t<u32> unk4; // 0x14
vm::bptr<void> lib_entries_ea; // 0x18
be_t<u32> lib_entries_size; // 0x1C
vm::bptr<void> lib_stub_ea; // 0x20
be_t<u32> lib_stub_size; // 0x24
vm::bptr<void> error_handler; // 0x28
char pad[4]; // 0x2C
};
enum : u32
{
SYS_PRX_RESIDENT = 0,
@ -172,7 +197,7 @@ error_code _sys_prx_load_module(ppu_thread& ppu, vm::cptr<char> path, u64 flags,
error_code _sys_prx_start_module(ppu_thread& ppu, u32 id, u64 flags, vm::ptr<sys_prx_start_stop_module_option_t> pOpt);
error_code _sys_prx_stop_module(ppu_thread& ppu, u32 id, u64 flags, vm::ptr<sys_prx_start_stop_module_option_t> pOpt);
error_code _sys_prx_unload_module(ppu_thread& ppu, u32 id, u64 flags, vm::ptr<sys_prx_unload_module_option_t> pOpt);
error_code _sys_prx_register_module(ppu_thread& ppu);
error_code _sys_prx_register_module(ppu_thread& ppu, vm::cptr<char> name, vm::ptr<void> opt);
error_code _sys_prx_query_module(ppu_thread& ppu);
error_code _sys_prx_register_library(ppu_thread& ppu, vm::ptr<void> library);
error_code _sys_prx_unregister_library(ppu_thread& ppu, vm::ptr<void> library);