aboutsummaryrefslogtreecommitdiffstats
path: root/tools (follow)
Commit message (Collapse)AuthorAgeFilesLines
* demo: tighten the pacing (43s of pauses -> 19s)blasty4 days1-38/+38
| | | | | | | | | | Manual navigation is snappy; the demo was not, because I authored the pauses for someone reading every status line. Halved every beat with a 0.25s floor so the scenes stay distinguishable, and dropped the prompt typing from 45ms to 18ms per character -- still legibly typing, no longer something you wait on. --speed still scales it either way: 0.5 for a fast cut, 2.0 to slow it back down for a narrated take.
* demo: do not re-navigate to main when the app already landed thereblasty4 days1-3/+11
| | | | | | | The app auto-lands on main once the function index is in, so scene_open typed a goto to a place it was already standing. Every keystroke a driver injects costs a round trip, so that was pure dead time at the very start of the tour -- the worst place to spend it, since it is the part a recording opens on.
* demo: --here, render the TUI in the terminal that ran the demoblasty4 days1-13/+89
| | | | | | | | | | | | | | | | | | | | | | | | | --spawn needs tmux or zellij and puts the app in a second pane, which is wrong when the capture is one terminal. --here launches the TUI through the ./ida-tui launcher with stdio inherited, so it draws on the terminal you ran the demo from, then drives it over the socket exactly as before and quits it at the end. Going through the launcher rather than re-deriving the interpreter keeps the $IDATUI_PYTHON rules in one place. Two things this mode has to get right: - Narration would be drawn over the app, so it is collected and replayed after the alternate screen is gone. The operator still sees the full scene list, just at the end instead of during. - The socket is waited for with a deadline that also watches the child, so a TUI that dies before it ever listens fails in a second instead of hanging until the timeout. Teardown reaps the process (wait, then terminate, then kill) and removes the scratch copy on every path. --here and --spawn are rejected together. Verified: argument handling, the mutual exclusion, and that the pure suites are unaffected. The end-to-end --here run is NOT verified here -- it needs a real terminal, which this environment does not have.
* tools/demo.py: a scripted feature tour, and the RPC bug it foundblasty4 days1-0/+325
| | | | | | | | | | | | | | | | | | | | | | | | | | Ten scenes over the RPC layer: goto, listing scroll, pseudocode, the literal format ring, follow/back, the graph (zoom, minimap, edge walking), split view, xrefs, a rename and a comment, the strings/symbols/structs/hex browsers, and search. It drives the semantic verbs, so prompts are typed character by character and a recording shows the app being used rather than poked. --spawn opens its own pane on a COPY of the target (binary plus .i64, so the analysis is not re-paid) and tears it down afterwards; --sock drives a session you set up yourself, for control over pane size and zoom. Edits are reverted at the end, including a re-navigate so the last frame does not still show the demo's rename. --speed scales every pause, --only runs a subset, --list prints the scenes. Writing it found a real bug in the RPC hex verb: it waited for `app.is_hex` to become true, but backslash TOGGLES the hex view, so the call that leaves hex could never satisfy its predicate and always timed out after 20s. Any driver could open the hex view and never close it. It now waits for the mode to flip, the way toggle_view already did. Verified by running every scene against a live database and asserting the UI actually moved -- landed on main, decomp reachable, graph reports 280 blocks, split toggles off, no modal left open, the rename reaches the database and the revert removes it. 15/15. Full suite still 788 passed, 0 failed.
* splash: blasty's transparent logo, and stop guessing the cell aspectblasty5 days1-0/+90
| | | | | | | | | | | | | | | | | | | | | | | | | | | | The artwork is now a proper transparent PNG with soft edges (24% of its pixels carry partial alpha) instead of opaque art on black with a stray full-width scan line along the bottom. Cropped to its content and resized 1024 -> 768px, which halves the file and costs nothing visible; logo-trans.png keeps the master for future re-renders. Two things the new art exposed, both wrong before it: fit() assumed cells were 1:2. This terminal reports 9x22, i.e. 1:2.44. The old logo was 474x516 -- close enough to the assumption that nobody noticed -- but a square image at the hardcoded 60x33 would have been visibly stretched. The graphics query now asks for the cell size too (CSI 16 t rides along in the same round trip, before the DA1 that already synchronises it) and fit() uses the answer. The footprint was a constant. logo_cells() derives it from the artwork and the measured cell size, so the art can be replaced without anyone remembering to edit a number. logo.ans was stale: the block-art fallback for terminals that can't draw an image was still the OLD artwork, scan line included. tools/make_logo_ans.py regenerates it from logo.png so the two cannot drift again. It understands alpha -- a transparent cell emits no colour and lets the terminal background through, and a cell with only one opaque half uses the matching half block so the pixel lands on the correct side.
* arm: offer 32-bit ARM at load, and fix `p` on carved codeblasty2026-07-261-2/+11
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Reported as "after c a few times and p at the entry point, Tab just flashes and nothing decompiles". Three separate things, found by following it down: **1. `p` failed on hand-carved code.** ida_funcs.add_func(ea) asks IDA to find the function's end and on carved code it often can't — a run ending in a tail call, or whose last instruction isn't recognised as a return, fails with no reason given. add_func(ea, end) with an explicit end succeeds. define_func_run tries IDA's way first, then falls back to the end of the contiguous instruction run, and says which it used. **2. The database was 64-bit, so Hex-Rays refused it regardless.** Bare `-parm` gives an AArch64 database. Ask Hex-Rays for the failure object rather than reading None as "dunno" and it says exactly what's wrong: "only 64-bit functions can be decompiled in the current database". So the disassembly looked right and F5 could never work. That is decided at LOAD and cannot be corrected — inf_set_app_bitness(32) afterwards makes the decompiler INTERR 50735. The fix is at the load dialog: arm:ARMv7-A (most firmware), arm:ARMv7-M / arm:ARMv6-M (Cortex-M, Thumb only) and arm:ARMv5TE now sit alongside 64-bit `arm`, labelled with their bitness. With arm:ARMv7-A, experiments/fibonacci.bin decompiles: void __fastcall __noreturn sub_0(int a1) { int v2; v2 = sub_E3C(a1, 0); ... } — and IDA's own auto-analysis finds 54 Thumb functions on load, versus none as plain `arm`. **3. `t` was silently building an undecompilable state.** It forced the SEGMENT to 32-bit in a 64-bit database, which produces correct-looking disassembly that F5 will never touch. It now says so and names the fix (Ctrl+L, arm:ARMv7-A) rather than leaving you to discover it. tools/verify_procs.py now reports each processor's resulting bitness, since that is the reason the variants exist — and it compares against the base module name, because a variant reports "ARM". tests: test_thumb_ui.py +5 (13 total) — a 64-bit database warns and names the fix, a 32-bit one finds functions by itself, Tab decompiles a Thumb function and the result reads like C. test_formats.py +2 (34) pinning that a 32-bit variant is offered and the ARM labels state their bitness. 209/0 scenarios, 26/0 blob, 30/0 project UI.
* formats: verify every offered processor name against a real IDAblasty2026-07-261-0/+64
The curated list was written from the procs/ directory listing. Two of the twenty names were wrong, and wrong here is not a soft failure: IDA REFUSES to open the database (rc=4) with nothing useful said. The load dialog would have handed people a dead end from inside the UI that exists to rescue them — the same silent-failure class the dialog was built to kill. h8 -> h8300 (h8.so is the module FILENAME, not a processor name) sparc -> sparcb / sparcl (and SPARC has endianness variants, like MIPS/PPC) Also probed the aliases people reach for first: arm64, aarch64, mips, m68k are all invalid. 'arm' covers AArch64 (verified: an AArch64 blob analyses to 35 functions under -parm), so those names now live in the human labels, where the filter still finds them — typing "arm64" finds ARM, "m68k" finds 68k, "mips" finds both endiannesses. tools/verify_procs.py does the check: open a scratch blob with -p<name>, read back inf_get_procname(), compare. Fresh temp dir per name, because once a database exists IDA ignores the load switches and every name after the first would "pass". 21/21 verified. tests: +11 formats, including the verified-set guard (adding a processor without re-running the script fails on purpose) and checks that the rejected aliases are NOT offered but ARE still findable by typing them. 32/0 formats, 199/0 scenarios.