diff --git a/unusedsymbols.py b/unusedsymbols.py new file mode 100755 index 0000000..ea250e4 --- /dev/null +++ b/unusedsymbols.py @@ -0,0 +1,259 @@ +#!/usr/bin/env python3 +# vim:set tabstop=4 shiftwidth=4 expandtab smarttab + +from sys import argv, exit, stderr +from struct import unpack, calcsize +from enum import Enum + +class nodetype(Enum): + REPT = 0 + FILE = 1 + MACRO = 2 + +class symtype(Enum): + LOCAL = 0 + IMPORT = 1 + EXPORT = 2 + +class sectype(Enum): + WRAM0 = 0 + VRAM = 1 + ROMX = 2 + ROM0 = 3 + HRAM = 4 + WRAMX = 5 + SRAM = 6 + OAM = 7 + +class patchtype(Enum): + BYTE = 0 + WORD = 1 + LONG = 2 + JR = 3 + +class asserttype(Enum): + WARN = 0 + ERROR = 1 + FAIL = 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 + +def parse_object(filename): + file = open(filename, "rb") + + obj = { + "nodes": [], + "symbols": [], + "sections": [], + "assertions": [], + } + + magic = unpack_file("4s", file)[0] + if magic == b'RGB6': + obj_ver = 6 + elif magic == b'RGB9': + obj_ver = 10 + unpack_file("= 16: + num_nodes = unpack_file("= 16: + node = unpack_file("= 14: + section["align"], section["offset"] = unpack_file("= 16: + node = unpack_file("= 16: + patch["line"] = unpack_file("= 14: + patch["pcsectionid"], patch["pcoffset"] = unpack_file("= 13: + num_assertions = unpack_file("= 16: + node = unpack_file("= 14: + assertion["section"], assertion["pcoffset"] = unpack_file("" % argv[0], file=stderr) + exit(1) + +argi = 1 + +just_dump = False +if argv[argi] == "-D": + just_dump = True + argi += 1 +if argv[argi] == "--": + argi += 1 + +globalsyms = {} + +for filename in argv[argi:]: + print(filename, file=stderr) + + obj = parse_object(filename) + if obj is None: + exit(1) + + if just_dump: + for symbol in obj["symbols"]: + print(symbol["name"]) + continue + + localsyms = {} + + imports = 0 + exports = 0 + for symbol in obj["symbols"]: + if symbol["type"] == symtype.LOCAL: + if symbol["name"] not in localsyms: + localsyms[symbol["name"]] = 0 + elif symbol["type"] == symtype.IMPORT: + imports += 1 + if symbol["name"] not in globalsyms: + globalsyms[symbol["name"]] = 0 + elif symbol["type"] == symtype.EXPORT: + exports += 1 + if symbol["name"] not in globalsyms: + globalsyms[symbol["name"]] = 0 + + print("Locals:", len(localsyms), file=stderr) + print("Imports:", imports, file=stderr) + print("Exports:", exports, file=stderr) + + def parse_rpn(rpn): + pos = 0 + while pos < len(rpn): + if rpn[pos] == 0x51: + pos += 1 + while rpn[pos] != 0: + pos += 1 + pos += 1 + elif rpn[pos] == 0x80: + pos += 5 + elif rpn[pos] == 0x50 or rpn[pos] == 0x81: + symbol_id = unpack("