summaryrefslogtreecommitdiff
path: root/tools/unnamed.py
diff options
context:
space:
mode:
authormid-kid <esteve.varela@gmail.com>2019-01-01 00:28:51 +0100
committermid-kid <esteve.varela@gmail.com>2019-01-01 00:28:51 +0100
commit3b97a15ea30b6ce8ed25828be364fb0418785af6 (patch)
tree8bf594feeb2748e34ae18fdfaf2c39f7af7aa0d8 /tools/unnamed.py
parent930d285fab94fde5e061efa80dc41d478f19fcff (diff)
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.
Diffstat (limited to 'tools/unnamed.py')
-rwxr-xr-xtools/unnamed.py94
1 files changed, 94 insertions, 0 deletions
diff --git a/tools/unnamed.py b/tools/unnamed.py
new file mode 100755
index 000000000..205e1efd5
--- /dev/null
+++ b/tools/unnamed.py
@@ -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]))