papermario/tools/find_bogus_functions.py
2020-08-12 21:56:23 -04:00

120 lines
3.3 KiB
Python
Executable File

#!/usr/bin/python3
import os
import re
script_dir = os.path.dirname(os.path.realpath(__file__))
asm_dir = script_dir + "/../asm/"
js = set()
jals = set()
bs = set()
bals = set()
debug = False
renames = []
def dprint(string):
if debug:
print(string)
def scan_file(path):
with open(path) as f:
file_lines = f.readlines()
for line in file_lines:
line = line.strip()
if re.findall(r'\sj\s+.*', line):
target = line.split()[-1]
js.add(target)
if re.findall(r'\sjal\s+.*', line):
target = line.split()[-1]
jals.add(target)
if re.findall(r'\sb.*', line):
target = line.split()[-1]
bs.add(target)
if re.findall(r'\sbal\s+.*', line):
target = line.split()[-1]
bals.add(target)
def get_linked_flags(label):
return (label in js or label in bs), (label in jals or label in bals)
def process_file(path):
print("Processing " + path)
with open(path) as fi:
file_lines = fi.readlines()
skip_next = False
to_delete = []
for i, line in enumerate(file_lines):
if skip_next:
skip_next = False
continue
line = line.strip()
if line.endswith(":") and not line.startswith(".L"):
func_preamble = line.startswith("func_")
label = line[:-1]
linked_to, linked_al_to = get_linked_flags(label)
if func_preamble:
# func_12345689
# Delete redundant label below
# if file_lines[i + 1].strip() == ".L" + label[5:13] + ":":
# to_delete.append(i + 1)
# skip_next = True
if linked_al_to:
# Seems to be legit. Do nothing for now
continue
elif linked_to:
# j / b 'd to, rename as label
renames.append((label, ".L" + label[5:]))
else:
# Not referenced by anything. Delete
to_delete.append(i)
if len(to_delete) > 0:
print("\tDeleting " + str(len(to_delete)) + " lines...")
for i in reversed(to_delete):
del file_lines[i]
with open(path, "w") as fo:
fo.writelines(file_lines)
# Collect all branches and jumps
for root, dirs, files in os.walk(asm_dir):
for file in files:
if file.endswith(".s"):
scan_file(os.path.join(root, file))
print("Scanned all files")
# Process files
for root, dirs, files in os.walk(asm_dir):
for file in files:
if file.endswith(".s") and "boot" not in file:
process_file(os.path.join(root, file))
if len(renames) > 0:
print("Renaming " + str(len(renames)) + " labels...")
for root, dirs, files in os.walk(asm_dir):
for file in files:
if file.endswith(".s"):
file_path = os.path.join(root, file)
with open(file_path) as f:
orig_file_text = f.read()
file_text = orig_file_text
for rename in renames:
file_text = file_text.replace(rename[0], rename[1])
if file_text != orig_file_text:
with open(file_path, "w") as f:
f.write(file_text)