forked from pret/ds_disassembly_tools
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmerge_nef.py
89 lines (75 loc) · 2.87 KB
/
merge_nef.py
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
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#!/usr/bin/env python3
# Creates an ELF from a NEF and corresponding SBIN.
import argparse
import tempfile
import subprocess
import struct
import shlex
import os
class Namespace(argparse.Namespace):
sbin: str
nef: str
elf: str
Elf32_Ehdr = struct.Struct('<16bhhlllllhhhhhh')
Elf32_Phdr = struct.Struct('<llllllll')
Elf32_Shdr = struct.Struct('<llllllllll')
Elf32_Sym = struct.Struct('<lllbbh')
def dump_autoloads(sbin, nef):
with open(sbin, 'rb') as sbinf:
binary = sbinf.read()
with open(nef, 'rb') as neff:
header = Elf32_Ehdr.unpack(neff.read(Elf32_Ehdr.size))
entry = header[19]
shoff = header[21]
shentsize = header[26]
shnum = header[27]
shstrndx = header[28]
neff.seek(shoff)
secs = list(Elf32_Shdr.iter_unpack(neff.read(shnum * shentsize)))
neff.seek(secs[shstrndx][4])
shstrtab = neff.read(secs[shstrndx][5])
sec_names = {}
for i, sec in enumerate(secs):
if sec[3] != 0:
sec_names[sec[3]] = shstrtab[sec[0]:].split(b'\0', 1)[0].decode()
if sec[1] == 2:
neff.seek(sec[4])
symtab = list(Elf32_Sym.iter_unpack(neff.read(sec[5])))
elif sec[1] == 3 and i != shstrndx:
neff.seek(sec[4])
strtab = neff.read(sec[5])
elif sec[1] == 1 and sec[3] != 0 and sec[3] <= entry and (sec[5] == 0 or entry < sec[3] + sec[5]):
secstart = sec[3]
for sym in symtab:
if strtab[sym[0]:].split(b'\0', 1)[0] == b'_start_ModuleParams':
offset = sym[1] - secstart
break
else:
raise ValueError('No symbol found in NEF named "_start_ModuleParams"')
atab_start, atab_end, aload, bss_start, bss_end = struct.unpack_from('<lllll', binary, offset)
aload -= secstart
tf = tempfile.NamedTemporaryFile(delete=False)
tf.write(binary[:aload])
tf.close()
yield sec_names.get(secstart), tf
for start, size, bsssize in struct.iter_unpack('<lll', binary[(atab_start - secstart):(atab_end - secstart)]):
tf = tempfile.NamedTemporaryFile(delete=False)
tf.write(binary[aload:aload + size])
tf.close()
yield sec_names.get(start), tf
aload += size
def main():
parser = argparse.ArgumentParser()
parser.add_argument('sbin')
parser.add_argument('nef')
parser.add_argument('elf')
args = parser.parse_args(namespace=Namespace())
tfs: list[str, tempfile.NamedTemporaryFile] = list(dump_autoloads(args.sbin, args.nef))
flags = ' '.join('--update-section {name:s}={file:s} -j {name:s}'.format(name=name, file=tf.name) for name, tf in tfs)
callstr = f'arm-none-eabi-objcopy {flags} {args.nef} {args.elf}'
print(callstr)
subprocess.run(shlex.split(callstr))
for name, tf in tfs:
os.remove(tf.name)
if __name__ == '__main__':
main()