mirror of
https://github.com/justinian/jsix.git
synced 2025-12-10 00:14:32 -08:00
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.
87 lines
2.2 KiB
Python
Executable File
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]}.")
|