diff options
| author | blasty <peter@haxx.in> | 2026-07-10 13:30:48 +0200 |
|---|---|---|
| committer | blasty <peter@haxx.in> | 2026-07-10 13:30:48 +0200 |
| commit | 7eab44b3dbdccb8434e658a0ab5f3bebe14d2935 (patch) | |
| tree | 40278c66ac828e7073b74d9d0728c1473293779d /idatui/domain.py | |
| parent | struct editor: auto-format the definition on save (diff) | |
| download | ida-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.py | 51 |
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 |
