From ba0b26ebb0ce16632e8a2e67675dd79a11e26551 Mon Sep 17 00:00:00 2001 From: blasty Date: Sun, 26 Jul 2026 00:00:19 +0200 Subject: loading: ask how to load an unrecognised file, like IDA does MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Last commit let you SAY how to load a blob. This one notices when you should have. Interactive IDA pops a dialog when no loader matches; we silently loaded as x86 at 0 and analysed to nothing, so the flag only helped people who already knew they needed it — which is exactly the people who don't need help. formats.sniff() recognises the formats IDA definitely handles (ELF, PE, Mach-O, dex, wasm, ar, COFF, Intel HEX, S-records). Anything else gets LoadOptionsScreen: a filterable processor list with human labels, a load-address field, Enter to accept, Esc to load it the way IDA would have anyway. Deliberate asymmetry: the sniff only claims formats it is sure about. A false "unknown" costs one dismissible dialog; a false "known" is the silent wrong answer this exists to kill. Esc is always an escape hatch. The list offers 20 processors, not IDA's 73 — most of the rest are museum pieces, and a name typed into the filter that matches nothing is taken literally so nothing is actually unreachable. Endianness is spelled out (arm vs armb) because getting it backwards is the most common route to zero functions. Asked only when nobody has answered yet: not with --processor, not in project mode (entries carry their own), and not when a database exists — the .i64 already records how the image was loaded. Textual trap worth recording: the screen stored the file size in self._size, which is Widget's own backing field for outer_size. Assigning an int to it crashes layout with "'int' object has no attribute 'region'" from deep inside _set_dirty, nowhere near the cause. Same family as the _render collision. The paragraph conversion now lives in exactly one place (formats.load_args); BinaryRef and launch both call it. Verified on a real AArch64 blob: dialog appears, filtering to "arm" leaves two entries, base 0x8000000 accepted -> "-parm -b800000" -> 35 functions at 0x8002440. An ELF never asks, and neither does a blob that already has a .i64. tests: new tests/test_formats.py (21) and a load_options scenario asserting the dialog stays out of the way for a recognised binary. 199/0 scenarios, 39/0 project, 30/0 project UI, 36/0 index, 27/0 pool, 21/0 formats. --- docs/PROJECTS.md | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'docs') diff --git a/docs/PROJECTS.md b/docs/PROJECTS.md index fdd15a1..5f8e327 100644 --- a/docs/PROJECTS.md +++ b/docs/PROJECTS.md @@ -245,6 +245,33 @@ An ELF/PE/Mach-O says what it is, so IDA figures it out. A raw firmware dump says nothing, and IDA falls back to **x86 at address 0** — which on an ARM image analyses to zero functions. It doesn't fail; it just quietly gives you nothing. +Open one without saying anything and idatui asks, the way interactive IDA does +when no loader matches: + + ┌ unrecognised file — processor? (20) ────────────────┐ + │ fw.bin (32,768 bytes) — no loader matched; without │ + │ a processor IDA assumes x86 at 0 │ + │ arm │ + │ arm ARM / AArch64 — little-endian │ + │ armb ARM — big-endian │ + │ load address, e.g. 0x8000000 (blank = 0) │ + │ Enter accept · Tab base address · Esc load as IDA │ + └─────────────────────────────────────────────────────┘ + +`formats.sniff()` decides whether to ask, and only recognises formats IDA +definitely handles (ELF, PE, Mach-O, dex, wasm, ar, COFF, Intel HEX, S-records). +Being cautious the wrong way costs one dismissible dialog; being cautious the +other way is the silent-nothing case we're trying to kill. Esc loads it the way +IDA would have, because the sniff can be wrong. + +A text container is only accepted when the whole header is printable — a raw +image whose first byte happens to be `:` is far likelier than Intel HEX. + +The dialog is skipped when the answer already exists: options on the command +line, options in the project, or a database that already records them. + +Or say it up front: + ida-tui fw.bin --processor arm --base 0x8000000 or per binary in a project, which is where it belongs for a multi-image firmware: -- cgit v1.3.1-sl0p