aboutsummaryrefslogtreecommitdiffstats
path: root/idatui/domain.py
diff options
context:
space:
mode:
Diffstat (limited to 'idatui/domain.py')
-rw-r--r--idatui/domain.py22
1 files changed, 22 insertions, 0 deletions
diff --git a/idatui/domain.py b/idatui/domain.py
index 8a127d7..1bf62ed 100644
--- a/idatui/domain.py
+++ b/idatui/domain.py
@@ -807,6 +807,7 @@ class Program:
self._disasm: dict[int, DisasmModel] = {}
self._listings: dict[int, ListingModel] = {} # keyed by segment start
self._decomp: dict[int, tuple[Decompilation, int]] = {}
+ self._decomp_maps: dict[int, tuple[list[list[int]], int]] = {} # line->ea sets
self._name_gen = 0 # bumped on rename; invalidates stale name caches
self._segments_cache: list[tuple[int, int, int, str]] | None = None
self._sections: list[tuple[int, int, str]] | None = None
@@ -1245,6 +1246,27 @@ class Program:
except Exception: # noqa: BLE001 -- fall back to the truncated preview
return None
+ def decomp_map(self, ea: int) -> list[list[int]]:
+ """Per-pseudocode-line instruction coverage for the split-view region
+ highlight: a list aligned to the decompiled lines, each the EAs the
+ decompiler attributes to that line (may be empty). Cached per function +
+ name generation; ``[]`` if the tool is unavailable."""
+ with self._lock:
+ hit = self._decomp_maps.get(ea)
+ gen = self._name_gen
+ if hit is not None and hit[1] == gen:
+ return hit[0]
+ try:
+ payload = self.client.call("decomp_map", addr=hex(ea))
+ except IDAToolError:
+ return []
+ lines = payload.get("lines", []) if isinstance(payload, dict) else []
+ out = [[_as_int(e) for e in (ln.get("eas") or [])]
+ for ln in lines if isinstance(ln, dict)]
+ with self._lock:
+ self._decomp_maps[ea] = (out, gen)
+ return out
+
# -- cross-references & containing function --------------------------- #
def function_of(self, ea: int) -> Func | None:
"""Return the function containing ``ea`` (resolves mid-function addrs)."""