From 4a3cf34f845e1865b2c1e663b2369ddbc490f5e6 Mon Sep 17 00:00:00 2001 From: blasty Date: Thu, 23 Jul 2026 22:01:21 +0200 Subject: fix: follow/double-click a label lands on the label, not the function entry resolve(name) went through lookup_funcs, which for a mid-function label (loc_/locret_) does get_name_ea -> label ea, then get_function(ea) and reports the CONTAINING function's entry address. So double-clicking (or following) a label jumped to the top of the function instead of the label's own address. Add a server tool resolve_names that returns the address a name actually denotes via idaapi.get_name_ea (functions, labels and data alike), and route Program.resolve() through it, keeping lookup_funcs only as a fallback for the "did you mean ..." suggestion on an unknown name. Verified: resolve('loc_2040') -> 0x2040 (was the function entry); double-click follow on a label row lands on the label ea. Regression sweep follow_xrefs/xref_labels/rename/rename_history/decomp_follow_self/search/ listing_view/disasm_nav/mouse 50/0. Needs a supervisor restart (new tool). --- idatui/domain.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'idatui') diff --git a/idatui/domain.py b/idatui/domain.py index e8e2996..2a3fc2b 100644 --- a/idatui/domain.py +++ b/idatui/domain.py @@ -1274,8 +1274,20 @@ class Program: return int(s, 16) if re.fullmatch(r"[0-9a-fA-F]+", s): return int(s, 16) - # Symbol name -> ask the server. lookup_funcs takes an array of strings - # and returns [{"query":..., "fn": {addr,name,size} | null, "error":...}]. + # Symbol name -> resolve to the address the NAME denotes (get_name_ea via + # resolve_names). This handles functions, data AND mid-function labels + # (loc_/locret_): lookup_funcs would map a label to its *containing* + # function's entry, so double-clicking a label jumped to the wrong place. + try: + payload = self.client.call("resolve_names", queries=[s]) + res = payload.get("result", []) if isinstance(payload, dict) else [] + ea = res[0].get("ea") if res and isinstance(res[0], dict) else None + if ea: + return _as_int(ea) + except IDAToolError: + pass # older server without resolve_names -> fall back below + # Fall back to function-name resolution (also drives the 'did you mean' + # suggestion when the name is unknown). try: payload = self.client.call("lookup_funcs", queries=[s]) except IDAToolError as e: -- cgit v1.3.1-sl0p