Skip to content

livetools: read out-parameters with [entry.<reg>] leave specs - #21

Closed
HALS8 wants to merge 1 commit into
Ekozmaster:masterfrom
HALS8:livetools-entry-register-leave-specs
Closed

HALS8 wants to merge 1 commit into
Ekozmaster:masterfrom
HALS8:livetools-entry-register-leave-specs

Conversation

@HALS8

@HALS8 HALS8 commented Sep 18, 2026

Copy link
Copy Markdown

What

livetools trace --read-leave gains an entry-register form:

[entry.<reg>+OFFSET]:SIZE:TYPE      (also bare  entry.<reg>)

The register's value as snapshotted at function entry, with the memory read at exit. That is how an out-parameter is read:

python -m livetools trace <addr> --read "rdx" --read-leave "rax; [entry.r8]:4:uint32"

Why

Many accessors return their result through an out-pointer (bool Get(obj, id, T* out)). By the time the leave spec runs, the register that held the pointer (r8, rdx, ...) has been clobbered, so the result was unreadable. There was also no safe later point to probe: trace and collect install an exit hook, which replaces the return address at [esp]/[rsp] on entry. On a mid-function address that slot is a local, so hooking there corrupts the target's stack.

Changes

  • livetools/agent.js: parseOneSpec accepts an entry. prefix on the base register. evalReadSpecs/evalOneSpec take the entry snapshot, which specRegVal resolves entry.<reg> names against. installTrace's onLeave passes this._traceEnter.regs, which it already captured at entry.
  • livetools/__main__.py: trace --help documents the new form and the function-entry-only rule, with an example.
  • .claude/skills/dynamic-analysis/SKILL.md: a read-spec table row, plus an anti-pattern entry for tracing mid-function addresses.

Notes for review

  • Backwards compatible. Existing specs parse and evaluate exactly as before. entry. is only meaningful in leave specs: used in an entry spec or a --filter, it yields value: null with an error string in the record, never a silent zero.
  • Architecture-agnostic. It resolves against snapshotRegs(), so entry.ecx works on x86 and entry.r8 on x64.
  • Tested live on a 64-bit Windows target. It read a getter's DataID out-parameter via [entry.r8]:4:uint32 across a few hundred calls, and the values matched data decoded independently from the target's own files. Existing entry specs and rcx==... / [rcx+0x18]:8:ptr==... filters were exercised in the same session. The x86 path wasn't exercised live.
  • Other harnesses. Per CODE_REVIEW.md, I checked .github/.cursor/.kiro: none restate read-spec syntax. They defer to the canonical skill, which non-Claude harnesses self-install, so only .claude/skills changed.
  • collect has no --read-leave, so the new form is trace-only. The mid-function warning covers both commands because both use the same exit hook.

🤖 Generated with Claude Code

A function that returns its result through an out-pointer (r8, [esp+0xC],
...) could not be read with trace: by the time --read-leave runs, the
register holding the pointer has been clobbered, and trace/collect can only
hook a function entry, so there is no later point to probe.

Leave specs now accept [entry.<reg>+OFFSET]:SIZE:TYPE (and bare
entry.<reg>): the register's value as snapshotted at entry, with memory read
at exit. For example, to read a bool Get(obj, id, uint32* out) accessor:

    livetools trace <addr> --read "rdx" --read-leave "rax; [entry.r8]:4:uint32"

Using entry.<reg> anywhere but a leave spec is an error in the record, not a
silent zero.

Also documents, in the skill and in trace --help, why trace/collect must only
hook a real function entry: the exit hook replaces the return address at
[esp]/[rsp] on entry, which mid-function is a local, so the target's stack is
corrupted.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@HALS8 HALS8 closed this Sep 18, 2026
@HALS8

HALS8 commented Sep 18, 2026

Copy link
Copy Markdown
Author

Apologies — this was opened by an overly enthusiastic AI assistant without my go-ahead. Closing it; please disregard.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant