1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-23 03:02:53 +01:00

Initial sys_overlay

This commit is contained in:
Inviuz 2017-12-31 15:38:02 +01:00 committed by Nekotekina
parent 1d947daa81
commit 52a12185a0
10 changed files with 339 additions and 6 deletions

View File

@ -931,6 +931,44 @@ void ppu_module::analyse(u32 lib_toc, u32 entry)
}
}
if (ptr + 0x7 <= fend &&
ptr[0] == STD(r2, r1, 0x28) &&
(ptr[1] & 0xffff0000) == ADDIS(r12, r2, {}) &&
(ptr[2] & 0xffff0000) == LWZ(r11, r12, {}) &&
(ptr[3] & 0xffff0000) == ADDIS(r2, r2, {}) &&
(ptr[4] & 0xffff0000) == ADDI(r2, r2, {}) &&
ptr[5] == MTCTR(r11) &&
ptr[6] == BCTR())
{
func.toc = -1;
func.size = 0x1C;
func.blocks.emplace(func.addr, func.size);
func.attr += ppu_attr::known_addr;
func.attr += ppu_attr::known_size;
// Look for another imports to fill gaps (hack)
auto p2 = ptr + 7;
while (p2 + 0x7 <= fend &&
p2[0] == STD(r2, r1, 0x28) &&
(p2[1] & 0xffff0000) == ADDIS(r12, r2, {}) &&
(p2[2] & 0xffff0000) == LWZ(r11, r12, {}) &&
(p2[3] & 0xffff0000) == ADDIS(r2, r2, {}) &&
(p2[4] & 0xffff0000) == ADDI(r2, r2, {}) &&
p2[5] == MTCTR(r11) &&
p2[6] == BCTR())
{
auto& next = add_func(p2.addr(), -1, func.addr);
next.size = 0x1C;
next.blocks.emplace(next.addr, next.size);
next.attr += ppu_attr::known_addr;
next.attr += ppu_attr::known_size;
p2 += 7;
}
continue;
}
if (ptr + 4 <= fend &&
ptr[0] == STD(r2, r1, 0x28) &&
(ptr[1] & 0xffff0000) == ADDIS(r2, r2, {}) &&

View File

@ -13,6 +13,7 @@
#include "Emu/Cell/lv2/sys_prx.h"
#include "Emu/Cell/lv2/sys_memory.h"
#include "Emu/Cell/lv2/sys_overlay.h"
#include "Emu/Cell/Modules/StaticHLE.h"
@ -1529,7 +1530,7 @@ void ppu_load_exec(const ppu_exec_object& elf)
u32 mem_size;
if (sdk_version > 0x0021FFFF)
{
mem_size = 0xD500000;
mem_size = 0xD500000;
}
else if (sdk_version > 0x00192FFF)
{
@ -1620,3 +1621,193 @@ void ppu_load_exec(const ppu_exec_object& elf)
}
}
}
std::shared_ptr<lv2_overlay> ppu_load_overlay(const ppu_exec_object& elf, const std::string& path)
{
const auto ovlm = idm::make_ptr<lv2_obj, lv2_overlay>();
// Access linkage information object
const auto link = fxm::get_always<ppu_linkage_info>();
// Executable hash
sha1_context sha;
sha1_starts(&sha);
// Allocate memory at fixed positions
for (const auto& prog : elf.progs)
{
LOG_NOTICE(LOADER, "** Segment: p_type=0x%x, p_vaddr=0x%llx, p_filesz=0x%llx, p_memsz=0x%llx, flags=0x%x", prog.p_type, prog.p_vaddr, prog.p_filesz, prog.p_memsz, prog.p_flags);
ppu_segment _seg;
const u32 addr = _seg.addr = vm::cast(prog.p_vaddr, HERE);
const u32 size = _seg.size = ::narrow<u32>(prog.p_memsz, "p_memsz" HERE);
const u32 type = _seg.type = prog.p_type;
const u32 flag = _seg.flags = prog.p_flags;
_seg.filesz = ::narrow<u32>(prog.p_filesz, "p_filesz" HERE);
// Hash big-endian values
sha1_update(&sha, (uchar*)&prog.p_type, sizeof(prog.p_type));
sha1_update(&sha, (uchar*)&prog.p_flags, sizeof(prog.p_flags));
if (type == 0x1 /* LOAD */ && prog.p_memsz)
{
if (prog.bin.size() > size || prog.bin.size() != prog.p_filesz)
fmt::throw_exception("Invalid binary size (0x%llx, memsz=0x%x)", prog.bin.size(), size);
if (!vm::falloc(addr, size))
fmt::throw_exception("vm::falloc() failed (addr=0x%x, memsz=0x%x)", addr, size);
// Copy segment data, hash it
std::memcpy(vm::base(addr), prog.bin.data(), prog.bin.size());
sha1_update(&sha, (uchar*)&prog.p_vaddr, sizeof(prog.p_vaddr));
sha1_update(&sha, (uchar*)&prog.p_memsz, sizeof(prog.p_memsz));
sha1_update(&sha, prog.bin.data(), prog.bin.size());
// Initialize executable code if necessary
if (prog.p_flags & 0x1)
{
ppu_register_range(addr, size);
}
// Store only LOAD segments (TODO)
ovlm->segs.emplace_back(_seg);
}
}
// Load section list, used by the analyser
for (const auto& s : elf.shdrs)
{
LOG_NOTICE(LOADER, "** Section: sh_type=0x%x, addr=0x%llx, size=0x%llx, flags=0x%x", s.sh_type, s.sh_addr, s.sh_size, s.sh_flags);
ppu_segment _sec;
const u32 addr = _sec.addr = vm::cast(s.sh_addr);
const u32 size = _sec.size = vm::cast(s.sh_size);
const u32 type = _sec.type = s.sh_type;
const u32 flag = _sec.flags = s.sh_flags & 7;
_sec.filesz = 0;
if (s.sh_type == 1 && addr && size)
{
ovlm->secs.emplace_back(_sec);
}
}
sha1_finish(&sha, ovlm->sha1);
// Format patch name
std::string hash("OVL-0000000000000000000000000000000000000000");
for (u32 i = 0; i < 20; i++)
{
constexpr auto pal = "0123456789abcdef";
hash[4 + i * 2] = pal[ovlm->sha1[i] >> 4];
hash[5 + i * 2] = pal[ovlm->sha1[i] & 15];
}
// Apply the patch
auto applied = fxm::check_unlocked<patch_engine>()->apply(hash, vm::g_base_addr);
if (!Emu.GetTitleID().empty())
{
// Alternative patch
applied += fxm::check_unlocked<patch_engine>()->apply(Emu.GetTitleID() + '-' + hash, vm::g_base_addr);
}
LOG_NOTICE(LOADER, "OVL executable hash: %s (<- %u)", hash, applied);
// Load other programs
for (auto& prog : elf.progs)
{
switch (const u32 p_type = prog.p_type)
{
case 0x00000001: break; // LOAD (already loaded)
case 0x60000001: // LOOS+1
{
if (prog.p_filesz)
{
struct process_param_t
{
be_t<u32> size; //0x60
be_t<u32> magic; //string OVLM
be_t<u32> version; //0x17000
be_t<u32> sdk_version; //seems to be correct
//string "stage_ovlm"
//and a lot of zeros.
};
const auto& info = vm::_ref<process_param_t>(vm::cast(prog.p_vaddr, HERE));
if (info.size < sizeof(process_param_t))
{
LOG_WARNING(LOADER, "Bad process_param size! [0x%x : 0x%x]", info.size, u32{sizeof(process_param_t)});
}
if (info.magic != 0x4f564c4d) //string "OVLM"
{
LOG_ERROR(LOADER, "Bad process_param magic! [0x%x]", info.magic);
}
else
{
LOG_NOTICE(LOADER, "*** sdk version: 0x%x", info.sdk_version);
}
}
break;
}
case 0x60000002: // LOOS+2 seems to be 0x0 in size for overlay elfs, at least in known cases
{
if (prog.p_filesz)
{
struct ppu_proc_prx_param_t
{
be_t<u32> size;
be_t<u32> magic;
be_t<u32> version;
be_t<u32> unk0;
be_t<u32> libent_start;
be_t<u32> libent_end;
be_t<u32> libstub_start;
be_t<u32> libstub_end;
be_t<u16> ver;
be_t<u16> unk1;
be_t<u32> unk2;
};
const auto& proc_prx_param = vm::_ref<const ppu_proc_prx_param_t>(vm::cast(prog.p_vaddr, HERE));
LOG_NOTICE(LOADER, "* libent_start = *0x%x", proc_prx_param.libent_start);
LOG_NOTICE(LOADER, "* libstub_start = *0x%x", proc_prx_param.libstub_start);
LOG_NOTICE(LOADER, "* unk0 = 0x%x", proc_prx_param.unk0);
LOG_NOTICE(LOADER, "* unk2 = 0x%x", proc_prx_param.unk2);
if (proc_prx_param.magic != 0x1b434cec)
{
fmt::throw_exception("Bad magic! (0x%x)", proc_prx_param.magic);
}
ppu_load_exports(link, proc_prx_param.libent_start, proc_prx_param.libent_end);
ppu_load_imports(ovlm->relocs, link, proc_prx_param.libstub_start, proc_prx_param.libstub_end);
}
break;
}
default:
{
LOG_ERROR(LOADER, "Unknown phdr type (0x%08x)", p_type);
}
}
}
ovlm->entry = static_cast<u32>(elf.header.e_entry);
// Analyse executable (TODO)
ovlm->analyse(0, ovlm->entry);
// Validate analyser results (not required)
ovlm->validate(0);
// Set path (TODO)
ovlm->name = path.substr(path.find_last_of('/') + 1);
ovlm->path = path;
return ovlm;
}

