summaryrefslogtreecommitdiffstats
path: root/idatui/domain.py
diff options
context:
space:
mode:
authorblasty <peter@haxx.in>2026-07-10 13:30:48 +0200
committerblasty <peter@haxx.in>2026-07-10 13:30:48 +0200
commit7eab44b3dbdccb8434e658a0ab5f3bebe14d2935 (patch)
tree40278c66ac828e7073b74d9d0728c1473293779d /idatui/domain.py
parentstruct editor: auto-format the definition on save (diff)
downloadida-tui-7eab44b3dbdccb8434e658a0ab5f3bebe14d2935.tar.gz
ida-tui-7eab44b3dbdccb8434e658a0ab5f3bebe14d2935.tar.xz
ida-tui-7eab44b3dbdccb8434e658a0ab5f3bebe14d2935.zip
retype: set variable/function types with 'y' (IDA-style), via structured tools
Instead of parsing pseudocode text, add structured server tools (server/ patch_server.py, alongside del_type): - func_types(addr): prototype + local variables (name/type/is_arg) - set_lvar_type(addr,var,type): retype a decompiler local, working on auto/ register vars too (stock set_type only updates already-user-modified lvars) 'y' in a code view retypes what's under the cursor: a local variable (prompt prefilled with its current type) or a function (prompt prefilled with its full prototype). Applies via set_lvar_type / set_type, then recompiles + refreshes. Copy-line moved off 'y' to Ctrl+Y. domain: Program.func_types / set_function_type / set_lvar_type (LVar/FuncTypes). Pilot: function-prototype retype (prefill + apply). full suite 94/94.
Diffstat (limited to 'idatui/domain.py')
-rw-r--r--idatui/domain.py51
1 files changed, 51 insertions, 0 deletions
diff --git a/idatui/domain.py b/idatui/domain.py
index f52535c..279ef49 100644
--- a/idatui/domain.py
+++ b/idatui/domain.py
@@ -93,6 +93,21 @@ class Xref:
@dataclass(frozen=True)
+class LVar:
+ name: str
+ type: str
+ is_arg: bool
+
+
+@dataclass
+class FuncTypes:
+ addr: int
+ name: str
+ prototype: str # e.g. 'int __fastcall foo(int a, char *b)'
+ lvars: list[LVar]
+
+
+@dataclass(frozen=True)
class Struct:
name: str
size: int
@@ -495,6 +510,42 @@ class Program:
return res[0].get("error")
return None
+ # -- function / variable types ---------------------------------------- #
+ def func_types(self, ea: int) -> FuncTypes | None:
+ """Structured decompiler types for the function at ``ea`` (prototype +
+ local variables). None if ``ea`` isn't a decompilable function. Requires
+ the injected ``func_types`` server tool."""
+ try:
+ r = self.client.call("func_types", addr=hex(ea))
+ except IDAToolError:
+ return None
+ if not isinstance(r, dict) or r.get("error"):
+ return None
+ lvars = [LVar(name=lv.get("name", ""), type=lv.get("type", ""),
+ is_arg=bool(lv.get("is_arg")))
+ for lv in r.get("lvars", []) if isinstance(lv, dict)]
+ return FuncTypes(addr=_as_int(r.get("addr", hex(ea))), name=r.get("name", ""),
+ prototype=r.get("prototype", ""), lvars=lvars)
+
+ def set_function_type(self, ea: int, signature: str) -> str | None:
+ """Set a function's prototype. None on success, else an error string."""
+ r = self.client.call("set_type", edits=[{"addr": hex(ea), "signature": signature}])
+ res = r.get("result", []) if isinstance(r, dict) else []
+ row = res[0] if res and isinstance(res[0], dict) else {}
+ if row.get("ok"):
+ return None
+ return row.get("error") or "failed to set the prototype"
+
+ def set_lvar_type(self, fn_ea: int, var: str, ty: str) -> str | None:
+ """Set a decompiler local variable's type (via the injected server tool).
+ None on success, else an error string."""
+ r = self.client.call("set_lvar_type", addr=hex(fn_ea), variable=var, type=ty)
+ if isinstance(r, dict) and r.get("error"):
+ return r["error"]
+ if isinstance(r, dict) and not r.get("ok"):
+ return "failed to set the variable type"
+ return None
+
def delete_type(self, name: str) -> str | None:
"""Delete a named type. Returns None on success, else an error string.
Requires a server-side ``del_type`` tool; if absent, a clear message is