PPU Analyzer: Utilize exported functions

This commit is contained in:
Elad Ashkenazi 2024-06-08 12:44:23 +03:00
parent 6d280c5f3c
commit 6fff22391c
5 changed files with 60 additions and 19 deletions

View file

@ -682,7 +682,7 @@ extern bool ppu_register_library_lock(std::string_view libname, bool lock_lib)
}
// Load and register exports; return special exports found (nameless module)
static auto ppu_load_exports(const ppu_module& _module, ppu_linkage_info* link, u32 exports_start, u32 exports_end, bool for_observing_callbacks = false, std::basic_string<bool>* loaded_flags = nullptr)
static auto ppu_load_exports(const ppu_module& _module, ppu_linkage_info* link, u32 exports_start, u32 exports_end, bool for_observing_callbacks = false, std::vector<u32>* funcs = nullptr, std::basic_string<bool>* loaded_flags = nullptr)
{
std::unordered_map<u32, u32> result;
@ -714,6 +714,11 @@ static auto ppu_load_exports(const ppu_module& _module, ppu_linkage_info* link,
const u32 nid = _module.get_ref<u32>(lib.nids, i);
const u32 addr = _module.get_ref<u32>(lib.addrs, i);
if (funcs)
{
funcs->emplace_back(addr);
}
if (i < lib.num_func)
{
ppu_loader.notice("** Special: [%s] at 0x%x [0x%x, 0x%x]", ppu_get_function_name({}, nid), addr, _module.get_ref<u32>(addr), _module.get_ref<u32>(addr + 4));
@ -735,13 +740,6 @@ static auto ppu_load_exports(const ppu_module& _module, ppu_linkage_info* link,
continue;
}
const bool is_dummy_load = Emu.IsReady() && g_fxo->get<main_ppu_module>().segs.empty() && !Emu.DeserialManager();
if (!is_dummy_load && for_observing_callbacks)
{
continue;
}
const std::string module_name(&_module.get_ref<const char>(lib.name));
if (unload_exports)
@ -761,7 +759,7 @@ static auto ppu_load_exports(const ppu_module& _module, ppu_linkage_info* link,
ppu_loader.error("Unexpected num_tlsvar (%u)!", lib.num_tlsvar);
}
const bool should_load = is_dummy_load || ppu_register_library_lock(module_name, true);
const bool should_load = for_observing_callbacks || ppu_register_library_lock(module_name, true);
if (loaded_flags)
{
@ -790,6 +788,16 @@ static auto ppu_load_exports(const ppu_module& _module, ppu_linkage_info* link,
const u32 faddr = _module.get_ref<u32>(faddrs, i);
ppu_loader.notice("**** %s export: [%s] (0x%08x) at 0x%x [at:0x%x]", module_name, ppu_get_function_name(module_name, fnid), fnid, faddr, _module.get_ref<u32>(faddr));
if (funcs)
{
funcs->emplace_back(faddr);
}
if (for_observing_callbacks)
{
continue;
}
// Function linkage info
auto& flink = mlink.functions[fnid];
@ -850,6 +858,11 @@ static auto ppu_load_exports(const ppu_module& _module, ppu_linkage_info* link,
const u32 vaddr = _module.get_ref<u32>(vaddrs, i);
ppu_loader.notice("**** %s export: &[%s] at 0x%x", module_name, ppu_get_variable_name(module_name, vnid), vaddr);
if (for_observing_callbacks)
{
continue;
}
// Variable linkage info
auto& vlink = mlink.variables[vnid];
@ -979,7 +992,7 @@ void ppu_manual_load_imports_exports(u32 imports_start, u32 imports_size, u32 ex
vm_all_fake_module.segs.emplace_back(ppu_segment{0x10000, 0 - 0x10000u, 1 /*LOAD*/, 0, 0 - 0x1000u, vm::base(0x10000)});
vm_all_fake_module.addr_to_seg_index.emplace(0x10000, 0);
ppu_load_exports(vm_all_fake_module, &link, exports_start, exports_start + exports_size, false, &loaded_flags);
ppu_load_exports(vm_all_fake_module, &link, exports_start, exports_start + exports_size, false, nullptr, &loaded_flags);
if (!imports_size)
{
@ -1731,6 +1744,8 @@ std::shared_ptr<lv2_prx> ppu_load_prx(const ppu_prx_object& elf, bool virtual_lo
}
}
std::vector<u32> exported_funcs;
if (!elf.progs.empty() && elf.progs[0].p_paddr)
{
struct ppu_prx_library_info
@ -1774,7 +1789,7 @@ std::shared_ptr<lv2_prx> ppu_load_prx(const ppu_prx_object& elf, bool virtual_lo
ppu_linkage_info dummy{};
prx->specials = ppu_load_exports(*prx, virtual_load ? &dummy : &link, prx->exports_start, prx->exports_end, true);
prx->specials = ppu_load_exports(*prx, virtual_load ? &dummy : &link, prx->exports_start, prx->exports_end, true, &exported_funcs);
prx->imports = ppu_load_imports(*prx, prx->relocs, virtual_load ? &dummy : &link, lib_info->imports_start, lib_info->imports_end);
if (virtual_load)
@ -1883,7 +1898,7 @@ std::shared_ptr<lv2_prx> ppu_load_prx(const ppu_prx_object& elf, bool virtual_lo
ppu_check_patch_spu_images(*prx, seg);
}
prx->analyse(toc, 0, end, applied);
prx->analyse(toc, 0, end, applied, exported_funcs);
if (!ar && !virtual_load)
{
@ -3014,7 +3029,7 @@ std::pair<std::shared_ptr<lv2_overlay>, CellError> ppu_load_overlay(const ppu_ex
const auto cpu = cpu_thread::get_current();
// Analyse executable (TODO)
if (!ovlm->analyse(0, ovlm->entry, end, ovlm->applied_patches, !cpu ? std::function<bool()>() : [cpu]()
if (!ovlm->analyse(0, ovlm->entry, end, ovlm->applied_patches, std::vector<u32>{}, !cpu ? std::function<bool()>() : [cpu]()
{
return !!(cpu->state & cpu_flag::exit);
}))