From 58eef983e23c770c34a0c797017c5de27c7ae7ec Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Mon, 1 Feb 2021 18:33:19 +0300 Subject: [PATCH] PPU Analyser: fix constraints for all elfs. Added for main executable and OVLs. Forgot to use it not just for SPRX. --- rpcs3/Emu/Cell/PPUAnalyser.cpp | 2 +- rpcs3/Emu/Cell/PPUAnalyser.h | 2 +- rpcs3/Emu/Cell/PPUModule.cpp | 48 +++++++++++++++++++++++++++++++--- 3 files changed, 46 insertions(+), 6 deletions(-) diff --git a/rpcs3/Emu/Cell/PPUAnalyser.cpp b/rpcs3/Emu/Cell/PPUAnalyser.cpp index 21d3221ff0..04f5d5954e 100644 --- a/rpcs3/Emu/Cell/PPUAnalyser.cpp +++ b/rpcs3/Emu/Cell/PPUAnalyser.cpp @@ -534,7 +534,7 @@ void ppu_module::analyse(u32 lib_toc, u32 entry, u32 end) // Assume first segment is executable const u32 start = segs[0].addr; - if (end == umax) + if (!end) { end = segs[0].addr + segs[0].size; } diff --git a/rpcs3/Emu/Cell/PPUAnalyser.h b/rpcs3/Emu/Cell/PPUAnalyser.h index 86d0d42cd9..6e9e1c2473 100644 --- a/rpcs3/Emu/Cell/PPUAnalyser.h +++ b/rpcs3/Emu/Cell/PPUAnalyser.h @@ -89,7 +89,7 @@ struct ppu_module secs = info.secs; } - void analyse(u32 lib_toc, u32 entry, u32 end = -1); + void analyse(u32 lib_toc, u32 entry, u32 end = 0); void validate(u32 reloc); }; diff --git a/rpcs3/Emu/Cell/PPUModule.cpp b/rpcs3/Emu/Cell/PPUModule.cpp index 1f5764ca71..e973bfd1bc 100644 --- a/rpcs3/Emu/Cell/PPUModule.cpp +++ b/rpcs3/Emu/Cell/PPUModule.cpp @@ -822,6 +822,8 @@ std::shared_ptr ppu_load_prx(const ppu_prx_object& elf, const std::stri sha1_context sha; sha1_starts(&sha); + u32 end = 0; + for (const auto& prog : elf.progs) { ppu_loader.notice("** Segment: p_type=0x%x, p_vaddr=0x%llx, p_filesz=0x%llx, p_memsz=0x%llx, flags=0x%x", prog.p_type, prog.p_vaddr, prog.p_filesz, prog.p_memsz, prog.p_flags); @@ -865,6 +867,7 @@ std::shared_ptr ppu_load_prx(const ppu_prx_object& elf, const std::stri if (prog.p_flags & 0x1) { ppu_register_range(addr, mem_size); + end = std::max(end, addr + mem_size); } _seg.addr = addr; @@ -881,6 +884,11 @@ std::shared_ptr ppu_load_prx(const ppu_prx_object& elf, const std::stri } } + if (!elf.shdrs.empty()) + { + end = 0; + } + for (const auto& s : elf.shdrs) { ppu_loader.notice("** Section: sh_type=0x%x, addr=0x%llx, size=0x%llx, flags=0x%x", s.sh_type, s.sh_addr, s.sh_size, s.sh_flags); @@ -905,6 +913,11 @@ std::shared_ptr ppu_load_prx(const ppu_prx_object& elf, const std::stri _sec.flags = static_cast(s.sh_flags & 7); _sec.filesz = 0; prx->secs.emplace_back(_sec); + + if (_sec.flags & 0x4) + { + end = std::max(end, _sec.addr + _sec.size); + } break; } } @@ -1058,7 +1071,7 @@ std::shared_ptr ppu_load_prx(const ppu_prx_object& elf, const std::stri prx->specials = ppu_load_exports(link, lib_info->exports_start, lib_info->exports_end); prx->imports = ppu_load_imports(prx->relocs, link, lib_info->imports_start, lib_info->imports_end); std::stable_sort(prx->relocs.begin(), prx->relocs.end()); - prx->analyse(lib_info->toc, 0, std::min(lib_info.addr(), prx->segs[0].addr + prx->segs[0].size)); + prx->analyse(lib_info->toc, 0, end); } else { @@ -1175,6 +1188,9 @@ bool ppu_load_exec(const ppu_exec_object& elf) u32 malloc_pagesize = 0x100000; u32 ppc_seg = 0; + // Limit for analysis + u32 end = 0; + // Executable hash sha1_context sha; sha1_starts(&sha); @@ -1246,6 +1262,7 @@ bool ppu_load_exec(const ppu_exec_object& elf) if (prog.p_flags & 0x1) { ppu_register_range(addr, size); + end = std::max(end, addr + size); } // Store only LOAD segments (TODO) @@ -1253,6 +1270,11 @@ bool ppu_load_exec(const ppu_exec_object& elf) } } + if (!elf.shdrs.empty()) + { + end = 0; + } + // Load section list, used by the analyser for (const auto& s : elf.shdrs) { @@ -1271,6 +1293,11 @@ bool ppu_load_exec(const ppu_exec_object& elf) if (addr && size) { _main->secs.emplace_back(_sec); + + if (_sec.flags & 0x4) + { + end = std::max(end, addr + size); + } } } @@ -1351,7 +1378,7 @@ bool ppu_load_exec(const ppu_exec_object& elf) case 0x00000007: // TLS { ppu_loader.notice("TLS info segment found: tls-image=*0x%x, image-size=0x%x, tls-size=0x%x", prog.p_vaddr, prog.p_filesz, prog.p_memsz); - + if ((prog.p_vaddr | prog.p_filesz | prog.p_memsz) > UINT32_MAX) { ppu_loader.fatal("ppu_load_exec(): TLS segment is invalid!"); @@ -1535,7 +1562,7 @@ bool ppu_load_exec(const ppu_exec_object& elf) _main->path = vfs::get(Emu.argv[0]); // Analyse executable (TODO) - _main->analyse(0, static_cast(elf.header.e_entry)); + _main->analyse(0, static_cast(elf.header.e_entry), end); // Validate analyser results (not required) _main->validate(0); @@ -1738,6 +1765,8 @@ std::pair, CellError> ppu_load_overlay(const ppu_ex const auto ovlm = std::make_shared(); + u32 end = 0; + // Allocate memory at fixed positions for (const auto& prog : elf.progs) { @@ -1784,6 +1813,7 @@ std::pair, CellError> ppu_load_overlay(const ppu_ex if (prog.p_flags & 0x1) { ppu_register_range(addr, size); + end = std::max(end, addr + size); } // Store only LOAD segments (TODO) @@ -1791,6 +1821,11 @@ std::pair, CellError> ppu_load_overlay(const ppu_ex } } + if (elf.shdrs.size()) + { + end = 0; + } + // Load section list, used by the analyser for (const auto& s : elf.shdrs) { @@ -1809,6 +1844,11 @@ std::pair, CellError> ppu_load_overlay(const ppu_ex if (addr && size) { ovlm->secs.emplace_back(_sec); + + if (_sec.flags & 0x4) + { + end = std::max(end, addr + size); + } } } @@ -1926,7 +1966,7 @@ std::pair, CellError> ppu_load_overlay(const ppu_ex ovlm->entry = static_cast(elf.header.e_entry); // Analyse executable (TODO) - ovlm->analyse(0, ovlm->entry); + ovlm->analyse(0, ovlm->entry, end); // Validate analyser results (not required) ovlm->validate(0);