mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-06 15:01:28 +12:00
PRX loader: Fix libfs_155.sprx loading
Fix relocations' segments referencing when there are "empty" (memsize=0) LOAD segments.
This commit is contained in:
parent
03ad5c6830
commit
7eb16e13bb
6 changed files with 29 additions and 12 deletions
|
@ -593,6 +593,8 @@ void ppu_module::analyse(u32 lib_toc, u32 entry)
|
||||||
// Grope for OPD section (TODO: optimization, better constraints)
|
// Grope for OPD section (TODO: optimization, better constraints)
|
||||||
for (const auto& seg : segs)
|
for (const auto& seg : segs)
|
||||||
{
|
{
|
||||||
|
if (!seg.addr) continue;
|
||||||
|
|
||||||
for (vm::cptr<u32> ptr = vm::cast(seg.addr); ptr.addr() < seg.addr + seg.size; ptr++)
|
for (vm::cptr<u32> ptr = vm::cast(seg.addr); ptr.addr() < seg.addr + seg.size; ptr++)
|
||||||
{
|
{
|
||||||
if (ptr[0] >= start && ptr[0] < end && ptr[0] % 4 == 0 && ptr[1] == toc)
|
if (ptr[0] >= start && ptr[0] < end && ptr[0] % 4 == 0 && ptr[1] == toc)
|
||||||
|
@ -616,6 +618,8 @@ void ppu_module::analyse(u32 lib_toc, u32 entry)
|
||||||
// Find references indiscriminately
|
// Find references indiscriminately
|
||||||
for (const auto& seg : segs)
|
for (const auto& seg : segs)
|
||||||
{
|
{
|
||||||
|
if (!seg.addr) continue;
|
||||||
|
|
||||||
for (vm::cptr<u32> ptr = vm::cast(seg.addr); ptr.addr() < seg.addr + seg.size; ptr++)
|
for (vm::cptr<u32> ptr = vm::cast(seg.addr); ptr.addr() < seg.addr + seg.size; ptr++)
|
||||||
{
|
{
|
||||||
const u32 value = *ptr;
|
const u32 value = *ptr;
|
||||||
|
@ -627,6 +631,8 @@ void ppu_module::analyse(u32 lib_toc, u32 entry)
|
||||||
|
|
||||||
for (const auto& _seg : segs)
|
for (const auto& _seg : segs)
|
||||||
{
|
{
|
||||||
|
if (!_seg.addr) continue;
|
||||||
|
|
||||||
if (value >= _seg.addr && value < _seg.addr + _seg.size)
|
if (value >= _seg.addr && value < _seg.addr + _seg.size)
|
||||||
{
|
{
|
||||||
addr_heap.emplace(value);
|
addr_heap.emplace(value);
|
||||||
|
|
|
@ -811,6 +811,10 @@ std::shared_ptr<lv2_prx> ppu_load_prx(const ppu_prx_object& elf, const std::stri
|
||||||
{
|
{
|
||||||
case 0x1: // LOAD
|
case 0x1: // LOAD
|
||||||
{
|
{
|
||||||
|
auto& _seg = prx->segs.emplace_back();
|
||||||
|
_seg.flags = prog.p_flags;
|
||||||
|
_seg.type = p_type;
|
||||||
|
|
||||||
if (prog.p_memsz)
|
if (prog.p_memsz)
|
||||||
{
|
{
|
||||||
const u32 mem_size = ::narrow<u32>(prog.p_memsz);
|
const u32 mem_size = ::narrow<u32>(prog.p_memsz);
|
||||||
|
@ -840,13 +844,9 @@ std::shared_ptr<lv2_prx> ppu_load_prx(const ppu_prx_object& elf, const std::stri
|
||||||
ppu_register_range(addr, mem_size);
|
ppu_register_range(addr, mem_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
ppu_segment _seg;
|
|
||||||
_seg.addr = addr;
|
_seg.addr = addr;
|
||||||
_seg.size = mem_size;
|
_seg.size = mem_size;
|
||||||
_seg.filesz = file_size;
|
_seg.filesz = file_size;
|
||||||
_seg.type = p_type;
|
|
||||||
_seg.flags = prog.p_flags;
|
|
||||||
prx->segs.emplace_back(_seg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -908,10 +908,22 @@ std::shared_ptr<lv2_prx> ppu_load_prx(const ppu_prx_object& elf, const std::stri
|
||||||
{
|
{
|
||||||
const auto& rel = reinterpret_cast<const ppu_prx_relocation_info&>(prog.bin[i]);
|
const auto& rel = reinterpret_cast<const ppu_prx_relocation_info&>(prog.bin[i]);
|
||||||
|
|
||||||
|
if (rel.offset >= prx->segs.at(rel.index_addr).size)
|
||||||
|
{
|
||||||
|
fmt::throw_exception("Relocation offset out of segment memory! (offset=0x%x, index_addr=%u)", rel.offset, rel.index_addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
const u32 data_base = rel.index_value == 0xFF ? 0 : prx->segs.at(rel.index_value).addr;
|
||||||
|
|
||||||
|
if (rel.index_value != 0xFF && !data_base)
|
||||||
|
{
|
||||||
|
fmt::throw_exception("Empty segment has been referenced for relocation data! (reloc_offset=0x%x, index_value=%u)", i, rel.index_value);
|
||||||
|
}
|
||||||
|
|
||||||
ppu_reloc _rel;
|
ppu_reloc _rel;
|
||||||
const u32 raddr = _rel.addr = vm::cast(prx->segs.at(rel.index_addr).addr + rel.offset);
|
const u32 raddr = _rel.addr = vm::cast(prx->segs.at(rel.index_addr).addr + rel.offset);
|
||||||
const u32 rtype = _rel.type = rel.type;
|
const u32 rtype = _rel.type = rel.type;
|
||||||
const u64 rdata = _rel.data = rel.index_value == 0xFF ? rel.ptr.addr().value() : prx->segs.at(rel.index_value).addr + rel.ptr.addr();
|
const u64 rdata = _rel.data = data_base + rel.ptr.addr();
|
||||||
prx->relocs.emplace_back(_rel);
|
prx->relocs.emplace_back(_rel);
|
||||||
|
|
||||||
switch (rtype)
|
switch (rtype)
|
||||||
|
|
|
@ -2324,9 +2324,10 @@ extern void ppu_initialize(const ppu_module& info)
|
||||||
globals.emplace_back(fmt::format("__cptr%x", suffix), reinterpret_cast<u64>(vm::g_exec_addr));
|
globals.emplace_back(fmt::format("__cptr%x", suffix), reinterpret_cast<u64>(vm::g_exec_addr));
|
||||||
|
|
||||||
// Initialize segments for relocations
|
// Initialize segments for relocations
|
||||||
for (u32 i = 0; i < info.segs.size(); i++)
|
for (u32 i = 0, num = 0; i < info.segs.size(); i++)
|
||||||
{
|
{
|
||||||
globals.emplace_back(fmt::format("__seg%u_%x", i, suffix), info.segs[i].addr);
|
if (!info.segs[i].addr) continue;
|
||||||
|
globals.emplace_back(fmt::format("__seg%u_%x", num++, suffix), info.segs[i].addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
link_workload.emplace_back(obj_name, false);
|
link_workload.emplace_back(obj_name, false);
|
||||||
|
@ -2490,6 +2491,7 @@ extern void ppu_initialize(const ppu_module& info)
|
||||||
|
|
||||||
for (const auto& seg : info.segs)
|
for (const auto& seg : info.segs)
|
||||||
{
|
{
|
||||||
|
if (!seg.addr) continue;
|
||||||
*jit_mod.vars[index++] = seg.addr;
|
*jit_mod.vars[index++] = seg.addr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -70,6 +70,7 @@ PPUTranslator::PPUTranslator(LLVMContext& context, Module* _module, const ppu_mo
|
||||||
// Create segment variables
|
// Create segment variables
|
||||||
for (const auto& seg : m_info.segs)
|
for (const auto& seg : m_info.segs)
|
||||||
{
|
{
|
||||||
|
if (!seg.addr) continue;
|
||||||
auto gv = new GlobalVariable(*_module, GetType<u64>(), true, GlobalValue::ExternalLinkage, 0, fmt::format("__seg%u_%x", m_segs.size(), gsuffix));
|
auto gv = new GlobalVariable(*_module, GetType<u64>(), true, GlobalValue::ExternalLinkage, 0, fmt::format("__seg%u_%x", m_segs.size(), gsuffix));
|
||||||
gv->setInitializer(ConstantInt::get(GetType<u64>(), seg.addr));
|
gv->setInitializer(ConstantInt::get(GetType<u64>(), seg.addr));
|
||||||
gv->setExternallyInitialized(true);
|
gv->setExternallyInitialized(true);
|
||||||
|
|
|
@ -750,6 +750,7 @@ error_code _sys_prx_get_module_info(ppu_thread& ppu, u32 id, u64 flags, vm::ptr<
|
||||||
u32 i = 0;
|
u32 i = 0;
|
||||||
for (; i < prx->segs.size() && i < pOpt->info->segments_num; i++)
|
for (; i < prx->segs.size() && i < pOpt->info->segments_num; i++)
|
||||||
{
|
{
|
||||||
|
if (!prx->segs[i].addr) continue; // TODO: Check this
|
||||||
pOpt->info->segments[i].index = i;
|
pOpt->info->segments[i].index = i;
|
||||||
pOpt->info->segments[i].base = prx->segs[i].addr;
|
pOpt->info->segments[i].base = prx->segs[i].addr;
|
||||||
pOpt->info->segments[i].filesz = prx->segs[i].filesz;
|
pOpt->info->segments[i].filesz = prx->segs[i].filesz;
|
||||||
|
|
|
@ -1150,11 +1150,6 @@ game_boot_result Emulator::Load(const std::string& title_id, bool add_only, bool
|
||||||
// Check .sprx filename
|
// Check .sprx filename
|
||||||
if (fmt::to_upper(entry.name).ends_with(".SPRX"))
|
if (fmt::to_upper(entry.name).ends_with(".SPRX"))
|
||||||
{
|
{
|
||||||
if (entry.name == "libfs_155.sprx")
|
|
||||||
{
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get full path
|
// Get full path
|
||||||
file_queue.emplace_back(dir_queue[i] + entry.name, 0);
|
file_queue.emplace_back(dir_queue[i] + entry.name, 0);
|
||||||
g_progr_ftotal++;
|
g_progr_ftotal++;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue