summaryrefslogtreecommitdiffstats
path: root/idatui/rpc.py
diff options
context:
space:
mode:
authorblasty <blasty@local>2026-08-06 22:12:56 +0200
committerblasty <blasty@local>2026-08-06 22:12:56 +0200
commit6f9cf89c0804eba19fb2d87469d2d2ab28f8049b (patch)
treebb3bb136ff5847765128f79b655420322b3f0efd /idatui/rpc.py
parenttests: one front door (diff)
downloadida-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.py17
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":