summaryrefslogtreecommitdiff
path: root/tools/unnamed.py
diff options
context:
space:
mode:
authorentrpntr <entrpntr@gmail.com>2020-04-06 14:28:33 -0400
committerentrpntr <entrpntr@gmail.com>2020-04-06 14:48:14 -0400
commit07a5cc60d0c3e37699ad5e45366cb9b093d6b7e7 (patch)
treed24dd2f6ac9f79f3247415d136b290a17766df3a /tools/unnamed.py
parentd46fcef6bc2c8054f873d238e020d43b6f1774f2 (diff)
Add unnamed.py and update for rgbds v0.4.x before continuing.
Diffstat (limited to 'tools/unnamed.py')
-rwxr-xr-xtools/unnamed.py114
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]))