aboutsummaryrefslogtreecommitdiffstats
path: root/idatui/domain.py (follow)
Commit message (Collapse)AuthorAgeFilesLines
* disasm: render opcode bytes (toggle 'o'), padded to widest insnblasty10 days1-3/+75
| | | | | | | | | | | | | | Fetch per-instruction opcode bytes alongside the disasm listing and show them in a column between the address and the mnemonic. Instruction length comes from consecutive addresses (variable-length safe: x86 movabs shows its full 10 bytes); the block over-fetches one instruction for the last line's boundary, falling back to the function end for the final insn. The column pads to the widest instruction across the whole function: _fetch_block tracks a running max, and on load a background scan_bytes() settles a stable width so padding doesn't jump as blocks stream in. _op_field is shared by the rendered strip, _line_plain, and search _fmt so cursor/match offsets stay aligned. 'o' toggles the column.
* fix: don't hang drive pc on undecompilable functionsuser11 days1-1/+16
| | | | | | | | | | | | | | | | toggle_view's settle predicate (lambda: app._active != before) never fired when tabbing toward pseudocode on a function Hex-Rays can't decompile: App._apply_decomp snaps the view back to disasm, so _active returns to its prior value -> full 20s settle timeout (x2 in _show_decomp, ~40s for drive pc). Recognize the decomp-failed fallback as settled. Also harden two amplifiers surfaced by the same case: - rpcclient: the CLI socket had no read timeout and would block forever on any server slowness; add a bounded settimeout (IDATUI_RPC_TIMEOUT, default 90s) with a clear error. - domain.decompile: pass a bounded 15s timeout and cache failures, so a failing decompile can't sit at the 30s client default or be re-run by transport retries.
* hex view: file offsets + 'g' goto (dedicated input)blasty11 days1-0/+31
| | | | | | | | | | | | | Add a file_regions server tool (get_fileregion_offset per segment) and Program.file_regions/file_offset so a virtual address maps to its raw on-disk offset without a format-specific header parser. The hex view now shows a VA column and a file-offset column side by side, and the status line reports file+off. Goto moves to its own top-level #goto Input instead of overloading the function-filter box (which is hidden with the names pane, so goto was unreachable there). In the hex view 'g' jumps the cursor to an address (bounds-checked against the image); elsewhere it navigates as before.
* hex view: raw image bytes (VA-addressed), synced to the code cursorblasty11 days1-0/+119
| | | | | | | | | | | | | | | | New HexView: a line-virtualized 16-bytes/row dump of the whole loaded image, addressed by virtual address. Format-agnostic — the range/segments come from IDA (image_range over sections()), not any file header; gaps read back as zeros. Backslash toggles it, synced to the address under the disasm/pseudocode cursor (see the naked bytes of some code/data). In hex: hjkl/paging navigate a byte cursor (status shows the section), Enter jumps the code view to the byte, Tab/Esc/backslash return to the preferred code view. A third _active state; block -cached + prefetched like the disasm model. domain: HexModel + Program.hex_model/read_bytes/image_range (get_bytes regions). Fixed a self-deadlock (hex_model held _lock while sections() re-locked). Pilot: sync, actual bytes, byte-step, return. full suite 98/98.
* retype: set variable/function types with 'y' (IDA-style), via structured toolsblasty11 days1-0/+51
| | | | | | | | | | | | | | | | 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.
* struct editor: C-style CRUD for local types (Ctrl+T)blasty12 days1-0/+77
| | | | | | | | | | | | | | | | | New StructEditor overlay: left is the list of local structs/unions, right is an editable C definition. Enter loads a struct (reconstructed as C from its member layout via type_inspect), Ctrl+S declares it (create or update via declare_type), Ctrl+N starts a new one, Del deletes, Esc returns to the list then closes. Domain: Struct model + Program.list_structs / struct_source / declare_type / delete_type (anonymous $-types filtered). Delete needs a 'del_type' tool the ida-pro-mcp server doesn't currently expose; delete_type detects its absence and reports a clear message instead of failing. Create/read/update work fully. Pilot checks: open, list, view C, create, update-in-place, delete(-or-report), close. full suite 84/84.
* xrefs: informative labels — function+offset, and section instead of '?'blasty12 days1-0/+34
| | | | | | | | | | | | | | | The xref list showed just the containing function name, so multiple sites in the same function were indistinguishable ('sub_2300' repeated), and references not in any function collapsed to a bare '?'. - In-function sites now show fn_name+offset (e.g. main+0xb08), so each site is distinct and you can see where in the function it is. - Non-function sites (GOT/reloc data slots, loose thunks) show the section they live in (.got, .data.rel.ro, .text, LOAD, ...) instead of '?'. Add Program.sections()/section_of() over survey_binary's segment map (fetched once, cached lazily). Pilot checks for both. full suite 67/67.
* comments: ';' sets a comment on the current line (disasm + pseudocode)blasty12 days1-0/+7
| | | | | | | | | | | | | Bind ';' (NavMixin, so both code views) to a comment prompt for the line under the cursor. Resolve the line's address (_cursor_ea in disasm, the /*0xEA*/ marker in pseudocode), prefill any existing comment (parsed from the rendered '//' text), and apply via the set_comments tool; an empty value clears it. After setting, reuse the name-generation invalidation (bump_names) so Hex-Rays is force_recompiled lazily and the pseudocode/disasm refresh in place at the saved position -- the new '// comment' shows on the line. Marks the IDB dirty (Ctrl+S). Pilot checks for the pseudocode round-trip. full suite 63/63.
* fix: pseudocode names not refreshing across history after renameblasty12 days1-1/+1
| | | | | | | | force_recompile takes 'items=[{addr}]', not 'addr' — my call raised and was swallowed, so the Hex-Rays cache was never cleared and a caller's cached pseudocode kept showing the old callee name on 'back' (disasm refreshed because its names are live). Use the correct params. History test now also caches and verifies the caller's pseudocode. pilot suite 52/52.
* fix input visibility (search/rename) + refresh stale names across historyblasty12 days1-4/+24
| | | | | | | | | | | | | | - Visibility: #search/#rename/#status were dock:bottom like the Footer and got placed on the SAME row (y=39) as the Footer, which drew over them, so the typed text was invisible. Drop the docking; they now sit in normal flow just above the Footer (y=38). Verified: input region is above the footer. - Stale names on 'back': a rename only invalidated the current function, so popping back to a caller (cached earlier) showed the old name. Add Program.bump_names(): a rename bumps a name-generation, clears all disasm block caches (disasm names are live), and decompilation is generation-checked and force-recompiled lazily on next view. _after_rename now invalidates globally. - verified: rename a callee, 'back' to the caller shows the new name. - pilot suite 51/51.
* rename symbol under cursor ('n') + save ('Ctrl+S')blasty12 days1-0/+13
| | | | | | | | | | | | | | | | | - 'n' on the token under the cursor opens a rename prompt prefilled with the current name. The symbol is classified and routed to the right rename batch: * resolves to a function start -> func * decompiler ref (global/string) -> data * pseudocode token, not a ref -> local (Hex-Rays lvar) * disasm var_/arg_ -> stack tool errors (e.g. name collisions) are surfaced in the status line. - after a rename: force_recompile + cache invalidation, reload the current views (preserving cursor), update the renamed function's row in place (avoids racing the initial stream), and update nav history names. - 'Ctrl+S' persists the IDB (idb_save); edits mark the session dirty. - 'n'/'N' search-repeat dropped for 'n'=rename (repeat stays on '/'+Enter / '?'). - verified live: func rename (list + disasm update), local var rename (pseudocode update), save. pilot suite 44/44; domain 17/17.
* xrefs + follow-under-cursor (disasm & pseudocode)blasty12 days1-0/+81
| | | | | | | | | | | | | | | - Enter follows the reference under the cursor: disasm uses xref_query(from) to find the code target; pseudocode matches a decompiler ref name on the line. Navigates to the containing function at the exact line (address-history push). - x opens an xrefs popup (XrefsScreen modal): xrefs_to the subject under cursor (call target if any, else the current item); Enter jumps to a referencing site, Esc closes. - domain: Program.function_of (mid-addr -> containing func via lookup_funcs), xrefs_from/xrefs_to (xref_query), Xref model, DisasmModel ea->index map for landing on an exact address. - fix: goto to a mid-function address now lands on the right line (was opening it as a bogus function start). - pilot suite 32/32; domain 17/17.
* function-name filter: incremental + highlight + clearblasty12 days1-0/+4
| | | | | | | | | | | | - Incremental client-side filter over the cached function list (no per-keystroke server round-trips): narrows + highlights the matched substring in each name as you type, debounced ~80ms. Substring or glob (*/?), smartcase. - Clear the filter: Esc in the filter box, OR Esc on the focused list, OR empty Enter. Status shows 'filter <q>: N/total'. - streaming pauses while a filter is active; re-applied over the full set once load completes. Row selection resolves the name from the index (cells can now be styled Text). - FunctionIndex.all_loaded(); pilot suite 27/27.
* decompiler view: Tab/Shift+Tab toggle disasm<->pseudocode, full bodiesblasty13 days1-5/+32
| | | | | | | | | | | - domain.decompile now fetches the FULL body: server caps responses at 50KB and clips strings to 1KB, but caches the full output and exposes it at _meta.ida_mcp.download_url -> we GET that so pseudocode is complete (main: 43257 chars, not a 1KB stub). include_addresses gives per-line /*0xEA*/. - DecompView (read-only TextArea, cpp highlighting best-effort, line numbers) - Tab and Shift+Tab toggle the code pane; lazy decompile in a worker, cached; hard-failures ('decompilation failed') shown gracefully with disasm fallback - pilot suite 14/14 (adds tab->pseudocode, full-body, shift+tab->disasm)
* Phase 1 TUI: two-pane functions<->disasm, virtualized listing, nav backboneblasty13 days1-0/+34
| | | | | | | | | | | | | | | - idatui/app.py: keyboard-first Textual app * FunctionsPanel: lazy-streamed function list (DataTable) with glob filter * DisasmView: line-VIRTUALIZED ScrollView -- paints from domain block cache, background-fetches misses, prefetches neighbors. Proven: 52,120-insn func, jump-to-bottom in 0.31s with only ~6 blocks (~1.5k lines) ever materialized. * address-history nav stack (Enter follow / Esc back); goto by name or 0xADDR * bump_idle_ttl + KeepAlive on startup so the session never idles out * all MCP work on Textual worker threads; UI never blocks - idatui/tui.py: launcher (python -m idatui.tui / console script 'idatui') - tests/test_tui.py: headless Pilot test, 9/9 (boot, load 10k funcs, open, scroll, bg-cache, goto-bottom, filter) - pyproject: textual extra + idatui script entry
* domain/paging layer: FunctionIndex, block-cached DisasmModel, decompile, resolveblasty13 days1-0/+384
- Program: model registry + small prefetch pool; cache invalidation hooks - FunctionIndex: lazy pagination (advance by len, clamp page=500), filter globs, viewport windows; full 10,092-func enumerate matches survey in ~3.1s - DisasmModel: block-cached windowed disasm (256/block), forward+back prefetch, cached instruction totals; deep window revisit 196ms -> 0ms (cache proven) - Decompilation: truncation-aware, hard-failure surfaced as data (monster funcs) - resolve(): int/hex/symbol via lookup_funcs (string-array query shape) - tests/test_domain.py: 17/17 on both ls (~290 funcs) and libcrypto (10k+52k-insn) - smoke_client no longer assumes 'main' exists (works on libraries) - doc: idle_ttl worker self-exit finding ("not reachable" needs re-open)