Files
jsix_import/scripts/build_symbol_table.py
Justin C. Miller 8966380ef9 [build] Warn on zero-length symbols when building symbol table
Make build_symbol_table.py output statistics on the symbol table it
builds, and emit warnings for zero-length symbols. Also added lengths to
several functions defined in asm that this uncovered.
2023-02-06 00:37:26 -08:00

87 lines
2.2 KiB
Python
Executable File

#!/usr/bin/env python3
#
# Generate the jsix style symbol table. The format in memory of this table
# is as follows:
#
# <num_entires> : 8 bytes
# <index> : 24 * N bytes
# <name data> : variable
#
# Each index entry has the format
# <symbol address> : 8 bytes
# <symbol size> : 8 bytes
# <offset of name> : 8 bytes
#
# Name offsets are from the start of the symbol table as a whole. (ie,
# where <num_entries> is located.)
import re
sym_re = re.compile(r'([0-9a-fA-F]{16}) ([0-9a-fA-F]{16} )?[tTvVwW] (.*)')
def parse_syms(infile):
"""Take the output of the `nm` command, and parse it into a tuple
representing the symbols in the text segment of the binary. Returns
a list of (address, symbol_name)."""
syms = []
for line in sys.stdin:
match = sym_re.match(line)
if not match: continue
addr = int(match.group(1), base=16)
size = int(match.group(2) or "0", base=16)
name = match.group(3)
if size == 0:
if not "." in name:
print(f"SYMBOL WARNING: zero size for symbol {name}")
continue
syms.append([addr, size, name, 0])
return syms
def write_table(syms, outfile):
"""Write the given symbol table as generated by parse_syms()
to the outfile, index first, and then name character data."""
import struct
outfile.write(struct.pack("@Q", len(syms)))
index_pos = outfile.tell()
outfile.seek(struct.calcsize("@QQQ") * len(syms), 1)
nul = b'\0'
for s in syms:
s[3] = outfile.tell()
outfile.write(s[2].encode('utf-8'))
outfile.write(nul)
outfile.seek(index_pos)
for s in syms:
addr = s[0]
size = s[1]
pos = s[3]
outfile.write(struct.pack("@QQQ", addr, size, pos))
return len(syms)
if __name__ == "__main__":
import sys
if len(sys.argv) != 2:
print(f"Usage: nm -n -S --demangle | {sys.argv[0]} <output>")
sys.exit(1)
syms = 0
size = 0
with open(sys.argv[1], "wb") as outfile:
syms = write_table(parse_syms(sys.stdin), outfile)
outfile.seek(0, 2)
size = outfile.tell()
print(f"Wrote {syms} symbols ({size/1024:.1f} KiB) to {sys.argv[1]}.")