diff options
| author | blasty <blasty@local> | 2026-07-26 09:21:52 +0200 |
|---|---|---|
| committer | blasty <blasty@local> | 2026-07-26 09:21:52 +0200 |
| commit | 3ba7518a600fceeffaa9c077a8f2855490f92ac7 (patch) | |
| tree | 3783324bff28c07e7c468d96b1a1cf66e3793945 /server | |
| parent | loading: a blob that analyses to nothing is still openable (diff) | |
| download | ida-tui-3ba7518a600fceeffaa9c077a8f2855490f92ac7.tar.gz ida-tui-3ba7518a600fceeffaa9c077a8f2855490f92ac7.tar.xz ida-tui-3ba7518a600fceeffaa9c077a8f2855490f92ac7.zip | |
listing: make every undefined byte its own row, so you can carve anywhere
Loading a blob and pressing `c` at 0 disassembles one instruction; everything
after it collapsed into a single row — "db 2044 dup(?)" — with no cursor
position anywhere inside it. There was no way to start a second instruction
stream at an arbitrary offset, which is most of what carving a firmware image
IS. In IDA every undefined byte is its own line and you just put the cursor on
one.
The collapse existed for a real reason (see the comment in the heads tool): a
.bss or a fresh blob would otherwise be millions of one-byte rows, and this
model materialises what it walks. Expanding physically would also make
`g <far address>` walk every byte in between.
So the run stays ONE physical head and PRESENTS as N logical rows. _row_at is a
prefix sum over heads, _phys() maps a row back to (head, byte offset), and the
text for an interior row is synthesised on demand — "db 4Ah", the actual value,
because the byte values are the whole point when you're looking for a stream.
Memory is unchanged (libcrypto: 1 head for its 80-byte .bss, 61MB RSS), and
index_of_ea into the middle of a run is 0.01ms via bisect.
Now: cursor on any byte, `c`, and you get an instruction; the bytes before it
stay individually addressable.
Two bugs found on the way:
* IDAToolError takes (tool, message) and five call sites in domain.py passed one
string. Every one of those error paths raised TypeError INSTEAD of the real
error — "define code @ 0x4020: Failed to create instruction" reached the user
as "IDAToolError.__init__() missing 1 required positional argument". Fixed all
five; the message that finally came through is what identified the next issue.
* Searching now walks one row per undefined byte, so _index_for_search is capped
at 400k lines and says when it truncated, rather than grinding through a
multi-megabyte blob nobody wants to text-search.
tests: test_blob_ui.py +8 — a run presents one row per byte, each is a single
addressable byte showing its value, an interior address resolves to its own row,
`c` on a chosen byte carves there, the carved row spans the instruction, and
neighbouring bytes stay addressable. Uses PLANTED A64 instructions, because
whether random bytes decode is chance and a test that depends on chance is
worthless on the run where it fails. 19/0 blob, 202/0 scenarios, 30/0 project UI.
Diffstat (limited to 'server')
0 files changed, 0 insertions, 0 deletions
