From fb275522b143d3891f5f8e9b1e6eaa635537ec15 Mon Sep 17 00:00:00 2001 From: blasty Date: Sun, 26 Jul 2026 15:38:06 +0200 Subject: decomp: say WHY a function won't decompile MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "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. --- tests/test_thumb_ui.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) (limited to 'tests') 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: -- cgit v1.3.1-sl0p