aboutsummaryrefslogtreecommitdiffstats
path: root/tests
diff options
context:
space:
mode:
authorblasty <blasty@local>2026-07-30 13:37:46 +0200
committerblasty <blasty@local>2026-07-30 13:37:46 +0200
commit214076f2e87e69e50600f75723af09d21dcc9ffc (patch)
tree27a3f70b3e7f8be759f25c40a591eb65acf91a39 /tests
parenttrace: seek verbs — next/previous execution, and who set this register (diff)
downloadida-tui-214076f2e87e69e50600f75723af09d21dcc9ffc.tar.gz
ida-tui-214076f2e87e69e50600f75723af09d21dcc9ffc.tar.xz
ida-tui-214076f2e87e69e50600f75723af09d21dcc9ffc.zip
trace: a stale navigation no longer drags the view backHEADmain
Fixes the bug found while building M3. Navigations run in workers and are applied when they land; the trace's OPENING seek goes to t=0, which for a normal binary is _start, and that navigation is slow. It arrived after later seeks and won, leaving the cursor and _cur on _start while the trace's pc was elsewhere — and it never settled, measured stable for 3+ seconds. Anything cursor-based done just after a seek (`>` asks about the address under the cursor) then acted on the wrong address. The decompiler path has had a staleness guard since 756589a; the listing path never got one. It has one now (_open_at_if_current), and a seek bumps _nav_seq so older in-flight navigations are dropped. Verified both directions on the exact reproduction: seek to the first execution of a repeated instruction, seek to the second, wait — cursor stays put with the guard, and with the guard removed it drifts to 0x34d0 (_start) exactly as reported. Scope, deliberately narrow. I first bumped _nav_seq in _goto_ea for EVERY navigation, which is the more general rule, and a full run then failed follow_xrefs — a follow can be dropped by whatever navigates next. That check has flaked before so it is not proof, but the mechanism is real and my evidence is only about seeks, so the bump lives in _seek. TODO records what would justify the general version and what test it needs. tests: +1 trace UI (39) — seek, seek again, wait 3s, and the cursor is still on the instruction the trace is at. Two consecutive full runs 212/0 after narrowing.
Diffstat (limited to 'tests')
-rw-r--r--tests/test_trace_ui.py21
1 files changed, 21 insertions, 0 deletions
diff --git a/tests/test_trace_ui.py b/tests/test_trace_ui.py
index b08ca02..32977ad 100644
--- a/tests/test_trace_ui.py
+++ b/tests/test_trace_ui.py
@@ -286,6 +286,27 @@ async def run() -> int:
mapped > 3 and missed == 0,
f"{mapped} mapped, {missed} not followed")
+ # -- a late navigation must not drag the view back --------------- #
+ # Navigations run in workers and finish out of order. The trace's
+ # OPENING seek goes to the entry point (t=0 is _start), takes a
+ # while, and used to arrive after later seeks — leaving the cursor
+ # on _start while the trace was elsewhere, and it never settled.
+ # Anything cursor-based done right after a seek then acted on the
+ # wrong address.
+ two = [a for a in t.by_ip if len(t.by_ip[a]) > 1]
+ if two:
+ a = max(two, key=lambda x: len(t.by_ip[x]))
+ s0, s1 = list(t.by_ip[a])[:2]
+ dbaddr = a + t.slide
+ app._seek(s0)
+ await wait(lambda: lst._cursor_ea() == dbaddr, pilot, 60)
+ app._seek(s1)
+ await pilot.pause(3.0) # long enough for a stale one to land
+ check("a stale navigation doesn't drag the cursor away",
+ lst._cursor_ea() == dbaddr and app._cur.ea == dbaddr,
+ f"cursor={lst._cursor_ea():#x} cur={app._cur.ea:#x} "
+ f"want {dbaddr:#x}")
+
# -- seeking, as opposed to stepping ---------------------------- #
# "When else did this instruction run?" — the question that makes a
# trace more than a very long single-step log.