mirror of https://github.com/pret/pokecrystal.git
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:
parent
930d285fab
commit
3b97a15ea3
|
@ -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]))
|
Loading…
Reference in New Issue