diff --git a/rpcs3/Emu/Cell/PPUAnalyser.h b/rpcs3/Emu/Cell/PPUAnalyser.h index cde7fb7949..c2965267cb 100644 --- a/rpcs3/Emu/Cell/PPUAnalyser.h +++ b/rpcs3/Emu/Cell/PPUAnalyser.h @@ -168,19 +168,19 @@ struct ppu_module } template requires requires (const U& obj) { +obj.size() * 0; } - to_be_t& get_ref(U&& addr, + to_be_t& get_ref(U&& addr, u32 index = 0, u32 line = __builtin_LINE(), u32 col = __builtin_COLUMN(), const char* file = __builtin_FILE(), const char* func = __builtin_FUNCTION()) const { constexpr usz size_element = std::is_void_v ? 0 : sizeof(std::conditional_t, char, T>); - if (auto ptr = get_ptr(addr.addr(), u32{size_element})) + if (auto ptr = get_ptr((addr + index).addr(), u32{size_element})) { return *ptr; } - fmt::throw_exception("get_ref(): Failure! (addr=0x%x)%s", addr.addr(), src_loc{line, col, file, func}); + fmt::throw_exception("get_ref(): Failure! (addr=0x%x)%s", (addr + index).addr(), src_loc{line, col, file, func}); return *std::add_pointer_t>{}; } }; diff --git a/rpcs3/Emu/Cell/PPUModule.cpp b/rpcs3/Emu/Cell/PPUModule.cpp index 060b767c7e..a8deaa53ff 100644 --- a/rpcs3/Emu/Cell/PPUModule.cpp +++ b/rpcs3/Emu/Cell/PPUModule.cpp @@ -552,7 +552,7 @@ extern const std::unordered_map& get_exported_function_na } // Resolve relocations for variable/function linkage. -static void ppu_patch_refs(std::vector* out_relocs, u32 fref, u32 faddr) +static void ppu_patch_refs(const ppu_module& _module, std::vector* out_relocs, u32 fref, u32 faddr) { struct ref_t { @@ -561,7 +561,7 @@ static void ppu_patch_refs(std::vector* out_relocs, u32 fref, u32 fad be_t addend; // Note: Treating it as addend seems to be correct for now, but still unknown if theres more in this variable }; - for (auto ref = vm::ptr::make(fref); ref->type; ref++) + for (const ref_t* ref = &_module.get_ref(fref); ref->type; fref += sizeof(ref_t), ref = &_module.get_ref(fref)) { if (ref->addend) ppu_loader.warning("**** REF(%u): Addend value(0x%x, 0x%x)", ref->type, ref->addr, ref->addend); @@ -584,28 +584,28 @@ static void ppu_patch_refs(std::vector* out_relocs, u32 fref, u32 fad { case 1: { - const u32 value = vm::_ref(ref->addr) = rdata; + const u32 value = _module.get_ref(ref->addr) = rdata; ppu_loader.trace("**** REF(1): 0x%x <- 0x%x", ref->addr, value); break; } case 4: { - const u16 value = vm::_ref(ref->addr) = static_cast(rdata); + const u16 value = _module.get_ref(ref->addr) = static_cast(rdata); ppu_loader.trace("**** REF(4): 0x%x <- 0x%04x (0x%llx)", ref->addr, value, faddr); break; } case 6: { - const u16 value = vm::_ref(ref->addr) = static_cast(rdata >> 16) + (rdata & 0x8000 ? 1 : 0); + const u16 value = _module.get_ref(ref->addr) = static_cast(rdata >> 16) + (rdata & 0x8000 ? 1 : 0); ppu_loader.trace("**** REF(6): 0x%x <- 0x%04x (0x%llx)", ref->addr, value, faddr); break; } case 57: { - const u16 value = vm::_ref, 0, 14>>(ref->addr) = static_cast(rdata) >> 2; + const u16 value = _module.get_ref, 0, 14>>(ref->addr) = static_cast(rdata) >> 2; ppu_loader.trace("**** REF(57): 0x%x <- 0x%04x (0x%llx)", ref->addr, value, faddr); break; } @@ -680,7 +680,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(ppu_linkage_info* link, u32 exports_start, u32 exports_end, bool for_observing_callbacks = false, std::basic_string* 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::basic_string* loaded_flags = nullptr) { std::unordered_map result; @@ -694,7 +694,7 @@ static auto ppu_load_exports(ppu_linkage_info* link, u32 exports_start, u32 expo for (u32 addr = exports_start; addr < exports_end; unload_index++, addr += lib.size ? lib.size : sizeof(ppu_prx_module_info)) { - std::memcpy(&lib, vm::base(addr), sizeof(lib)); + std::memcpy(&lib, &_module.get_ref(addr), sizeof(lib)); const bool is_library = !!(lib.attributes & PRX_EXPORT_LIBRARY_FLAG); const bool is_management = !is_library && !!(lib.attributes & PRX_EXPORT_PRX_MANAGEMENT_FUNCTIONS_FLAG); @@ -709,12 +709,12 @@ static auto ppu_load_exports(ppu_linkage_info* link, u32 exports_start, u32 expo // Set special exports for (u32 i = 0, end = lib.num_func + lib.num_var; i < end; i++) { - const u32 nid = lib.nids[i]; - const u32 addr = lib.addrs[i]; + const u32 nid = _module.get_ref(lib.nids, i); + const u32 addr = _module.get_ref(lib.addrs, i); if (i < lib.num_func) { - ppu_loader.notice("** Special: [%s] at 0x%x [0x%x, 0x%x]", ppu_get_function_name({}, nid), addr, vm::_ref(addr), vm::_ref(addr + 4)); + ppu_loader.notice("** Special: [%s] at 0x%x [0x%x, 0x%x]", ppu_get_function_name({}, nid), addr, _module.get_ref(addr), _module.get_ref(addr + 4)); } else { @@ -738,7 +738,7 @@ static auto ppu_load_exports(ppu_linkage_info* link, u32 exports_start, u32 expo continue; } - const std::string module_name(lib.name.get_ptr()); + const std::string module_name(&_module.get_ref(lib.name)); if (unload_exports) { @@ -782,9 +782,9 @@ static auto ppu_load_exports(ppu_linkage_info* link, u32 exports_start, u32 expo // Get functions for (u32 i = 0, end = lib.num_func; i < end; i++) { - const u32 fnid = fnids[i]; - const u32 faddr = 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, vm::read32(faddr)); + const u32 fnid = _module.get_ref(fnids, i); + const u32 faddr = _module.get_ref(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(faddr)); // Function linkage info auto& flink = mlink.functions[fnid]; @@ -811,7 +811,10 @@ static auto ppu_load_exports(ppu_linkage_info* link, u32 exports_start, u32 expo // Set exported function flink.export_addr = target - 4; - ppu_form_branch_to_code(vm::read32(faddr), target); + if (auto ptr = _module.get_ptr(faddr); vm::try_get_addr(ptr).first) + { + ppu_form_branch_to_code(*ptr, target); + } } else { @@ -821,13 +824,13 @@ static auto ppu_load_exports(ppu_linkage_info* link, u32 exports_start, u32 expo // Fix imports for (const u32 addr : flink.imports) { - vm::write32(addr, faddr); + _module.get_ref(addr) = faddr; //ppu_loader.warning("Exported function '%s' in module '%s'", ppu_get_function_name(module_name, fnid), module_name); } for (const u32 fref : flink.frefss) { - ppu_patch_refs(nullptr, fref, faddr); + ppu_patch_refs(_module, nullptr, fref, faddr); } } } @@ -839,8 +842,8 @@ static auto ppu_load_exports(ppu_linkage_info* link, u32 exports_start, u32 expo // Get variables for (u32 i = 0, end = lib.num_var; i < end; i++) { - const u32 vnid = vnids[i]; - const u32 vaddr = vaddrs[i]; + const u32 vnid = _module.get_ref(vnids, i); + const u32 vaddr = _module.get_ref(vaddrs, i); ppu_loader.notice("**** %s export: &[%s] at 0x%x", module_name, ppu_get_variable_name(module_name, vnid), vaddr); // Variable linkage info @@ -863,7 +866,7 @@ static auto ppu_load_exports(ppu_linkage_info* link, u32 exports_start, u32 expo // Fix imports for (const auto vref : vlink.imports) { - ppu_patch_refs(nullptr, vref, vaddr); + ppu_patch_refs(_module, nullptr, vref, vaddr); //ppu_loader.warning("Exported variable '%s' in module '%s'", ppu_get_variable_name(module_name, vnid), module_name); } } @@ -873,17 +876,17 @@ static auto ppu_load_exports(ppu_linkage_info* link, u32 exports_start, u32 expo return result; } -static auto ppu_load_imports(std::vector& relocs, ppu_linkage_info* link, u32 imports_start, u32 imports_end) +static auto ppu_load_imports(const ppu_module& _module, std::vector& relocs, ppu_linkage_info* link, u32 imports_start, u32 imports_end) { std::unordered_map result; - reader_lock lock(link->mutex); + std::lock_guard lock(link->mutex); for (u32 addr = imports_start; addr < imports_end;) { - const auto& lib = vm::_ref(addr); + const auto& lib = _module.get_ref(addr); - const std::string module_name(lib.name.get_ptr()); + const std::string module_name(&_module.get_ref(lib.name)); ppu_loader.notice("** Imported module '%s' (ver=0x%x, attr=0x%x, 0x%x, 0x%x) [0x%x]", module_name, lib.version, lib.attributes, lib.unk4, lib.unk5, addr); @@ -903,8 +906,8 @@ static auto ppu_load_imports(std::vector& relocs, ppu_linkage_info* l for (u32 i = 0, end = lib.num_func; i < end; i++) { - const u32 fnid = fnids[i]; - const u32 fstub = faddrs[i]; + const u32 fnid = _module.get_ref(fnids, i); + const u32 fstub = _module.get_ref(faddrs, i); const u32 faddr = (faddrs + i).addr(); ppu_loader.notice("**** %s import: [%s] (0x%08x) -> 0x%x", module_name, ppu_get_function_name(module_name, fnid), fnid, fstub); @@ -920,14 +923,14 @@ static auto ppu_load_imports(std::vector& relocs, ppu_linkage_info* l const u32 link_addr = flink.export_addr ? flink.export_addr : g_fxo->get().addr; // Write import table - vm::write32(faddr, link_addr); + _module.get_ref(faddr) = link_addr; // 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) + if (const u32 frefs = (lib.attributes & 0x2000) ? +_module.get_ref(fnids, i + lib.num_func) : 0) { result.emplace(frefs, &flink); flink.frefss.emplace(frefs); - ppu_patch_refs(&relocs, frefs, link_addr); + ppu_patch_refs(_module, &relocs, frefs, link_addr); } //ppu_loader.warning("Imported function '%s' in module '%s' (0x%x)", ppu_get_function_name(module_name, fnid), module_name, faddr); @@ -938,8 +941,8 @@ static auto ppu_load_imports(std::vector& relocs, ppu_linkage_info* l for (u32 i = 0, end = lib.num_var; i < end; i++) { - const u32 vnid = vnids[i]; - const u32 vref = vstubs[i]; + const u32 vnid = _module.get_ref(vnids, i); + const u32 vref = _module.get_ref(vstubs, i); ppu_loader.notice("**** %s import: &[%s] (ref=*0x%x)", module_name, ppu_get_variable_name(module_name, vnid), vref); // Variable linkage info @@ -951,7 +954,7 @@ static auto ppu_load_imports(std::vector& relocs, ppu_linkage_info* l mlink.imported = true; // Link if available - ppu_patch_refs(&relocs, vref, vlink.export_addr); + ppu_patch_refs(_module, &relocs, vref, vlink.export_addr); //ppu_loader.warning("Imported variable '%s' in module '%s' (0x%x)", ppu_get_variable_name(module_name, vnid), module_name, vlink.first); } @@ -968,14 +971,18 @@ void ppu_manual_load_imports_exports(u32 imports_start, u32 imports_size, u32 ex auto& _main = g_fxo->get(); auto& link = g_fxo->get(); - ppu_load_exports(&link, exports_start, exports_start + exports_size, false, &loaded_flags); + ppu_module vm_all_fake_module{}; + vm_all_fake_module.segs.emplace_back(ppu_segment{0x10000, -0x10000u, 1 /*LOAD*/, 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); if (!imports_size) { return; } - ppu_load_imports(_main.relocs, &link, imports_start, imports_start + imports_size); + ppu_load_imports(vm_all_fake_module, _main.relocs, &link, imports_start, imports_start + imports_size); } // For savestates @@ -1569,10 +1576,14 @@ std::shared_ptr ppu_load_prx(const ppu_prx_object& elf, bool virtual_lo ppu_loader.warning("Library %s (rtoc=0x%x):", lib_name, lib_info->toc); - if (!virtual_load) + ppu_linkage_info dummy{}; + + prx->specials = ppu_load_exports(*prx, virtual_load ? &dummy : &link, prx->exports_start, prx->exports_end, true); + prx->imports = ppu_load_imports(*prx, prx->relocs, virtual_load ? &dummy : &link, lib_info->imports_start, lib_info->imports_end); + + if (virtual_load) { - prx->specials = ppu_load_exports(&link, prx->exports_start, prx->exports_end, true); - prx->imports = ppu_load_imports(prx->relocs, &link, lib_info->imports_start, lib_info->imports_end); + prx->imports.clear(); } std::stable_sort(prx->relocs.begin(), prx->relocs.end()); @@ -2105,10 +2116,12 @@ bool ppu_load_exec(const ppu_exec_object& elf, bool virtual_load, const std::str return false; } + ppu_linkage_info dummy{}; + if (!virtual_load) { - ppu_load_exports(&link, proc_prx_param.libent_start, proc_prx_param.libent_end); - ppu_load_imports(_main.relocs, &link, proc_prx_param.libstub_start, proc_prx_param.libstub_end); + ppu_load_exports(_main, virtual_load ? &dummy : &link, proc_prx_param.libent_start, proc_prx_param.libent_end); + ppu_load_imports(_main, _main.relocs, virtual_load ? &dummy : &link, proc_prx_param.libstub_start, proc_prx_param.libstub_end); } std::stable_sort(_main.relocs.begin(), _main.relocs.end()); @@ -2667,10 +2680,12 @@ std::pair, CellError> ppu_load_overlay(const ppu_ex fmt::throw_exception("Bad magic! (0x%x)", proc_prx_param.magic); } + ppu_linkage_info dummy{}; + if (!virtual_load) { - 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); + ppu_load_exports(*ovlm, virtual_load ? &dummy : &link, proc_prx_param.libent_start, proc_prx_param.libent_end); + ppu_load_imports(*ovlm, ovlm->relocs, virtual_load ? &dummy : &link, proc_prx_param.libstub_start, proc_prx_param.libstub_end); } } break;