64kramsystem / 64kramsystem/ghidra-vice-connector
Tracepoints: non-stopping checkpoints for call graph mapping
- 主要言語
- Python
- スター
- 1
- フォーク
- 0
- PR マージ指標
- 30日以内にマージされた PR はありません
説明
## Summary
Add the ability to set tracepoints — checkpoints that log execution without pausing — so the game can run freely while address hits are collected. This lets you map which subroutines are called, how often, and in what order during a gameplay session without interactive stepping.
Source: IceBroLite tracepoint view; VICE BMP already supports `stop_on_hit=False` on checkpoints.
---
## How VICE supports this
`checkpoint_set()` in `util.py:480` already accepts `stop_on_hit: bool`. Setting it to `False` creates a tracepoint. VICE fires `RESP_CHECKPOINT_INFO` (0x11) events (with `currently_hit=True`) each time the tracepoint is hit, without stopping execution.
The missing piece is:
1. A `RESP_CHECKPOINT_INFO` **event** handler (currently only `RESP_STOPPED` and `RESP_RESUMED` are handled in `hooks.py`)
2. Ghidra methods to set/clear tracepoints and display the log
---
## Implementation plan
### 1. `util.py` — event handler for checkpoint hits
In `ViceBmpClient.connect()` (`util.py:159`), register a handler for `RESP_CHECKPOINT_INFO` (0x11) as an event:
```python
self.on_event(RESP_CHECKPOINT_INFO, self._on_checkpoint_hit)
```
```python
def _on_checkpoint_hit(self, resp_type, error, body):
cp = _parse_checkpoint_info(body) # util.py:98 — already parses all fields
if cp['currently_hit'] and not cp['stop_on_hit']:
self._tracepoint_hits.append({
'number': cp['number'],
'address': cp['start'],
'hit_count': cp['hit_count'],
})
```
`_tracepoint_hits` is a list (or `collections.deque(maxlen=10000)`) initialized in `__init__`.
### 2. `methods.py` — new methods
```python
@REGISTRY.method(display='Set Tracepoint')
def set_tracepoint(process: C64, address: Address):
"""Set a non-stopping execution tracepoint."""
vice = commands.STATE.require_vice()
vice.checkpoint_set(address.offset, address.offset,
stop_on_hit=False, cpu_op=CPU_OP_EXEC)
with commands.open_tracked_tx('Add tracepoint'):
commands.put_breakpoints()
@REGISTRY.method(display='Dump Tracepoint Log')
def dump_tracepoint_log(process: C64):
"""Print accumulated tracepoint hits to the Ghidra console."""
hits = commands.STATE.require_vice()._tracepoint_hits
for h in hits:
log.info(f" TP#{h['number']} addr=0x{h['address']:04X} hits={h['hit_count']}")
log.info(f"Total: {len(hits)} events")
@REGISTRY.method(display='Clear Tracepoint Log')
def clear_tracepoint_log(process: C64):
commands.STATE.require_vice()._tracepoint_hits.clear()
```
### 3. Schema / breakpoint display
Tracepoints and breakpoints both use VICE checkpoints. The existing `put_breakpoints()` (`commands.py:328`) and `ViceBreakpoint` schema already capture `stop_on_hit` implicitly via the `_kinds` display string. Consider adding a `_display` suffix `"[TRACE]"` vs `"[BREAK]"` to distinguish them in the Ghidra breakpoint panel.
---
## Files to change
- `src/main/py/src/vice/util.py` — `__init__`: add `_tracepoint_hits`; `connect()`: register `RESP_CHECKPOINT_INFO` event; add `_on_checkpoint_hit()`
- `src/main/py/src/vice/methods.py` — add `set_tracepoint`, `dump_tracepoint_log`, `clear_tracepoint_log`
- `src/main/py/src/vice/commands.py` — optionally update `put_breakpoints()` display to distinguish trace vs break
コントリビューションガイド
このリポジトリのコントリビューションガイドは索引されていません
評価
この issue はまだ評価されていません。