7edbfcb7838f45d8d6181cce4bdd52f7b70a7dd7
[lunaix-os.git] / lunaix-os / scripts / syms_export.py
1 import subprocess
2 import math
3 import re
4
5 sym_line = re.compile(r"^(?P<addr>[0-9a-f]+)\s[a-z]\s+F\s+\.[a-z._]+\s+[0-9a-f]+(?P<label>.+)$")
6
7 def main(kbin, sym_out, endianness='little', bits=32, just_print=False):
8     assert bits >= 32
9     assert (1 << int(math.log2(bits))) == bits
10
11     b_len = bits // 8
12     result = subprocess.run(["objdump", "--syms", kbin],stdout=subprocess.PIPE, stderr=subprocess.PIPE)
13     if result.returncode != 0:
14         print(result.stderr)
15         return
16     
17     def to_native(val: int):
18         return val.to_bytes(b_len, endianness, signed=False)
19     
20     output = result.stdout.split(b'\n')
21     functions = []
22     for l in output:
23         l = l.decode("ascii")
24         if not l:
25             continue
26         
27         mo = sym_line.match(l)
28         if not mo:
29             continue
30
31         mg = mo.groupdict()
32         addr = int(mg["addr"], 16)
33         label = mg["label"].strip() + '\0'
34
35         functions.append((addr, label))
36
37     functions = sorted(functions, key=lambda x: x[0])
38
39     if just_print:
40         for (a, l) in functions:
41             print(hex(a), ":", l)
42         return
43     
44     # struct {
45     #   ptr_t addr;
46     #   unsigned int label_off;
47     # }
48     sym_struct_sz = b_len * 2
49     meta_struct_sz = 4 * 2
50     label_off_base = sym_struct_sz * len(functions) + meta_struct_sz
51     alignment = bytearray([b'\0' for _ in range(b_len - 4)])
52
53     label_off = 0
54     bmask = b_len - 1   
55     text_region = bytearray()
56     null = bytearray(b'\0')
57     with open(sym_out, mode='wb') as f:
58         # struct {
59         #   unsigned int num_entry;
60         #   unsigned int label_off_base;
61         # }
62         f.write(to_native(len(functions)))
63         f.write(to_native(label_off_base))
64
65         for a, l in functions:
66             f.write(to_native(a))
67             f.write(to_native(label_off))
68             f.write(alignment)
69             
70             text_region += bytes(l, 'ascii')
71             aligned_len = (len(l) + bmask) & ~bmask
72             for i in range(aligned_len - len(l)):
73                 text_region.append(null[0])
74
75             label_off += aligned_len
76         
77         f.write(text_region)
78
79 import argparse
80 import sys
81 if __name__ == "__main__":
82     parser = argparse.ArgumentParser()
83     parser.add_argument('elf_exec')
84     parser.add_argument('-o', '--outfile', required=True)
85     parser.add_argument('--bits', default=32)
86     parser.add_argument('--order', default='little')
87     parser.add_argument('-p', '--just-print', action='store_true')
88
89     args = parser.parse_args()
90
91     main(args.elf_exec, args.outfile, endianness=args.order, bits=int(args.bits), just_print=args.just_print)
92