dirty_ram per_pc: stamp resident-occupant CRC and caller RA on external entries

Make a bare interpreted PC explainable from the session-long per_pc snapshot
alone. DirtyRamPcEntry gains occ_crc / occ_ok (the static overlay variant whose
code ranges span the PC, via a per-PC scan of the static-match cache, and
whether it validated at that moment) and last_ext_ra (gpr[31] at the most
recent external entry, i.e. the caller that reached this interior). Both are
stamped only on external entries -- arrivals from native dispatch, not interp
block chaining -- and emitted per row in dirty_ram_stats.per_pc as occ_crc,
occ_ok and ext_ra.

Reading the pair: occ_ok=1 is an interior gap inside live native code (an
alias seed fixes it); occ_ok=0 with a CRC means the spanning piece is resident
but CRC-missing, so it was compiled from another section's bytes or rewritten
at run time and no seed helps; 0 means nothing compiled spans the PC.

psx_overlay_resident_crc_at() records each static-match cache entry's code
span (lo_min/hi_max) so the scan is a range test; DLL-path titles fall back to
the loader's last residency hash. The debug-server reply buffer grows 32 -> 64
KiB for the wider rows; the tail reserve still cuts between rows.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
Kevin
2026-09-05 18:11:13 -04:00
parent 17f49ad3b2
commit 6e760748c2
5 changed files with 145 additions and 4 deletions
+37
View File
@@ -243,6 +243,43 @@ vector observation there.
---
## `dirty_ram_stats` `per_pc` — interpreted-PC table
Snapshot of the open-addressed per-entry-PC table
(`g_dirty_ram_pc_table`, `dirty_ram_interp.c`): one object per interpreted
entry PC. Read-only; safe to poll while the game runs.
- `pc` — physical entry PC.
- `hits` — dispatches here (interp block chaining conflated in).
- `insns` — instructions executed across those hits.
- `entries` — dispatches that arrived from NATIVE code (a call or a fresh
dispatch), not interp block-to-block chaining. `entries > 0` marks a real
interior entry point — the seed stream for overlay-capture aliasing.
- `occ_crc` / `occ_ok` — enrichment (2026-09-05): at the last external
entry, the manifest CRC of the static overlay variant whose code ranges
span this PC (`psx_overlay_resident_crc_at`; DLL-path titles get the last
residency hash instead), and whether it validated then. The CRC is the one
the variant was compiled from, so it maps straight back to a capture /
`.EMI` section offline. Read the pair as: `occ_ok = 1` — an interior gap
inside live native code, an alias seed will make it native; `occ_ok = 0`
with a CRC — the band's compiled occupant is resident but CRC-missing (data
inside the code range is rewritten at run time, or the section differs from
the compiled one), so the whole band runs interpreted and no seed helps;
`0x00000000` — nothing compiled spans this PC (BIOS / kernel / boot EXE).
- `ext_ra` — enrichment: `$ra` at the most recent external entry, i.e. the
caller that reached this interior. A PC reached only through a
function-pointer table shows the dispatcher's `ra` here, so the table's
call site is recoverable from the snapshot alone (the LOGO effect-handler
case) without a live `overlay_fp_log` window. `ext_ra == pc` means the
entry was a `jr ra` *return* from native code into an interpreted
continuation, not a call.
The array is emitted inline and truncates before the trailing bitmap
diagnostics when the response buffer fills; a partial list is still valid JSON
(the cut lands between rows). Poll periodically to accumulate coverage.
---
## Rule when the server can't answer your question
If an inspection need isn't covered by the existing commands, **do not fall back to printf or log files**. Instead:
+24
View File
@@ -224,6 +224,30 @@ typedef struct {
* below the local-flow floor every taken branch
* re-dispatches, so chain blocks dominate. entry_hits
* is the evidence stream for interior-alias seeds. */
/* Enrichment (2026-09-05, BoF3): make a bare interpreted PC explainable
* from a session-long per_pc snapshot alone, with no offline join and no
* live-ring window. Stamped only on EXTERNAL entries (arrived from native
* dispatch, addr != chain target), which is where the value is. */
uint32_t occ_crc; /* tier 1: psx_overlay_resident_crc_at(pc) at the last
* external entry -- the manifest CRC of the static
* variant whose code ranges span this PC (DLL path:
* last hash taken). Disambiguates a mixed band
* (0x801D0C00 carries BATTLE/ETC/SCENARIO/WORLD
* occupants) to the one actually loaded, which the
* offline enrich_pcs join cannot. 0 = nothing compiled
* spans this PC (BIOS / kernel / boot EXE). */
uint8_t occ_ok; /* 1 = that variant validated at the time (interior
* gap inside live native code: an Axis B seed);
* 0 = it is resident but CRC-missing (data inside the
* code range rewritten, or a different section than
* the one compiled) -- the whole band runs
* interpreted and no seed will fix it. */
uint32_t last_ext_ra;/* tier 2: gpr[31] (caller RA) at the most recent
* external entry — names the call site that reaches a
* function-pointer-table interior. This is the §9 (LOGO
* effect-handler tables) diagnosis made durable and
* session-long instead of ring-bounded; the full
* call/jalr/jr transfer split stays in the fp-log ring. */
} DirtyRamPcEntry;
extern DirtyRamPcEntry g_dirty_ram_pc_table[DIRTY_RAM_PC_TABLE_SIZE];
/* Every aligned main-RAM word is a possible instruction PC. Execution
+11 -3
View File
@@ -2906,7 +2906,11 @@ static void handle_dirty_ram_stats(int id, const char *json)
uint32_t out[5]);
(void)json;
char buf[32 * 1024];
/* 64 KiB (was 32): the per_pc array is emitted inline and each row grew by
* the occ_crc / ext_ra enrichment fields (2026-09-05). The tail reserve
* below still truncates the row list before the fixed diagnostics, so a
* larger buffer only means more per_pc rows fit before that cut. */
char buf[64 * 1024];
int n = snprintf(buf, sizeof(buf),
"{\"id\":%d,\"ok\":true,\"blocks_run\":%llu,"
"\"insns_run\":%llu,\"aborts\":%llu,"
@@ -2926,12 +2930,16 @@ static void handle_dirty_ram_stats(int id, const char *json)
if (e->pc == 0 || e->hits == 0) continue;
n += snprintf(buf + n, sizeof(buf) - n,
"%s{\"pc\":\"0x%08X\",\"hits\":%llu,\"insns\":%llu,"
"\"entries\":%llu}",
"\"entries\":%llu,\"occ_crc\":\"0x%08X\","
"\"occ_ok\":%u,\"ext_ra\":\"0x%08X\"}",
first ? "" : ",",
(unsigned)e->pc,
(unsigned long long)e->hits,
(unsigned long long)e->insns,
(unsigned long long)e->entry_hits);
(unsigned long long)e->entry_hits,
(unsigned)e->occ_crc,
(unsigned)e->occ_ok,
(unsigned)e->last_ext_ra);
first = 0;
/* Reserve enough tail room for all bitmap/guard diagnostics below. */
if (n >= (int)sizeof(buf) - 2048) break;
+13 -1
View File
@@ -2891,7 +2891,19 @@ static int dirty_ram_dispatch_inner(CPUState* cpu, uint32_t addr, uint32_t stop_
* not a new entry. Anything else arrived from native code (a call or
* a fresh dispatch) and is real interior-entry evidence for alias
* seeding. */
if (pc_entry && addr != g_dirty_interp_chain_target) pc_entry->entry_hits++;
if (pc_entry && addr != g_dirty_interp_chain_target) {
pc_entry->entry_hits++;
/* Enrichment, external entries only (this is a real native/dispatch
* arrival, not interp block chaining). occ_crc names which overlay is
* resident in this band; last_ext_ra names the caller that reached
* this interior. Both durable in the per_pc snapshot — no ring window,
* no offline join. See DirtyRamPcEntry. */
extern uint32_t psx_overlay_resident_crc_at(uint32_t phys, int *valid);
int occ_ok = 0;
pc_entry->occ_crc = psx_overlay_resident_crc_at(phys, &occ_ok);
pc_entry->occ_ok = (uint8_t)occ_ok;
pc_entry->last_ext_ra = cpu->gpr[31];
}
g_dirty_interp_chain_target = 0;
/* Block-entry ring buffer — answers "who tried to JALR into this RAM
+60
View File
@@ -504,6 +504,10 @@ static uint64_t s_diffgate_interp = 0; /* CPS interior re-entries sent to the
/* interp because their candidate is */
/* still inside the diff verify budget */
static uint32_t s_last_crc = 0;
/* psx_overlay_resident_crc_at(phys, &valid) -- the occupant fingerprint the dirty
* interpreter stamps on each interpreted PC (DirtyRamPcEntry.occ_crc) -- is
* defined with the static-match cache below; s_last_crc is its DLL-path
* fallback. */
static uint32_t s_no_manifest = 0; /* exports skipped (no manifest range)*/
static uint64_t s_cand_overflow = 0; /* registrations dropped at CAND_CAP */
static uint64_t s_pair_aliases = 0; /* validated complete pairs deduped */
@@ -565,6 +569,8 @@ typedef struct {
uint32_t expected_crc;
uint32_t gen_sum;
int matches;
uint32_t lo_min; /* span of the variant's code ranges (phys), for */
uint32_t hi_max; /* psx_overlay_resident_crc_at() */
} StaticMatchCache;
static StaticMatchCache s_static_match_cache[STATIC_MATCH_CACHE_CAP];
@@ -647,10 +653,62 @@ int psx_overlay_static_code_matches(const uint32_t *lo_len_pairs,
entry->expected_crc = expected_crc;
entry->gen_sum = gen_sum;
entry->matches = matches;
uint32_t lo_min = 0xFFFFFFFFu, hi_max = 0;
for (uint32_t i = 0; i < count; i++) {
uint32_t lo = lo_len_pairs[i * 2u] & 0x1FFFFFFFu;
uint32_t hi = lo + lo_len_pairs[i * 2u + 1u];
if (lo < lo_min) lo_min = lo;
if (hi > hi_max) hi_max = hi;
}
entry->lo_min = lo_min;
entry->hi_max = hi_max;
}
return matches;
}
/* Occupant fingerprint for an interpreted PC (tier-1 enrichment,
* DirtyRamPcEntry.occ_crc / occ_ok). Scans the static-match cache for the
* variant whose code ranges span `phys`:
* - one that matched and whose pages are unchanged since (same
* page-generation test the dispatch fast path uses) -> its manifest CRC,
* *valid = 1. An interior the static walk missed, interpreted inside a
* validating variant: the normal Axis B seed.
* - otherwise the spanning variant most recently consulted -> its manifest
* CRC, *valid = 0. "Compiled for this band, resident, but NOT validating"
* -- a CRC-miss occupant (data inside the code range rewritten at run
* time, or a section that differs from the one compiled). This is the
* case a plain 0 would hide, and it is the one that explains a band that
* is compiled yet fully interpreted (SCENA16 at the title screen,
* 2026-09-05).
* - no spanning variant at all -> 0 / *valid = 0 (BIOS, kernel, boot EXE,
* or a band nothing was compiled for); DLL-path titles get the last
* residency hash as a hint instead.
* The CRC is the one the variant was compiled from, so it maps straight back
* to a capture / .EMI section offline. Called only on EXTERNAL interp
* entries, so a 4096-slot scan is fine. */
uint32_t psx_overlay_resident_crc_at(uint32_t phys, int *valid) {
phys &= 0x1FFFFFFFu;
uint32_t stale = 0;
for (uint32_t i = 0; i < STATIC_MATCH_CACHE_CAP; i++) {
const StaticMatchCache *e = &s_static_match_cache[i];
if (!e->ranges || phys < e->lo_min || phys >= e->hi_max)
continue;
if (e->matches) {
uint32_t gen_sum = 0;
for (uint32_t k = 0; k < e->count; k++)
gen_sum += overlay_watch_pagegen_sum(e->ranges[k * 2u] & 0x1FFFFFFFu,
e->ranges[k * 2u + 1u]);
if (gen_sum == e->gen_sum) {
if (valid) *valid = 1;
return e->expected_crc;
}
}
if (!stale) stale = e->expected_crc;
}
if (valid) *valid = 0;
return stale ? stale : s_last_crc;
}
void overlay_loader_static_match_stats(uint64_t *rehashes,
uint64_t *crc_misses,
uint64_t *gen_fastpath) {
@@ -658,6 +716,8 @@ void overlay_loader_static_match_stats(uint64_t *rehashes,
if (crc_misses) *crc_misses = s_static_match_crc_misses;
if (gen_fastpath) *gen_fastpath = s_static_match_gen_fastpath;
}
#else
uint32_t psx_overlay_resident_crc_at(uint32_t phys, int *valid) { (void)phys; if (valid) *valid = 0; return s_last_crc; }
#endif
/* ---- Per-DLL code-range manifest --------------------------------------- */