diff --git a/rpcs3/Emu/Cell/PPUModule.cpp b/rpcs3/Emu/Cell/PPUModule.cpp index 5100a0e785..764a5cc76d 100644 --- a/rpcs3/Emu/Cell/PPUModule.cpp +++ b/rpcs3/Emu/Cell/PPUModule.cpp @@ -119,6 +119,7 @@ struct ppu_linkage_info std::unordered_map> functions; std::unordered_map> variables; + // Obsolete bool imported = false; }; @@ -578,8 +579,10 @@ static auto ppu_load_exports(const std::shared_ptr& link, u32 return result; } -static void ppu_load_imports(std::vector& relocs, const std::shared_ptr& link, u32 imports_start, u32 imports_end) +static auto ppu_load_imports(std::vector& relocs, const std::shared_ptr& link, u32 imports_start, u32 imports_end) { + std::unordered_map result; + for (u32 addr = imports_start; addr < imports_end;) { const auto& lib = vm::_ref(addr); @@ -613,6 +616,7 @@ static void ppu_load_imports(std::vector& relocs, const std::shared_p auto& flink = link->modules[module_name].functions[fnid]; // Add new import + result.emplace(faddr, &flink); flink.imports.emplace(faddr); mlink.imported = true; @@ -625,6 +629,7 @@ static void ppu_load_imports(std::vector& relocs, const std::shared_p // Patch refs if necessary (0x2000 seems to be correct flag indicating the presence of additional info) if (const u32 frefs = (lib.attributes & 0x2000) ? +fnids[i + lib.num_func] : 0) { + result.emplace(frefs, &flink); flink.frefss.emplace(frefs); ppu_patch_refs(&relocs, frefs, link_addr); } @@ -645,6 +650,7 @@ static void ppu_load_imports(std::vector& relocs, const std::shared_p auto& vlink = link->modules[module_name].variables[vnid]; // Add new import + result.emplace(vref, &vlink); vlink.imports.emplace(vref); mlink.imported = true; @@ -656,6 +662,8 @@ static void ppu_load_imports(std::vector& relocs, const std::shared_p addr += lib.size ? lib.size : sizeof(ppu_prx_module_info); } + + return result; } std::shared_ptr ppu_load_prx(const ppu_prx_object& elf, const std::string& path) @@ -870,8 +878,7 @@ std::shared_ptr ppu_load_prx(const ppu_prx_object& elf, const std::stri LOG_WARNING(LOADER, "Library %s (rtoc=0x%x):", lib_name, lib_info->toc); prx->specials = ppu_load_exports(link, lib_info->exports_start, lib_info->exports_end); - - ppu_load_imports(prx->relocs, link, lib_info->imports_start, lib_info->imports_end); + prx->imports = ppu_load_imports(prx->relocs, link, lib_info->imports_start, lib_info->imports_end); prx->analyse(lib_info->toc, 0); } @@ -892,6 +899,14 @@ std::shared_ptr ppu_load_prx(const ppu_prx_object& elf, const std::stri void ppu_unload_prx(const lv2_prx& prx) { + // Clean linkage info + for (auto& imp : prx.imports) + { + auto pinfo = static_cast(imp.second); + pinfo->frefss.erase(imp.first); + pinfo->imports.erase(imp.first); + } + for (auto& seg : prx.segs) { vm::dealloc(seg.addr, vm::main); diff --git a/rpcs3/Emu/Cell/lv2/sys_prx.h b/rpcs3/Emu/Cell/lv2/sys_prx.h index 4067464ea1..307f90db14 100644 --- a/rpcs3/Emu/Cell/lv2/sys_prx.h +++ b/rpcs3/Emu/Cell/lv2/sys_prx.h @@ -115,6 +115,7 @@ struct lv2_prx final : lv2_obj, ppu_module bool is_started = false; std::unordered_map specials; + std::unordered_map imports; vm::ps3::ptr argv)> start = vm::null; vm::ps3::ptr argv)> stop = vm::null;