v0.7: event-listener system (addEventListener/step/breakpoint/signal/exit)
- Native step/cont moved to __step_native/__cont_native; public step()/cont()
defined in prelude.js wrap them and dispatch JS listeners on each stop.
- addEventListener/removeEventListener/clearListeners/listeners() registry on
globalThis, persistent for the daemon lifetime (independent of ctx.reset()).
- Event object carries {state, prev, stop_reason} plus breakpoint_id/signal/
exit_code as appropriate. Implements the SPEC 'Event Listeners' + 'Core Loop'.
- No-listener fast path keeps existing scripts zero-cost.
- examples/smarm_ctx_switch.js: worked session inspecting smarm's naked-asm
context switch; README updated (status table, listener API, deferred list).
This commit is contained in:
@@ -20,6 +20,7 @@ each step" is the natural interface. The full motivation is in `SPEC.md`.
|
||||
| v0.4 | INT3 software breakpoints with by-name/by-id ops; auto disarm-step-rearm; RIP rewind on hit |
|
||||
| v0.5 | x86-64 disassembly via `iced-x86`; `read_mem_pristine()` overlays original bytes through active INT3s; branch targets get symbolised |
|
||||
| v0.6 | `state.stack`; `until(loc)`; `finish()`; `show.{disasm,bp,regs}` prelude helpers |
|
||||
| v0.7 | Event-listener system: `addEventListener('step'\|'breakpoint'\|'signal'\|'exit', ...)`, `removeEventListener`, `clearListeners`, `listeners()`; `step`/`cont` fire listeners per stop with `{state, prev, stop_reason, ...}` events; native steppers moved to `__step_native`/`__cont_native` |
|
||||
|
||||
Each `vN` corresponds to one git commit. See `git log --oneline`.
|
||||
|
||||
@@ -27,17 +28,20 @@ Each `vN` corresponds to one git commit. See `git log --oneline`.
|
||||
|
||||
The spec calls for these; they're deliberately deferred:
|
||||
|
||||
- Event listener system (`addEventListener('step', ...)` etc.) — current model
|
||||
is synchronous send-script-get-output; events come next.
|
||||
- `attach(pid)` — only `spawn` works today.
|
||||
- Hardware watchpoints.
|
||||
- Hardware watchpoints. (The `watchpoint` event type exists in the listener
|
||||
registry but never fires until hardware watchpoints land.)
|
||||
- Source-level debugging via DWARF (`gimli`).
|
||||
- Multi-threaded targets; shared-library symbol resolution.
|
||||
- Browser visualisation / DOM API.
|
||||
- Conditional breakpoints.
|
||||
- Conditional breakpoints. (Now trivial to express as a guard inside a
|
||||
`breakpoint` listener, but native `--condition` support is still deferred.)
|
||||
- The `--summary` mode for batch stepping.
|
||||
- Reverse execution.
|
||||
|
||||
The event-listener system (`addEventListener('step', ...)` etc.) landed in
|
||||
v0.7 — see the status table.
|
||||
|
||||
The complete "what not yet" list is in `SPEC.md`.
|
||||
|
||||
## Build
|
||||
@@ -174,8 +178,34 @@ finish() // until([rbp+8]) — assumes frame pointer
|
||||
show.disasm(n=8, [at])
|
||||
show.bp()
|
||||
show.regs([keys])
|
||||
|
||||
// Event listeners (v0.7). Handlers fire on each stop during step()/cont().
|
||||
addEventListener(type, handler) // type: 'step'|'breakpoint'|'signal'|'exit'
|
||||
removeEventListener(type, handler)
|
||||
clearListeners([type]) // drop one type, or all if omitted
|
||||
listeners() // -> { step: n, breakpoint: n, ... } counts
|
||||
```
|
||||
|
||||
### Event listeners
|
||||
|
||||
The event object passed to each handler:
|
||||
|
||||
```js
|
||||
e.state // live state (re-reads via ptrace), same as the `state` global
|
||||
e.prev // pre-resume snapshot, or null on the very first event
|
||||
e.stop_reason // "step" | "breakpoint:N" | "signal:SIGSEGV" | "exited:0" | ...
|
||||
e.breakpoint_id // number — only on 'breakpoint' events
|
||||
e.signal // string — only on 'signal' events
|
||||
e.exit_code // number — only on 'exit' events
|
||||
```
|
||||
|
||||
`step(n)` single-steps one instruction at a time, firing listeners after each
|
||||
stop; `cont()` fires after the stop it lands on. When no listeners are
|
||||
registered, both take the native fast path and pay nothing. Handler exceptions
|
||||
are caught and printed, so one bad listener won't abort a long step loop.
|
||||
A worked example against smarm's context switch is in
|
||||
`examples/smarm_ctx_switch.js`.
|
||||
|
||||
## Architecture
|
||||
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user