mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-25 18:05:12 -04:00
runtime: validate stale-static ranges in full — drop the exec_pc clip
dirty_ram_text_native_ok_ranges_from clipped validation to [exec_pc, end), assuming a continuation never fetches bytes behind its resume PC. False for any entry with a backward edge: a post-call continuation re-enters mid-function and loops back into the clipped region, executing stale static code. CMR2's overlay engine carries a second copy of the vertex-transform kernel at 0x80016B34 that forked exactly this way (r16 +0xA0 static vs +0x100 live, the same 0x60 delta as the first locus) after the inter-piece transfer guards closed the fallthrough edge. Validation now covers every emitted range of the entry regardless of resume PC. A genuinely patched prologue blocks the whole entry to the dirty-RAM interpreter -- correct, merely slower.
This commit is contained in:
+9
-10
@@ -482,15 +482,19 @@ int dirty_ram_text_native_ok(uint32_t phys) {
|
||||
* a mismatch never poisons an unrelated 4 KB page forever: every decision is
|
||||
* made from the live bytes the native body will actually execute.
|
||||
*
|
||||
* exec_pc is the dispatch/resume address. Ranges that end at or before that PC
|
||||
* are skipped, and a range that straddles it is clipped to [exec_pc, end). A
|
||||
* runtime patch of a function prologue must not block a compiled continuation
|
||||
* that never fetches the patched bytes. */
|
||||
* exec_pc is the dispatch/resume address, kept for observability and future
|
||||
* use; ranges are validated IN FULL regardless of it. The former
|
||||
* [exec_pc, end) clip assumed a continuation "never fetches the patched
|
||||
* bytes" behind its resume PC — false for any entry with a backward edge:
|
||||
* a post-call continuation re-enters mid-function and loops back into the
|
||||
* clipped-away region, executing stale static code (CMR2 overlay
|
||||
* corruption, second locus 0x80016B34). A genuinely patched prologue now
|
||||
* blocks the whole entry to the interpreter — correct, merely slower. */
|
||||
int dirty_ram_text_native_ok_ranges_from(const uint32_t *lo_len_pairs,
|
||||
uint32_t count,
|
||||
uint32_t exec_pc) {
|
||||
if (!text_ref_image || !lo_len_pairs || count == 0) return 0;
|
||||
uint32_t at = exec_pc & 0x1FFFFFFFu;
|
||||
(void)exec_pc;
|
||||
int any = 0;
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
uint32_t phys = lo_len_pairs[i * 2u] & 0x1FFFFFFFu;
|
||||
@@ -500,11 +504,6 @@ int dirty_ram_text_native_ok_ranges_from(const uint32_t *lo_len_pairs,
|
||||
g_text_native_blocked++;
|
||||
return 0;
|
||||
}
|
||||
if (phys + len <= at) continue;
|
||||
if (phys < at) {
|
||||
len -= at - phys;
|
||||
phys = at;
|
||||
}
|
||||
any = 1;
|
||||
/* Page-clean fast path: every page this range touches is neither
|
||||
* guard-modified nor runtime-dirty, so its bytes still equal the
|
||||
|
||||
Reference in New Issue
Block a user