Add tool to find unnamed symbols

This tool should help us identify which are the symbols that still need
proper names, and in which files they're located.
This commit is contained in:
mid-kid 2019-01-01 00:28:51 +01:00
parent 930d285fab
commit 3b97a15ea3

94
tools/unnamed.py Executable file
View File

@ -0,0 +1,94 @@
#!/usr/bin/env python3
from sys import stderr, exit
from subprocess import run
from struct import unpack, calcsize
from enum import Enum
class symtype(Enum):
LOCAL = 0
IMPORT = 1
EXPORT = 2
def unpack_file(fmt, file):
size = calcsize(fmt)
return unpack(fmt, file.read(size))
def read_string(file):
buf = bytearray()
while True:
b = file.read(1)
if b is None or b == b'\0':
return buf.decode()
else:
buf += b
# Fix broken pipe when using `head`
from signal import signal, SIGPIPE, SIG_DFL
signal(SIGPIPE,SIG_DFL)
import argparse
parser = argparse.ArgumentParser(description="Parse the symfile to find unnamed symbols")
parser.add_argument('symfile', type=argparse.FileType('r'), help="the list of symbols")
parser.add_argument('-r', '--rootdir', type=str, help="scan the output files to obtain a list of files with unnamed symbols (NOTE: will rebuild objects as necessary)")
args = parser.parse_args()
# Get list of object files
objects = None
if args.rootdir:
for line in run(["make", "-C", args.rootdir, "-s", "-p"],
capture_output=True).stdout.decode().split("\n"):
if line.startswith("crystal_obj := "):
objects = line[15:].strip().split()
break
else:
print("Error: Object files not found!", file=stderr)
exit(1)
# Scan all unnamed symbols from the symfile
symbols = set()
for line in args.symfile:
line = line.split(";")[0].strip()
split = line.split(" ")
if len(split) < 2:
continue
symbol = " ".join(split[1:]).strip()
if symbol[-3:].lower() == split[0][-3:].lower():
symbols.add(symbol)
# If no object files were provided, just print what we know and exit
print("Unnamed symbols: %d" % len(symbols))
if not objects:
for sym in symbols:
print(sym)
exit()
# Count the amount of symbols in each file
files = {}
for objfile in objects:
f = open(objfile, "rb")
if unpack_file("4s", f)[0] != b'RGB6':
print("Error: File '%s' is of an unknown format." % filename, file=stderr)
exit(1)
num_symbols = unpack_file("<II", f)[0]
for x in range(num_symbols):
sym_name = read_string(f)
sym_type = symtype(unpack_file("<B", f)[0])
if sym_type == symtype.IMPORT:
continue
sym_filename = read_string(f)
unpack_file("<III", f)
if sym_name not in symbols:
continue
if sym_filename not in files:
files[sym_filename] = 0
files[sym_filename] += 1
# Sort the files, the one with the most amount of symbols first
files = sorted([(fname, files[fname]) for fname in files], key=lambda x: x[1], reverse=True)
for f in files:
print("%s: %d" % (f[0], f[1]))