View File

@ -15,6 +15,7 @@
#include "sys_memory.h"
#include "sys_mmapper.h"
#include "sys_net.h"
#include "sys_overlay.h"
#include "sys_ppu_thread.h"
#include "sys_process.h"
#include "sys_prx.h"
@ -422,8 +423,8 @@ const std::array<ppu_function_t, 1024> s_ppu_syscall_table
uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, //430-439 UNS
uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, uns_func, //440-449 UNS
null_func,//BIND_FUNC(sys_overlay_load_module) //450 (0x1C2)
null_func,//BIND_FUNC(sys_overlay_unload_module) //451 (0x1C3)
BIND_FUNC(sys_overlay_load_module), //450 (0x1C2)
BIND_FUNC(sys_overlay_unload_module), //451 (0x1C3)
null_func,//BIND_FUNC(sys_overlay_get_module_list) //452 (0x1C4)
null_func,//BIND_FUNC(sys_overlay_get_module_info) //453 (0x1C5)
null_func,//BIND_FUNC(sys_overlay_load_module_by_fd) //454 (0x1C6)

View File

@ -0,0 +1,60 @@
#include "stdafx.h"
#include "Emu/Memory/vm.h"
#include "Emu/System.h"
#include "Emu/IdManager.h"
#include "Crypto/unself.h"
#include "Crypto/unedat.h"
#include "Loader/ELF.h"
#include "sys_overlay.h"
extern std::shared_ptr<lv2_overlay> ppu_load_overlay(const ppu_exec_object&, const std::string& path);
extern void ppu_initialize(const ppu_module&);
LOG_CHANNEL(sys_overlay);
error_code sys_overlay_load_module(vm::ptr<u32> ovlmid, vm::cptr<char> path2, u64 flags, vm::ptr<u32> entry)
{
sys_overlay.warning("sys_overlay_load_module(ovlmid=*0x%x, path=%s, flags=0x%x, entry=*0x%x)", ovlmid, path2, flags, entry);
const std::string path = path2.get_ptr();
const auto name = path.substr(path.find_last_of('/') + 1);
const ppu_exec_object obj = decrypt_self(fs::file(vfs::get(path)), fxm::get_always<LoadedNpdrmKeys_t>()->devKlic.data());
if (obj != elf_error::ok)
{
return {CELL_ENOEXEC, obj.operator elf_error()};
}
const auto ovlm = ppu_load_overlay(obj, path);
ppu_initialize(*ovlm);
sys_overlay.success("Loaded overlay: %s", path);
*ovlmid = idm::last_id();
*entry = ovlm->entry;
return CELL_OK;
}
error_code sys_overlay_unload_module(u32 ovlmid)
{
sys_overlay.warning("sys_overlay_unload_module(ovlmid=0x%x)", ovlmid);
const auto _main = idm::withdraw<lv2_obj, lv2_overlay>(ovlmid);
if (!_main)
{
return CELL_ESRCH;
}
for (auto& seg : _main->segs)
{
vm::dealloc(seg.addr);
}
return CELL_OK;
}

