1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
|
#!/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()
# "arm:ARMv7-A" selects a VARIANT: inf_get_procname() reports the base
# module ("ARM"), so compare that and check the bitness separately —
# the variant is only worth offering if it actually changes something.
base = name.split(":", 1)[0]
bits = ""
if rc == 0:
import ida_ida
bits = f" bitness={ida_ida.inf_get_app_bitness()}"
ok = rc == 0 and got.lower() == base.lower()
print(f" {'ok ' if ok else 'BAD '} {name:<14} rc={rc} -> {got!r}{bits} {desc}")
if rc == 0:
idapro.close_database(save=False)
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())
|