aboutsummaryrefslogtreecommitdiffstats
path: root/tools/verify_procs.py
diff options
context:
space:
mode:
authorblasty <blasty@local>2026-07-26 00:04:38 +0200
committerblasty <blasty@local>2026-07-26 00:04:38 +0200
commitcf8b4645e2744fff455fc09167f91d011a3e620a (patch)
treef8480964ec9e531ed98916f3cb6a5d513833a2b6 /tools/verify_procs.py
parentloading: ask how to load an unrecognised file, like IDA does (diff)
downloadida-tui-cf8b4645e2744fff455fc09167f91d011a3e620a.tar.gz
ida-tui-cf8b4645e2744fff455fc09167f91d011a3e620a.tar.xz
ida-tui-cf8b4645e2744fff455fc09167f91d011a3e620a.zip
formats: verify every offered processor name against a real IDA
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.
Diffstat (limited to 'tools/verify_procs.py')
-rw-r--r--tools/verify_procs.py64
1 files changed, 64 insertions, 0 deletions
diff --git a/tools/verify_procs.py b/tools/verify_procs.py
new file mode 100644
index 0000000..8012931
--- /dev/null
+++ b/tools/verify_procs.py
@@ -0,0 +1,64 @@
+#!/usr/bin/env python3
+"""Check every name in ``formats.PROCESSORS`` against a real IDA.
+
+Run this before adding a processor to the list.
+
+A wrong ``-p`` name is not a soft failure: IDA refuses to open the database
+(rc=4) with nothing useful said, which is the same silent-failure class the load
+dialog exists to prevent. Offering a name that doesn't work would hand the user
+a dead end from inside the very UI meant to rescue them.
+
+Two of the first twenty entries were wrong — ``h8`` and ``sparc`` are module
+FILENAMES (procs/h8.so, procs/sparc.so), not processor names; the real ones are
+``h8300`` and ``sparcb``/``sparcl``. The aliases people reach for first
+(``arm64``, ``aarch64``, ``mips``, ``m68k``) are all invalid too, which is why
+they appear in the human labels instead, where the filter can still find them.
+
+ /usr/bin/python tools/verify_procs.py # needs idalib, not textual
+"""
+
+from __future__ import annotations
+
+import os
+import sys
+import tempfile
+
+sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+
+from idatui.formats import PROCESSORS # noqa: E402
+
+
+def main() -> int:
+ import idapro
+ idapro.enable_console_messages(False)
+ import ida_auto
+ import ida_ida
+
+ blob = bytes(range(256)) * 8
+ bad: list[tuple[str, int, str]] = []
+ for name, desc in PROCESSORS:
+ # A fresh directory each time: once a database exists IDA ignores the
+ # load switches, and every name after the first would "pass".
+ d = tempfile.mkdtemp()
+ path = os.path.join(d, "probe.bin")
+ with open(path, "wb") as f:
+ f.write(blob)
+ rc = idapro.open_database(path, run_auto_analysis=False, args=f"-p{name}")
+ got = ""
+ if rc == 0:
+ ida_auto.auto_wait()
+ got = ida_ida.inf_get_procname()
+ idapro.close_database(save=False)
+ ok = rc == 0 and got.lower() == name.lower()
+ print(f" {'ok ' if ok else 'BAD '} {name:<12} rc={rc} -> {got!r} {desc}")
+ if not ok:
+ bad.append((name, rc, got))
+
+ print(f"\n{len(PROCESSORS) - len(bad)}/{len(PROCESSORS)} verified")
+ for name, rc, got in bad:
+ print(f" {name}: rc={rc} procname={got!r}")
+ return 1 if bad else 0
+
+
+if __name__ == "__main__":
+ raise SystemExit(main())