mirror of
https://gitlab.com/xCrystal/pokecrystal-board.git
synced 2024-09-09 09:51:34 -07:00
Merge pull request #599 from mid-kid/master
Add tool to find unnamed symbols: Take 2
This commit is contained in:
commit
8577d78f4d
@ -23,3 +23,5 @@ before_script:
|
||||
script:
|
||||
- make -j2 compare
|
||||
- check_status
|
||||
after_success:
|
||||
- .travis/webhook.sh
|
||||
|
18
.travis/webhook.sh
Executable file
18
.travis/webhook.sh
Executable file
@ -0,0 +1,18 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Only run this script if it's the master branch build.
|
||||
[ "$TRAVIS_BRANCH" != 'master' -o "$TRAVIS_PULL_REQUEST" != 'false' ] && exit
|
||||
|
||||
root="$(realpath "$(dirname "$0")/..")"
|
||||
content=""
|
||||
|
||||
# Report unnamed symbols
|
||||
content+="$("$root/tools/unnamed.py" -r "$root" "$root/pokecrystal.sym" | grep -v -e '^lib/mobile/' -e '^mobile/' | head)"
|
||||
|
||||
curl -H 'Content-Type: application/json' -X POST "$POKECRYSTAL_DISCORD_WEBHOOK_URL" -d@- << EOF
|
||||
{
|
||||
"username": "$POKECRYSTAL_DISCORD_WEBHOOK_USERNAME",
|
||||
"avatar_url": "$POKECRYSTAL_DISCORD_WEBHOOK_AVATAR_URL",
|
||||
"content": "\`\`\`$(echo "$content" | sed -E ':a;N;$!ba;s/\r{0,1}\n/\\n/g')\`\`\`"
|
||||
}
|
||||
EOF
|
98
tools/unnamed.py
Executable file
98
tools/unnamed.py
Executable file
@ -0,0 +1,98 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
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=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 Popen(["make", "-C", args.rootdir, "-s", "-p"],
|
||||
stdout=PIPE).stdout.read().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_total = 0
|
||||
symbols = set()
|
||||
for line in args.symfile:
|
||||
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")
|
||||
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
Block a user