From c96f3a877f37f3a9bd0903c0f5c6190aaad35f1c Mon Sep 17 00:00:00 2001 From: Eladash Date: Sun, 6 Aug 2023 14:02:36 +0300 Subject: [PATCH] PPU Analyzer: Add more function constraints --- rpcs3/Emu/Cell/PPUAnalyser.cpp | 40 ++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/rpcs3/Emu/Cell/PPUAnalyser.cpp b/rpcs3/Emu/Cell/PPUAnalyser.cpp index 2a0186213c..f878e22cb2 100644 --- a/rpcs3/Emu/Cell/PPUAnalyser.cpp +++ b/rpcs3/Emu/Cell/PPUAnalyser.cpp @@ -556,6 +556,32 @@ bool ppu_module::analyse(u32 lib_toc, u32 entry, const u32 sec_end, const std::b // Known references (within segs, addr and value alignment = 4) std::set addr_heap{entry}; + auto verify_func = [&](u32 addr) + { + if (!entry) + { + // Fixed addresses + return true; + } + + // Check if the storage address exists within relocations + + for (auto& rel : this->relocs) + { + if ((rel.addr & -8) == (addr & -8)) + { + if (rel.type != 38 && rel.type != 44 && (rel.addr & -4) != (addr & -4)) + { + continue; + } + + return true; + } + } + + return false; + }; + // Register new function auto add_func = [&](u32 addr, u32 toc, u32 caller) -> ppu_function& { @@ -617,7 +643,7 @@ bool ppu_module::analyse(u32 lib_toc, u32 entry, const u32 sec_end, const std::b for (; _ptr <= seg_end;) { - if (ptr[1] == toc && ptr[0] >= start && ptr[0] < end && ptr[0] % 4 == 0) + if (ptr[1] == toc && ptr[0] >= start && ptr[0] < end && ptr[0] % 4 == 0 && verify_func(_ptr.addr())) { // New function ppu_log.trace("OPD*: [0x%x] 0x%x (TOC=0x%x)", _ptr, ptr[0], ptr[1]); @@ -700,13 +726,13 @@ bool ppu_module::analyse(u32 lib_toc, u32 entry, const u32 sec_end, const std::b //const u32 _toc_end = _toc + 0x8000; // TODO: improve TOC constraints - if (_toc % 4 || !get_ptr(_toc) || _toc >= 0x40000000 || (_toc >= start && _toc < end)) + if (_toc % 4 || !get_ptr(_toc) || _toc >= 0x40000000 || (_toc >= start && _toc < end)) { sec_end.set(0); break; } - if (addr % 4 || addr < start || addr >= end || addr == _toc) + if (addr % 4 || addr < start || addr >= end || addr == _toc || !verify_func(_ptr.addr())) { sec_end.set(0); break; @@ -956,7 +982,7 @@ bool ppu_module::analyse(u32 lib_toc, u32 entry, const u32 sec_end, const std::b // Simple trampoline const u32 target = (ptr[0] << 16) + ppu_opcode_t{ptr[1]}.simm16; - if (target >= start && target < end) + if (target >= start && target < end && verify_func(_ptr.addr())) { auto& new_func = add_func(target, func.toc, func.addr); @@ -1027,7 +1053,7 @@ bool ppu_module::analyse(u32 lib_toc, u32 entry, const u32 sec_end, const std::b const u32 target = (ptr[3] << 16) + s16(ptr[4]); const u32 toc_add = (ptr[1] << 16) + s16(ptr[2]); - if (target >= start && target < end) + if (target >= start && target < end && verify_func((_ptr + 3).addr())) { auto& new_func = add_func(target, 0, func.addr); @@ -1074,7 +1100,7 @@ bool ppu_module::analyse(u32 lib_toc, u32 entry, const u32 sec_end, const std::b const u32 toc_add = (ptr[1] << 16) + s16(ptr[2]); const u32 target = (ptr[3] & 0x2 ? 0 : (_ptr + 3).addr()) + ppu_opcode_t{ptr[3]}.bt24; - if (target >= start && target < end) + if (target >= start && target < end && verify_func((_ptr + 3).addr())) { auto& new_func = add_func(target, 0, func.addr); @@ -1437,7 +1463,7 @@ bool ppu_module::analyse(u32 lib_toc, u32 entry, const u32 sec_end, const std::b { const u32 target = (op.aa ? 0 : iaddr) + (type == ppu_itype::B ? +op.bt24 : +op.bt14); - if (target >= start && target < end) + if (target >= start && target < end && verify_func((_ptr - 1).addr())) { if (target < func.addr || target >= func.addr + func.size) {