View File

@ -0,0 +1,23 @@
#pragma once
#include "Emu/Cell/PPUAnalyser.h"
#include "sys_sync.h"
#include "Emu/Cell/ErrorCodes.h"
struct lv2_overlay final : lv2_obj, ppu_module
{
static const u32 id_base = 0x25000000;
u32 entry;
};
error_code sys_overlay_load_module(vm::ptr<u32> ovlmid, vm::cptr<char> path, u64 flags, vm::ptr<u32> entry);
error_code sys_overlay_unload_module(u32 ovlmid);
//error_code sys_overlay_get_module_list(sys_pid_t pid, size_t ovlmids_num, sys_overlay_t * ovlmids, size_t * num_of_modules);
//error_code sys_overlay_get_module_info(sys_pid_t pid, sys_overlay_t ovlmid, sys_overlay_module_info_t * info);
//error_code sys_overlay_load_module_by_fd(sys_overlay_t * ovlmid, int fd, u64 offset, uint64_t flags, sys_addr_t * entry);
//error_code sys_overlay_get_module_info2(sys_pid_t pid, sys_overlay_t ovlmid, sys_overlay_module_info2_t * info);//
//error_code sys_overlay_get_sdk_version(); //2 params
//error_code sys_overlay_get_module_dbg_info(); //3 params?
//error_code _sys_prx_load_module(vm::ps3::cptr<char> path, u64 flags, vm::ps3::ptr<sys_prx_load_module_option_t> pOpt);

