From def21a52bb18ed1219ec06fd0b3ea7deb618d4d4 Mon Sep 17 00:00:00 2001 From: James Sandri <7078671+jlsandri@users.noreply.github.com> Date: Fri, 27 Mar 2026 00:37:38 +1100 Subject: [PATCH] Clamp overlapping Ghidra function boundaries MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ghidra's auto-analysis can produce overlapping function ranges where a parent function's reported length includes nested sub-functions (e.g. a parent reported as 456 bytes when it should be 52). The recompiler then emits one giant body containing sub-functions inline, and pc-mismatch safety checks on sub-calls cause cascading early returns. After merging all function sources in extractFunctions(), clamp each function's end to the next function's start — unless the gap is < 16 bytes (entry slice pattern). --- ps2xRecomp/src/lib/elf_parser.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/ps2xRecomp/src/lib/elf_parser.cpp b/ps2xRecomp/src/lib/elf_parser.cpp index bd91e037..a4696e93 100644 --- a/ps2xRecomp/src/lib/elf_parser.cpp +++ b/ps2xRecomp/src/lib/elf_parser.cpp @@ -797,6 +797,27 @@ namespace ps2recomp func.end = (nextStart > func.start) ? nextStart : (func.start + 4); } + // Clamp overlapping functions. Ghidra sometimes reports parent functions + // whose range includes nested sub-functions (e.g. 0x1046B8 spanning + // 456 bytes when it should be 52). Without this clamp the recompiler + // emits one giant body containing the sub-functions inline, and the + // pc-mismatch checks on sub-calls cause cascading early returns. + // + // Entry slices (alternate entry points into the same function body) + // start within a few bytes of the parent (e.g. 0x15D680 and + // game_loop_body at 0x15D684). These must NOT be clamped — doing so + // would truncate the parent to just a few bytes. We use a 16-byte + // threshold: if the next function starts within 16 bytes, it is likely + // an entry slice and we skip the clamp. + for (size_t index = 0; index + 1 < functions.size(); index++) + { + uint32_t gap = functions[index + 1].start - functions[index].start; + if (functions[index].end > functions[index + 1].start && gap >= 16) + { + functions[index].end = functions[index + 1].start; + } + } + return functions; }