diff options
| author | blasty <blasty@local> | 2026-07-26 15:38:06 +0200 |
|---|---|---|
| committer | blasty <blasty@local> | 2026-07-26 15:38:06 +0200 |
| commit | fb275522b143d3891f5f8e9b1e6eaa635537ec15 (patch) | |
| tree | 28dc600876269e32758aa7429ca492e779ca1cc1 /tests | |
| parent | app: rebuild the function index after an edit changes it (diff) | |
| download | ida-tui-fb275522b143d3891f5f8e9b1e6eaa635537ec15.tar.gz ida-tui-fb275522b143d3891f5f8e9b1e6eaa635537ec15.tar.xz ida-tui-fb275522b143d3891f5f8e9b1e6eaa635537ec15.zip | |
decomp: say WHY a function won't decompile
"I can't decompile my freshly defined function" — and the app's answer was to
flash and go back to the listing. It knew the reason and threw it away twice.
The plain decompile tool reports "Decompilation failed at 0x0 (address: 0x0)".
Hex-Rays itself fills in a hexrays_failure_t with the actual sentence, and in
this case it is the whole answer: "only 64-bit functions can be decompiled in
the current database". Nobody can guess that from a flash, and it is not fixable
in place — the database's bitness is set at load — so without the message there
is no way forward at all.
New decomp_error tool returns Hex-Rays' own description; _load_decomp asks for it
in the same worker when a decompile fails, and the status now reads:
sub_0: cannot decompile — only 64-bit functions can be decompiled in the
current database — Ctrl+L and pick arm:ARMv7-A
Then it got thrown away a second time, by the reload. Falling back to the
listing reopens it, and the reload writes its own status afterwards — the same
clobber that has now bitten four times. The fix this round is the last one:
_flash is SHOWN by idle status writes but no longer CONSUMED by them, because a
reload emits several (prime, then cursor) and consuming on the first meant the
second erased the message. It clears on the next keypress instead — when the
user has actually moved on.
(That also fixes a self-inflicted "status: None": the old code read _flash back
after something else had already consumed it.)
tests: +2 thumb (15) — a failed decompile says why in Hex-Rays' words, and the
reason survives the view reloading under it. 209/0 scenarios, 30/0 blob, 30/0
project UI.
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/test_thumb_ui.py | 20 |
1 files changed, 20 insertions, 0 deletions
diff --git a/tests/test_thumb_ui.py b/tests/test_thumb_ui.py index 090dc2a..5b6f18e 100644 --- a/tests/test_thumb_ui.py +++ b/tests/test_thumb_ui.py @@ -146,6 +146,26 @@ async def run() -> int: "64-bit" in status and "decompile" in status, status[:120]) check("and names the fix", "ARMv7-A" in status, status[:120]) + # And if you ignore that and carry on, the failure has to say WHY. The + # plain decompile tool reports "Decompilation failed at 0x0" and drops + # the reason, which is the only part that tells you what to do — with it + # missing, F5 doing nothing is indistinguishable from a bug in the TUI. + lst.cursor = lst.model.index_of_ea(0) + await pilot.pause(0.2) + mp = lst.model + await pilot.press("p") + await wait(lambda: lst.model is not mp and lst.model is not None, pilot, 60) + await wait(lambda: app._func_index is not None + and len(app._func_index) > 0, pilot, 60) + await pilot.press("tab") + await wait(lambda: "cannot decompile" in + str(app.query_one("#status", Static).render()), pilot, 90) + status = str(app.query_one("#status", Static).render()) + check("a failed decompile says why, in Hex-Rays' own words", + "only 64-bit functions" in status, status[:130]) + check("and the reason survives the view reloading under it", + "cannot decompile" in status, status[:130]) + # -- the whole point: a 32-bit database decompiles ---------------------- # for ext in (".i64", ".id0", ".id1", ".id2", ".nam", ".til"): try: |
