diff options
author | entrpntr <entrpntr@gmail.com> | 2020-04-06 14:28:33 -0400 |
---|---|---|
committer | entrpntr <entrpntr@gmail.com> | 2020-04-06 14:48:14 -0400 |
commit | 07a5cc60d0c3e37699ad5e45366cb9b093d6b7e7 (patch) | |
tree | d24dd2f6ac9f79f3247415d136b290a17766df3a /tools/unnamed.py | |
parent | d46fcef6bc2c8054f873d238e020d43b6f1774f2 (diff) |
Add unnamed.py and update for rgbds v0.4.x before continuing.
Diffstat (limited to 'tools/unnamed.py')
-rwxr-xr-x | tools/unnamed.py | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/tools/unnamed.py b/tools/unnamed.py new file mode 100755 index 00000000..1c66a36d --- /dev/null +++ b/tools/unnamed.py @@ -0,0 +1,114 @@ +#!/usr/bin/env python3 + +import os, re +from sys import stderr, exit +from subprocess import Popen, PIPE +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=str, help="the filename with 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 +obj_suffix = '_obj := ' +m = re.match('poke(.*)\.sym', args.symfile) +sym_game = m.group(1) +def match_obj(game, line): + return (sym_game == game) and line.startswith(game + obj_suffix) +if args.rootdir: + for line in Popen(["make", "-C", args.rootdir, "-s", "-p"], + stdout=PIPE).stdout.read().decode().split("\n"): + if match_obj('gold', line) or match_obj('silver', line): + offset = len(sym_game) + len(obj_suffix) + objects = line[offset:].strip().split() + break + + else: + print("Error: Object files not found!", file=stderr) + exit(1) + +# Scan all unnamed symbols from the symfile +symbols_total = 0 +symbols = set() +for line in open(args.symfile, 'r'): + line = line.split(";")[0].strip() + split = line.split(" ") + if len(split) < 2: + continue + + symbols_total += 1 + + 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 (%.2f%% complete)" % (len(symbols), + (symbols_total - len(symbols)) / symbols_total * 100)) +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") + obj_ver = None + + magic = unpack_file("4s", f)[0] + if magic == b'RGB6': + obj_ver = 6 + elif magic == b'RGB9': + obj_ver = 10 + unpack_file("<I", f)[0] + + if obj_ver not in [6, 10, 11, 12, 13]: + print("Error: File '%s' is of an unknown format." % objfile, 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] & 0x7f) + 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])) |