diff options
| author | blasty <blasty@local> | 2026-08-06 22:12:56 +0200 |
|---|---|---|
| committer | blasty <blasty@local> | 2026-08-06 22:12:56 +0200 |
| commit | 6f9cf89c0804eba19fb2d87469d2d2ab28f8049b (patch) | |
| tree | bb3bb136ff5847765128f79b655420322b3f0efd /idatui/rpc.py | |
| parent | tests: one front door (diff) | |
| download | ida-tui-6f9cf89c0804eba19fb2d87469d2d2ab28f8049b.tar.gz ida-tui-6f9cf89c0804eba19fb2d87469d2d2ab28f8049b.tar.xz ida-tui-6f9cf89c0804eba19fb2d87469d2d2ab28f8049b.zip | |
app: lift trace navigation out of IdaTui
First cut at the 4000-line class. Trace is the cleanest seam: 348 contiguous
lines, one coherent job (where we are in time and everything that moves us),
and two suites already covering it.
TraceController owns the state now -- the trace, the timestamp, the trail maps.
IdaTui keeps the keys, because Textual only merges BINDINGS from DOMNode
subclasses and a mixin's would be silently dropped, and it keeps the @work entry
points, because the worker machinery wants a DOMNode host. Both are one-line
delegates.
_trace/_t/_trail_map/_trail_map_ea/_trail_line_of stay readable on the app as
properties: the pilot suite and rpc.py read the position by those names, and a
property means one owner rather than a copy that can drift. rpc.py itself now
goes through the controller.
The parallel line-map that _apply_split_map used to poke into five attributes is
now one adopt_map() call -- same single shared index, but the sharing is stated
rather than implied by two places assigning the same fields.
731 checks, unchanged.
Diffstat (limited to 'idatui/rpc.py')
| -rw-r--r-- | idatui/rpc.py | 17 |
1 files changed, 9 insertions, 8 deletions
diff --git a/idatui/rpc.py b/idatui/rpc.py index 43a34b7..90cfd3c 100644 --- a/idatui/rpc.py +++ b/idatui/rpc.py @@ -890,9 +890,10 @@ class RpcServer: # -- projects ------------------------------------------------------ # if method == "trace": - if app._trace is None: + tc = app.trace_ctl + if tc.trace is None: raise ValueError("no trace loaded (launch with --trace FILE)") - t = app._trace + t = tc.trace if "seek" in params: v = params["seek"] # "!50" seeks a percentage, like Tenet's timestamp shell. @@ -900,7 +901,7 @@ class RpcServer: idx = int(float(v[1:]) * (t.length - 1) / 100.0) else: idx = int(str(v).replace(",", ""), 0) if isinstance(v, str) else int(v) - app._seek(idx) + tc.seek(idx) elif "goto" in params: # first execution of an address/name tgt = params["goto"] ea = (int(str(tgt), 0) if str(tgt).lower().startswith("0x") @@ -908,17 +909,17 @@ class RpcServer: first = t.first_execution(ea) if first is None: raise ValueError(f"{tgt} never executed in this trace") - app._seek(first) + tc.seek(first) elif "step" in params: n = int(params.get("step") or 1) over = bool(params.get("over")) for _ in range(abs(n)): - (app._step_over if over else app._step)(1 if n > 0 else -1) + (tc.step_over if over else tc.step)(1 if n > 0 else -1) await settle(app, timeout=float(params.get("timeout", 20.0))) snap = snapshot(app) - snap["trace"] = {"idx": app._t, "length": t.length, - "pc": hex(t.ip(app._t)), - "changed": sorted(t.changed(app._t))} + snap["trace"] = {"idx": tc.t, "length": t.length, + "pc": hex(t.ip(tc.t)), + "changed": sorted(t.changed(tc.t))} return snap if method == "binaries": |
