64kramsystem / 64kramsystem/ghidra-vice-connector

Memory access heatmap: runtime code-vs-data classification

Abierto
#18 0 comentarios 0 reacciones 0 asignados Ver en GitHub
priority: high
Lenguaje dominante
Python
Estrellas
1
Forks
0
Métricas de merge de PR
Sin PR fusionados en 30 d

Descripción

## Summary

The fundamental challenge in C64 game disassembly is distinguishing code from data in a flat 64KB address space (sprite frames, music data, lookup tables, level maps all live alongside executable code). Using VICE tracepoints (non-stopping checkpoints) to record which addresses are executed vs. read as data vs. written, then annotating the Ghidra listing accordingly, can solve this automatically at runtime.

Inspired by RetroDebugger's memory access layers and IceBroLite's memory visualization.

---

## How VICE supports this

Checkpoints with `stop_on_hit=False` fire without pausing execution. VICE still sends `RESP_CHECKPOINT_INFO` (0x11) events when these tracepoints are hit — with `currently_hit=True` and the `cpu_op` flag (EXEC/LOAD/STORE) identifying the access type.

`checkpoint_set()` in `util.py:480` already accepts `stop_on_hit` — it just needs to be `False`. The event handler in `hooks.py` currently only handles `RESP_STOPPED` (0x62) and `RESP_RESUMED` (0x63); a handler for `RESP_CHECKPOINT_INFO` (0x11) needs to be registered.

---

## Implementation plan

### Phase 1 — Collect access data

1. **`util.py`**: Register a `RESP_CHECKPOINT_INFO` (0x11) event handler in `ViceBmpClient` that accumulates `(address, cpu_op)` hits into a dict without blocking. The address is already in the checkpoint info struct at `start` field (`util.py:98-116`).

2. **`methods.py`**: Add three new remote methods:
- `start_heatmap(process: C64, start: Address, end: Address)` — calls `checkpoint_set()` three times (EXEC, LOAD, STORE) with `stop_on_hit=False` over the given range.
- `stop_heatmap(process: C64)` — deletes the heatmap checkpoints.
- `apply_heatmap(process: C64)` — applies collected data to the program (Phase 2).

### Phase 2 — Annotate the Ghidra listing

`apply_heatmap()` iterates the accumulated access dict and for each address:
- EXEC hits → set Ghidra bookmark type `"Code"` (or call `trace.disassemble()` at those addresses)
- LOAD-only (never EXEC) → set bookmark type `"Data"`, add plate comment `"Read as data (heatmap)"`
- STORE hits → add plate comment `"Written at runtime"`

Bookmarks are written via the trace: `trace.proxy_object_path(...).set_value(...)` or via a post-analysis Ghidra script that reads from a persisted set.

### Alternative: CPU History bulk approach

If tracepoints prove too noisy (too many RESP_CHECKPOINT_INFO events flooding the socket), use `CMD_CPU_HISTORY` (0x86) on each stop instead: retrieve the last N instructions, extract their PCs, and accumulate them. This gives executed addresses only, not data reads.

---

## BMP commands involved

| Command | Hex | Already in util.py? |
|---------|-----|-------------------|
| `CMD_CHECKPOINT_SET` | 0x12 | Yes (`util.py:480`) |
| `CMD_CHECKPOINT_DELETE` | 0x13 | Yes (`util.py:512`) |
| `RESP_CHECKPOINT_INFO` event | 0x11 | Not handled as event |

---

## Files to change

- `src/main/py/src/vice/util.py` — add `RESP_CHECKPOINT_INFO` event handling
- `src/main/py/src/vice/methods.py` — add `start_heatmap`, `stop_heatmap`, `apply_heatmap` methods
- `src/main/py/src/vice/commands.py` — add accumulated access state and annotation logic

Guía de contribución

No hay ninguna guía de contribución indexada para este repositorio

Evaluación

Este issue todavía no se ha evaluado.

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.