diff options
| author | blasty <blasty@local> | 2026-08-07 00:33:12 +0200 |
|---|---|---|
| committer | blasty <blasty@local> | 2026-08-07 00:33:28 +0200 |
| commit | 2b0ae8df463edb597007186688ee557c18f1ac18 (patch) | |
| tree | 006045dd73f4049d98e20a8c0830406490445f08 /docs | |
| parent | launch: the sweep could delete the file it was asked to open (diff) | |
| download | ida-tui-2b0ae8df463edb597007186688ee557c18f1ac18.tar.gz ida-tui-2b0ae8df463edb597007186688ee557c18f1ac18.tar.xz ida-tui-2b0ae8df463edb597007186688ee557c18f1ac18.zip | |
diag: somewhere for swallowed errors to go
A TUI must not die because one background load failed, so this codebase catches
broadly -- ~50 `except Exception` sites, two dozen resolving to `pass`. Right
policy, one bad consequence: with 44 `@work(thread=True)` workers, a failure in
a background load leaves no trace whatsoever. The view stays empty and there is
nothing to read afterwards, because the app owns the screen.
kittygfx already solved this for itself with $IDATUI_KITTY_LOG. idatui/diag.py
is the same idea for everything else: $IDATUI_LOG writes every swallowed error
plus its traceback to a file, and the last 50 are kept in memory regardless so a
driver can ask a live app what went wrong. Unset, it costs an environ lookup.
Wired in where losing the error changes a DECISION rather than just a pixel:
* rename: a resolve() that throws renames as DATA instead of as a function.
* name: a function_of() that throws means we never learn the address is a
function start, so the index keeps the old name and every readback says the
rename didn't happen.
* retype: a resolve() that throws retypes the ENCLOSING function instead.
* decompile: a failed full-body fetch silently returns CLIPPED pseudocode.
* trail: a failed decomp_map stops the pseudocode being painted, silently.
Deliberately NOT wired into the query_one guards -- a modal owning the screen is
normal and constant, and logging it would bury the real entries in noise.
New RPC verb `diag {n?, clear?}`, documented in docs/RPC.md: the answer to "the
verb reported success and the pane shows nothing".
Also a flake, same shape as the others: follow_xrefs waited on the nav depth but
asserted on _cur, and a follow pushes the source entry BEFORE opening the
target -- so the check could run in between and see the function it jumped
from. About one run in ten. It waits on the postcondition it asserts now; three
clean full runs since.
833 checks; --fast is 344 in 3.5s.
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/RPC.md | 1 |
1 files changed, 1 insertions, 0 deletions
diff --git a/docs/RPC.md b/docs/RPC.md index 3ea7f33..e433551 100644 --- a/docs/RPC.md +++ b/docs/RPC.md @@ -71,6 +71,7 @@ stalls. `target` is a name, `0xADDR`, or omitted (= current function). | `xrefs_to` | `target`, `limit?=200` | `[{frm,to,type,fn_addr,fn_name}]` — who references it. | | `xrefs_from` | `target`, `limit?=200` | what it references. For a **function** (name/entry ea): whole-body callees + string/data refs from the decompiler, `[{to,name,string,is_func,type}]`. For an explicit **0xADDR**: address-scoped `[{frm,to,type,fn_addr,fn_name}]`. | | `resolve` | `name` | `{ea}` (or `{ea:null}`). | +| `diag` | `n?=10`, `clear?` | `{recent:[{when,what,error,where,thread}], log}` — errors the app swallowed rather than crashing on. The answer to "the verb said success and the pane shows nothing": inside a full-screen TUI a traceback has nowhere to go, so it comes out here. Set `$IDATUI_LOG=/tmp/x.log` when spawning for the same entries plus tracebacks, on disk. | ### Semantic verbs High-level ops type through the **real prompts** with a per-char delay |
