mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-15 13:21:14 +00:00
PPU Loader: Fix imports/exports in virtual mode
This commit is contained in:
parent
c96f3a877f
commit
506ec0f947
@ -168,19 +168,19 @@ struct ppu_module
|
||||
}
|
||||
|
||||
template <typename T, typename U> requires requires (const U& obj) { +obj.size() * 0; }
|
||||
to_be_t<T>& get_ref(U&& addr,
|
||||
to_be_t<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<T> ? 0 : sizeof(std::conditional_t<std::is_void_v<T>, char, T>);
|
||||
if (auto ptr = get_ptr<T>(addr.addr(), u32{size_element}))
|
||||
if (auto ptr = get_ptr<T>((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<to_be_t<T>>{};
|
||||
}
|
||||
};
|
||||
|
@ -552,7 +552,7 @@ extern const std::unordered_map<u32, std::string_view>& get_exported_function_na
|
||||
}
|
||||
|
||||
// Resolve relocations for variable/function linkage.
|
||||
static void ppu_patch_refs(std::vector<ppu_reloc>* out_relocs, u32 fref, u32 faddr)
|
||||
static void ppu_patch_refs(const ppu_module& _module, std::vector<ppu_reloc>* out_relocs, u32 fref, u32 faddr)
|
||||
{
|
||||
struct ref_t
|
||||
{
|
||||
@ -561,7 +561,7 @@ static void ppu_patch_refs(std::vector<ppu_reloc>* out_relocs, u32 fref, u32 fad
|
||||
be_t<u32> 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<ref_t>::make(fref); ref->type; ref++)
|
||||
for (const ref_t* ref = &_module.get_ref<ref_t>(fref); ref->type; fref += sizeof(ref_t), ref = &_module.get_ref<ref_t>(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<ppu_reloc>* out_relocs, u32 fref, u32 fad
|
||||
{
|
||||
case 1:
|
||||
{
|
||||
const u32 value = vm::_ref<u32>(ref->addr) = rdata;
|
||||
const u32 value = _module.get_ref<u32>(ref->addr) = rdata;
|
||||
ppu_loader.trace("**** REF(1): 0x%x <- 0x%x", ref->addr, value);
|
||||
break;
|
||||
}
|
||||
|
||||
case 4:
|
||||
{
|
||||
const u16 value = vm::_ref<u16>(ref->addr) = static_cast<u16>(rdata);
|
||||
const u16 value = _module.get_ref<u16>(ref->addr) = static_cast<u16>(rdata);
|
||||
ppu_loader.trace("**** REF(4): 0x%x <- 0x%04x (0x%llx)", ref->addr, value, faddr);
|
||||
break;
|
||||
}
|
||||
|
||||
case 6:
|
||||
{
|
||||
const u16 value = vm::_ref<u16>(ref->addr) = static_cast<u16>(rdata >> 16) + (rdata & 0x8000 ? 1 : 0);
|
||||
const u16 value = _module.get_ref<u16>(ref->addr) = static_cast<u16>(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<ppu_bf_t<be_t<u16>, 0, 14>>(ref->addr) = static_cast<u16>(rdata) >> 2;
|
||||
const u16 value = _module.get_ref<ppu_bf_t<be_t<u16>, 0, 14>>(ref->addr) = static_cast<u16>(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<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::basic_string<bool>* loaded_flags = nullptr)
|
||||
{
|
||||
std::unordered_map<u32, u32> 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<ppu_prx_module_info>(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<u32>(lib.nids, i);
|
||||
const u32 addr = _module.get_ref<u32>(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<u32>(addr), vm::_ref<u32>(addr + 4));
|
||||
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));
|
||||
}
|
||||
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<const char>(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<u32>(fnids, i);
|
||||
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));
|
||||
|
||||
// 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<u32>(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<u32>(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<u32>(vnids, i);
|
||||
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);
|
||||
|
||||
// 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<ppu_reloc>& relocs, ppu_linkage_info* link, u32 imports_start, u32 imports_end)
|
||||
static auto ppu_load_imports(const ppu_module& _module, std::vector<ppu_reloc>& relocs, ppu_linkage_info* link, u32 imports_start, u32 imports_end)
|
||||
{
|
||||
std::unordered_map<u32, void*> 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<const ppu_prx_module_info>(addr);
|
||||
const auto& lib = _module.get_ref<const ppu_prx_module_info>(addr);
|
||||
|
||||
const std::string module_name(lib.name.get_ptr());
|
||||
const std::string module_name(&_module.get_ref<const char>(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<ppu_reloc>& 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<u32>(fnids, i);
|
||||
const u32 fstub = _module.get_ref<u32>(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<ppu_reloc>& relocs, ppu_linkage_info* l
|
||||
const u32 link_addr = flink.export_addr ? flink.export_addr : g_fxo->get<ppu_function_manager>().addr;
|
||||
|
||||
// Write import table
|
||||
vm::write32(faddr, link_addr);
|
||||
_module.get_ref<u32>(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<u32>(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<ppu_reloc>& 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<u32>(vnids, i);
|
||||
const u32 vref = _module.get_ref<u32>(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<ppu_reloc>& 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<main_ppu_module>();
|
||||
auto& link = g_fxo->get<ppu_linkage_info>();
|
||||
|
||||
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<lv2_prx> 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<std::shared_ptr<lv2_overlay>, 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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user