1
+ #!/usr/bin/env python3
2
+ import argparse
3
+ import sys
4
+ import struct
5
+
6
+ START_MAKER = b"__SYMBOL_TABLE_START__"
7
+ END_MAKER = b"__SYMBOL_TABLE_END__"
8
+ SYMBOL_TABLE_MAGIC = 0xbeefbeef
9
+ SYMBOL_MAX_LEN = 55
10
+
11
+
12
+ def main ():
13
+ parser = argparse .ArgumentParser ()
14
+ parser .add_argument ("symbols_file" )
15
+ parser .add_argument ("executable" )
16
+ args = parser .parse_args ()
17
+
18
+ # Locate the symbol table in the executable.
19
+ image = open (args .executable , "rb" ).read ()
20
+ offset = image .find (START_MAKER )
21
+ offset_end = image .find (END_MAKER )
22
+ if offset < 0 or offset_end < 0 :
23
+ sys .exit ("embed-symbol-table.py: failed to locate the symbol table" )
24
+ if image .find (START_MAKER , offset + 1 ) >= 0 :
25
+ print (hex (offset ), hex (image .find (START_MAKER , offset + 1 )))
26
+ sys .exit (
27
+ "embed-symbol-table.py: found multiple empty symbol tables (perhaps because "
28
+ + "START_MAKER is not sufficiently long to be unique?)" )
29
+
30
+ # Parse the nm output and extract symbol names and theier addresses.
31
+ symbols = {}
32
+ for line in open (args .symbols_file ).read ().strip ().split ("\n " ):
33
+ cols = line .split (" " , 1 )
34
+ try :
35
+ addr = int (cols [0 ], 16 )
36
+ except ValueError :
37
+ continue
38
+ name = cols [1 ]
39
+ symbols [addr ] = name
40
+
41
+ symbols = sorted (symbols .items (), key = lambda s : s [0 ])
42
+
43
+ # Build a symbol table.
44
+ symbol_table = struct .pack ("<IIQ" , SYMBOL_TABLE_MAGIC , len (symbols ), 0 )
45
+ for addr , name in symbols :
46
+ if len (name ) <= SYMBOL_MAX_LEN :
47
+ truncated_name = name [:55 ]
48
+ else :
49
+ prefix_len = SYMBOL_MAX_LEN // 2
50
+ suffix_len = SYMBOL_MAX_LEN - len ("..." ) - prefix_len
51
+ truncated_name = name [:prefix_len ] + "..." + name [- suffix_len :]
52
+ assert len (truncated_name ) == SYMBOL_MAX_LEN
53
+ symbol_table += struct .pack ("<Q56s" , addr ,
54
+ bytes (truncated_name , "ascii" ))
55
+
56
+ max_size = offset_end - offset
57
+ if len (symbol_table ) > max_size :
58
+ sys .exit (
59
+ f"embed-symbol-table.py: Too many symbols; please expand the symbol table area (max_size={ max_size / 1024 } KiB, created={ len (symbol_table ) / 1024 } KiB)"
60
+ )
61
+
62
+ # Embed the symbol table.
63
+ image = image [:offset ] + symbol_table + image [offset + len (symbol_table ):]
64
+ open (args .executable , "wb" ).write (image )
65
+
66
+
67
+ if __name__ == "__main__" :
68
+ main ()
0 commit comments