papermario/tools/add_to_symbol_addrs.py

151 lines
4.2 KiB
Python
Raw Normal View History

2021-02-06 16:37:43 +01:00
#!/usr/bin/python3
import os
import re
2021-02-09 18:45:46 +01:00
import subprocess
import sys
2021-02-06 16:37:43 +01:00
script_dir = os.path.dirname(os.path.realpath(__file__))
root_dir = script_dir + "/../"
asm_dir = root_dir + "asm/nonmatchings/"
2021-02-09 18:45:46 +01:00
symbol_addrs_path = os.path.join(script_dir, "symbol_addrs.txt")
elf_path = os.path.join(root_dir, "build", "papermario.elf")
map_path = os.path.join(root_dir, "build", "papermario.map")
2021-02-06 16:37:43 +01:00
2021-02-09 18:45:46 +01:00
map_symbols = {}
symbol_addrs = []
elf_symbols = []
2021-02-06 16:37:43 +01:00
2021-02-09 18:45:46 +01:00
def scan_map():
ram_offset = None
cur_file = "<no file>"
prev_line = ""
with open(map_path) as f:
for line in f:
if "load address" in line:
ram = int(line[16 : 16 + 18], 0)
rom = int(line[59 : 59 + 18], 0)
ram_offset = ram - rom
continue
prev_line = line
2021-02-06 16:37:43 +01:00
2021-02-09 18:45:46 +01:00
if (
ram_offset is None
or "=" in line
or "*fill*" in line
or " 0x" not in line
):
continue
2021-02-06 16:37:43 +01:00
2021-02-09 18:45:46 +01:00
ram = int(line[16 : 16 + 18], 0)
rom = ram - ram_offset
sym = line.split()[-1]
if "0x" in sym:
ram_offset = None
continue
elif "/" in sym:
cur_file = sym
continue
2021-02-06 16:37:43 +01:00
2021-02-09 18:45:46 +01:00
map_symbols[sym] = (rom, cur_file, ram)
2021-02-06 16:37:43 +01:00
2021-02-09 18:45:46 +01:00
def read_symbol_addrs():
unique_lines = set()
2021-02-06 16:37:43 +01:00
2021-02-09 18:45:46 +01:00
with open(symbol_addrs_path, "r") as f:
for line in f.readlines():
unique_lines.add(line)
2021-02-06 16:37:43 +01:00
2021-02-09 18:45:46 +01:00
for line in unique_lines:
main, ext = line.rstrip().split(";")
args = ext.split("//")[-1].strip().split(" ")
name, addr = main.split(" = ")
symbol_addrs.append((name, int(addr, 0), args))
2021-02-06 16:37:43 +01:00
2021-02-09 18:45:46 +01:00
def read_elf():
try:
result = subprocess.run(['objdump', '-x', elf_path], stdout=subprocess.PIPE)
objdump_lines = result.stdout.decode().split("\n")
except:
print(f"Error: Could not run objdump on {elf_path} - make sure that the project is built")
sys.exit(1)
2021-02-09 11:39:22 +01:00
2021-02-09 18:45:46 +01:00
for line in objdump_lines:
if " F " in line or " O " in line or " *ABS*" in line:
components = line.split()
name = components[-1]
2021-02-09 11:39:22 +01:00
2021-02-09 18:45:46 +01:00
if "/" in name or \
name.startswith("_") or \
name.startswith("jtbl_") or \
re.match(r"L[0-9A-F]{8}", name):
2021-02-09 11:39:22 +01:00
continue
2021-02-09 18:45:46 +01:00
addr = int(components[0], 16)
if " F " in line:
type = "func"
else:
type = "data"
opts = [f"type:{type}"]
if name in map_symbols:
opts.append(f"rom:0x{map_symbols[name][0]:X}")
elif re.match(".*_[0-9A-F]{8}_[0-9A-F]{6}", name):
rom = name.split("_")[-1]
opts.append(f"rom:0x{rom}")
elf_symbols.append((name, addr, opts))
def reconcile_symbols():
print(f"Processing {str(len(elf_symbols))} elf symbols...")
for i, sym in enumerate(elf_symbols):
if i % 1000 == 0:
print(i)
name_match = None
rom_match = None
for sym2 in symbol_addrs:
# Name
if not name_match:
if sym[0] == sym2[0]:
name_match = sym2
if sym[1] != sym2[1]:
print(f"Address mismatch! {sym[0]} is 0x{sym[1]:X} in the elf and 0x{sym2[1]} in symbol_addrs")
if not rom_match:
if sym[2] == sym2[2]:
rom_match = sym2
# Rom
if not rom_match:
# Todo account for either or both syms not containing a rom addr
if sym[2] == sym2[2]:
rom_match = sym2
if not name_match:
if sym[0] == sym2[1]:
name_match = sym2
if not name_match and not rom_match:
# Todo add new symbol to symbol_addrs
pass
elif not name_match:
#todo rename symbol in symbol_addrs
pass
elif not rom_match:
# todo add rom addr in symbol_addrs
pass
scan_map()
read_symbol_addrs()
read_elf()
reconcile_symbols()