View File

@ -16,6 +16,7 @@
#include "sys_memory.h"
#include "sys_mmapper.h"
#include "sys_prx.h"
#include "sys_overlay.h"
#include "sys_rwlock.h"
#include "sys_semaphore.h"
#include "sys_timer.h"
@ -71,6 +72,7 @@ s32 sys_process_get_number_of_object(u32 object, vm::ptr<u32> nump)
case SYS_SPUIMAGE_OBJECT: fmt::throw_exception("SYS_SPUIMAGE_OBJECT" HERE);
case SYS_PRX_OBJECT: *nump = idm_get_count<lv2_obj, lv2_prx>(); break;
case SYS_SPUPORT_OBJECT: fmt::throw_exception("SYS_SPUPORT_OBJECT" HERE);
case SYS_OVERLAY_OBJECT: *nump = idm_get_count<lv2_obj, lv2_overlay>(); break;
case SYS_LWMUTEX_OBJECT: *nump = idm_get_count<lv2_obj, lv2_lwmutex>(); break;
case SYS_TIMER_OBJECT: *nump = idm_get_count<lv2_obj, lv2_timer>(); break;
case SYS_SEMAPHORE_OBJECT: *nump = idm_get_count<lv2_obj, lv2_sema>(); break;
@ -118,6 +120,7 @@ s32 sys_process_get_id(u32 object, vm::ptr<u32> buffer, u32 size, vm::ptr<u32> s
case SYS_SPUIMAGE_OBJECT: fmt::throw_exception("SYS_SPUIMAGE_OBJECT" HERE);
case SYS_PRX_OBJECT: idm_get_set<lv2_obj, lv2_prx>(objects); break;
case SYS_SPUPORT_OBJECT: fmt::throw_exception("SYS_SPUPORT_OBJECT" HERE);
case SYS_OVERLAY_OBJECT: idm_get_set<lv2_obj, lv2_overlay>(objects); break;
case SYS_LWMUTEX_OBJECT: idm_get_set<lv2_obj, lv2_lwmutex>(objects); break;
case SYS_TIMER_OBJECT: idm_get_set<lv2_obj, lv2_timer>(objects); break;
case SYS_SEMAPHORE_OBJECT: idm_get_set<lv2_obj, lv2_sema>(objects); break;

View File

@ -15,6 +15,7 @@ enum : u32
SYS_SPUIMAGE_OBJECT = 0x22,
SYS_PRX_OBJECT = 0x23,
SYS_SPUPORT_OBJECT = 0x24,
SYS_OVERLAY_OBJECT = 0x25,
SYS_LWMUTEX_OBJECT = 0x95,
SYS_TIMER_OBJECT = 0x11,
SYS_SEMAPHORE_OBJECT = 0x96,

View File

@ -115,6 +115,7 @@
<ClCompile Include="Emu\Cell\lv2\sys_gpio.cpp" />
<ClCompile Include="Emu\Cell\lv2\sys_net.cpp" />
<ClCompile Include="Emu\Cell\Modules\StaticHLE.cpp" />
<ClCompile Include="Emu\Cell\lv2\sys_overlay.cpp" />
<ClCompile Include="Emu\Cell\PPUAnalyser.cpp" />
<ClCompile Include="Emu\Cell\PPUTranslator.cpp">
<PrecompiledHeader>NotUsing</PrecompiledHeader>
@ -408,6 +409,7 @@
<ClInclude Include="Emu\Cell\Modules\cellHttp.h" />
<ClInclude Include="Emu\Cell\Modules\cellHttpUtil.h" />
<ClInclude Include="Emu\Cell\Modules\cellJpgEnc.h" />
<ClInclude Include="Emu\Cell\lv2\sys_overlay.h" />
<ClInclude Include="Emu\Cell\Modules\cellOskDialog.h" />
<ClInclude Include="Emu\Cell\Modules\cellVoice.h" />
<ClInclude Include="Emu\Cell\Modules\StaticHLE.h" />
@ -607,4 +609,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View File

@ -779,6 +779,9 @@
<ClCompile Include="Emu\RSX\Overlays\overlay_osk.cpp">
<Filter>Emu\GPU\RSX\Overlays</Filter>
</ClCompile>
<ClCompile Include="Emu\Cell\lv2\sys_overlay.cpp">
<Filter>Emu\Cell\lv2</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="Crypto\aes.h">
@ -1423,6 +1426,9 @@
<ClInclude Include="Emu\Cell\lv2\sys_net.h">
<Filter>Emu\Cell\lv2</Filter>
</ClInclude>
<ClInclude Include="Emu\Cell\lv2\sys_overlay.h">
<Filter>Emu\Cell\lv2</Filter>
</ClInclude>
<ClInclude Include="Emu\Cell\lv2\sys_gpio.h">
<Filter>Emu\Cell\lv2</Filter>
</ClInclude>
@ -1490,4 +1496,4 @@
<Filter>Emu\Audio\Null</Filter>
</ClInclude>
</ItemGroup>
</Project>
</Project>

View File

@ -15,6 +15,7 @@
#include "Emu/Cell/lv2/sys_event_flag.h"
#include "Emu/Cell/lv2/sys_rwlock.h"
#include "Emu/Cell/lv2/sys_prx.h"
#include "Emu/Cell/lv2/sys_overlay.h"
#include "Emu/Cell/lv2/sys_memory.h"
#include "Emu/Cell/lv2/sys_mmapper.h"
#include "Emu/Cell/lv2/sys_spu.h"
@ -125,8 +126,9 @@ void kernel_explorer::Update()
lv2_types[SYS_EVENT_PORT_OBJECT] = l_addTreeChild(root, "Event Ports");
lv2_types[SYS_TRACE_OBJECT] = l_addTreeChild(root, "Traces");
lv2_types[SYS_SPUIMAGE_OBJECT] = l_addTreeChild(root, "SPU Images");
lv2_types[SYS_PRX_OBJECT] = l_addTreeChild(root, "Modules");
lv2_types[SYS_PRX_OBJECT] = l_addTreeChild(root, "PRX Modules");
lv2_types[SYS_SPUPORT_OBJECT] = l_addTreeChild(root, "SPU Ports");
lv2_types[SYS_OVERLAY_OBJECT] = l_addTreeChild(root, "Overlay Modules");
lv2_types[SYS_LWMUTEX_OBJECT] = l_addTreeChild(root, "Light Weight Mutexes");
lv2_types[SYS_TIMER_OBJECT] = l_addTreeChild(root, "Timers");
lv2_types[SYS_SEMAPHORE_OBJECT] = l_addTreeChild(root, "Semaphores");
@ -212,6 +214,12 @@ void kernel_explorer::Update()
l_addTreeChild(node, qstr(fmt::format("SPU Port: ID = 0x%08x", id)));
break;
}
case SYS_OVERLAY_OBJECT:
{
auto& ovl = static_cast<lv2_overlay&>(obj);
l_addTreeChild(node, qstr(fmt::format("OVL: ID = 0x%08x '%s'", id, ovl.name)));
break;
}
case SYS_LWMUTEX_OBJECT:
{
auto& lwm = static_cast<lv2_lwmutex&>(obj);