From a9546714a18fea954bea2ee12817247697b10d09 Mon Sep 17 00:00:00 2001 From: blasty Date: Thu, 9 Jul 2026 20:07:26 +0200 Subject: fix: disasm follow stepped to the next line on a call (fall-through edge) xrefs_from on a call/branch returns the ordinary fall-through edge (target == the next instruction) as an indistinguishable type=code xref, and _follow_disasm picked the first code edge -> 'follow' just advanced one line instead of entering the callee (e.g. Enter on 'call cs:memset_ptr' stayed in the same function). Plumb the next instruction's ea from the view and drop the edge whose target is that next instruction, so follow lands on the real call/jump target. Mirrors the ordinary-flow fix already applied to the xrefs path (e6375de). --- idatui/app.py | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/idatui/app.py b/idatui/app.py index 76f9943..234cfc8 100644 --- a/idatui/app.py +++ b/idatui/app.py @@ -1288,8 +1288,12 @@ class IdaTui(App): word = view.word_under_cursor() if isinstance(view, DisasmView): ea = view._cursor_ea() + # The instruction's ordinary fall-through edge (to the next line) is + # an indistinguishable 'code' xref; pass it so follow can skip it and + # land on a call/jump's real target instead of the next instruction. + nxt = view.model.cached_line(view.cursor + 1) if view.model else None if ea is not None: - self._follow_disasm(ea, word) + self._follow_disasm(ea, word, nxt.ea if nxt else None) elif isinstance(view, DecompView) and view._texts: self._follow_decomp(view._texts[view.cursor], word) @@ -1312,7 +1316,8 @@ class IdaTui(App): return not all(c in "0123456789abcdefABCDEF" for c in word) @work(thread=True, group="nav") - def _follow_disasm(self, ea: int, word: str | None) -> None: + def _follow_disasm(self, ea: int, word: str | None, + next_ea: int | None = None) -> None: assert self.program is not None # Prefer the symbol under the cursor (handles multiple refs on a line). if self._looks_like_symbol(word): @@ -1322,8 +1327,12 @@ class IdaTui(App): except Exception: # noqa: BLE001 -- not a resolvable name; fall back pass xr = self.program.xrefs_from(ea) - tgt = next((x for x in xr if x.type == "code" and x.to), None) - tgt = tgt or next((x for x in xr if x.to), None) + # Drop the ordinary fall-through edge (its target is the next + # instruction): on a call/branch it would otherwise be picked before the + # real target and 'follow' would just step to the next line. + cand = [x for x in xr if x.to and x.to != next_ea] + tgt = next((x for x in cand if x.type == "code"), None) + tgt = tgt or next((x for x in cand), None) if tgt is None or tgt.to is None: self.app.call_from_thread(self._status, "nothing to follow here") return -- cgit v1.3.1-sl0p