diff options
| author | blasty <blasty@local> | 2026-07-09 15:06:31 +0200 |
|---|---|---|
| committer | blasty <blasty@local> | 2026-07-09 15:06:31 +0200 |
| commit | 01fc7da4f3198f922cd4859b8cefb93119f70a9a (patch) | |
| tree | 52c4da82b1337f0b7ff7957738c8e449164645ca | |
| parent | rename symbol under cursor ('n') + save ('Ctrl+S') (diff) | |
| download | ida-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.py | 12 | ||||
| -rw-r--r-- | tests/test_tui.py | 22 |
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 |
