aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorblasty <blasty@local>2026-07-09 15:06:31 +0200
committerblasty <blasty@local>2026-07-09 15:06:31 +0200
commit01fc7da4f3198f922cd4859b8cefb93119f70a9a (patch)
tree52c4da82b1337f0b7ff7957738c8e449164645ca
parentrename symbol under cursor ('n') + save ('Ctrl+S') (diff)
downloadida-tui-01fc7da4f3198f922cd4859b8cefb93119f70a9a.tar.gz
ida-tui-01fc7da4f3198f922cd4859b8cefb93119f70a9a.tar.xz
ida-tui-01fc7da4f3198f922cd4859b8cefb93119f70a9a.zip
fix: decompiler follow/xrefs of a name not listed in refs
_follow_decomp / _xrefs_decomp only matched the pseudocode ref list, so a function name under the cursor that wasn't in refs (self-reference, or refs truncated on big functions) did nothing — while disasm worked because it also resolves the symbol. Both decomp paths now fall back to program.resolve(word) like disasm does. pilot suite 45/45.
-rw-r--r--idatui/app.py12
-rw-r--r--tests/test_tui.py22
2 files changed, 34 insertions, 0 deletions
diff --git a/idatui/app.py b/idatui/app.py
index 45a5c82..b030e69 100644
--- a/idatui/app.py
+++ b/idatui/app.py
@@ -1256,6 +1256,13 @@ class IdaTui(App):
addr = None
if word: # the ref whose name is exactly the token under the cursor
addr = next((r.addr for r in dec.refs if r.name == word), None)
+ # A named function under the cursor may not be listed in refs
+ # (e.g. self-reference, or refs truncated) — resolve it directly.
+ if addr is None and self._looks_like_symbol(word):
+ try:
+ addr = self.program.resolve(word)
+ except Exception: # noqa: BLE001
+ addr = None
if addr is None:
addr = self._ref_on_line(line)
if addr is None:
@@ -1294,6 +1301,11 @@ class IdaTui(App):
if self._cur is not None and word:
dec = self.program.decompile(self._cur.ea)
subj = next((r.addr for r in dec.refs if r.name == word), None)
+ if subj is None and self._looks_like_symbol(word):
+ try:
+ subj = self.program.resolve(word)
+ except Exception: # noqa: BLE001
+ subj = None
if subj is None:
subj = self._ref_on_line(line) or (self._cur.ea if self._cur else None)
if subj is not None:
diff --git a/tests/test_tui.py b/tests/test_tui.py
index 422476a..eee33e5 100644
--- a/tests/test_tui.py
+++ b/tests/test_tui.py
@@ -445,6 +445,28 @@ async def run(db):
check("rename reverted cleanly",
rr.get("summary", {}).get("ok", 0) == 1, str(rr.get("summary")))
+ # Decompiler follow of a name NOT in refs (the function's own name).
+ await pilot.press("g")
+ await pilot.pause(0.2)
+ for ch in fn.name:
+ await pilot.press(ch)
+ await pilot.press("enter")
+ await wait_until(pilot, lambda: dis.total > 0, timeout=20)
+ if app._active != "decomp":
+ await pilot.press("tab")
+ await wait_until(pilot, lambda: dec.loaded_ea == fn.addr, timeout=20)
+ nx = dec._texts[0].find(fn.name) if dec._texts else -1
+ if nx >= 0:
+ dec.focus()
+ dec.cursor, dec.cursor_x = 0, nx + 1
+ dec.refresh()
+ await pilot.pause(0.1)
+ depth = len(app._nav)
+ await pilot.press("enter")
+ moved = await wait_until(pilot, lambda: len(app._nav) > depth, timeout=25)
+ check("decompiler follows a name not in refs (resolve fallback)",
+ moved and app._cur.ea == fn.addr, f"moved={moved}")
+
def main(argv):
db = None