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
|
"""Produce readable .c files for every component at every version.
Unlike phase3 (which normalises aggressively for diffing), this preserves
everything a human wants: real names, formatting, comments, and each function's
address. One .c per build, plus a per-build index.
"""
import glob, os, sys, time
import idapro, idautils, idc, ida_hexrays
def dump(elf, out):
rc = idapro.open_database(elf, run_auto_analysis=False)
if rc != 0: return None
ida_hexrays.init_hexrays_plugin()
fns = sorted(idautils.Functions())
named = sum(1 for f in fns if not idc.get_func_name(f).startswith(('sub_','nullsub')))
with open(out, 'w') as fh:
fh.write("/* %s\n %d functions (%d named) — decompiled with ported symbols\n"
" Generated by phase6_dump_c.py; addresses are the build's own VAs. */\n\n"
% (os.path.basename(elf), len(fns), named))
for f in fns:
n = idc.get_func_name(f)
end = idc.get_func_attr(f, idc.FUNCATTR_END)
cmt = idc.get_func_cmt(f, 1) or idc.get_func_cmt(f, 0) or ''
fh.write("//" + "-"*76 + "\n// %s @ %#x-%#x (%d bytes)\n" % (n, f, end, end-f))
if cmt:
for line in cmt.splitlines(): fh.write("// %s\n" % line)
try:
fh.write(str(ida_hexrays.decompile(f)) + "\n\n")
except Exception as e:
fh.write("/* decompilation failed: %r */\n\n" % (e,))
idapro.close_database(save=False)
return len(fns), named
if __name__ == '__main__':
os.makedirs('decompiled', exist_ok=True)
fams = sys.argv[1:] or ['hdcp','sos','sys_drv','asd']
for fam in fams:
for elf in sorted(glob.glob('handover/elf/versions/%s/*.elf' % fam)):
tag = os.path.basename(elf)[:-4]
out = 'decompiled/%s.c' % tag
t0 = time.time()
r = dump(elf, out)
if r is None: print(" FAILED %s" % tag, flush=True); continue
print(" %-42s %5d fns (%4d named) %7d bytes %.1fs"
% (tag, r[0], r[1], os.path.getsize(out), time.time()-t0), flush=True)
|