papermario/tools/splat/util/relocs.py
HailSanta 6c606383e8
nok and pra done (#936)
* nok_04 ok

* thread done

* push block doc

* nok done

* almost done pra

* pra done

* cleanup pra_31 mtx names

* git subrepo pull --force tools/splat

subrepo:
  subdir:   "tools/splat"
  merged:   "3bbc02af68"
upstream:
  origin:   "https://github.com/ethteck/splat.git"
  branch:   "master"
  commit:   "3bbc02af68"
git-subrepo:
  version:  "0.4.5"
  origin:   "???"
  commit:   "???"

---------

Co-authored-by: HailSanta <Hail2Santa@gmail.com>
2023-02-08 09:47:26 +09:00

126 lines
3.9 KiB
Python

from dataclasses import dataclass
from typing import Dict
import spimdisasm
import tqdm
from intervaltree import Interval, IntervalTree
from util import log, options, symbols
@dataclass
class Reloc:
rom_address: int
reloc_type: str
symbol_name: str
addend: int = 0
all_relocs: Dict[int, Reloc] = {}
def add_reloc(reloc: Reloc):
all_relocs[reloc.rom_address] = reloc
def initialize():
global all_relocs
all_relocs = {}
for path in options.opts.reloc_addrs_paths:
if not path.exists():
continue
with path.open() as f:
sym_addrs_lines = f.readlines()
for line_num, line in enumerate(
tqdm.tqdm(sym_addrs_lines, desc=f"Loading relocs ({path.stem})")
):
line = line.strip()
# Allow comments
line = line.split("//")[0]
line = line.strip()
if line == "":
continue
rom_addr = None
reloc_type = None
symbol_name = None
addend = None
for info in line.split(" "):
if ":" not in info:
continue
if info.count(":") > 1:
log.parsing_error_preamble(path, line_num, line)
log.write(f"Too many ':'s in '{info}'")
log.error("")
attr_name, attr_val = info.split(":")
if attr_name == "":
log.parsing_error_preamble(path, line_num, line)
log.write(
f"Missing attribute name in '{info}', is there extra whitespace?"
)
log.error("")
if attr_val == "":
log.parsing_error_preamble(path, line_num, line)
log.write(
f"Missing attribute value in '{info}', is there extra whitespace?"
)
log.error("")
# Non-Boolean attributes
try:
if attr_name == "rom":
rom_addr = int(attr_val, 0)
continue
if attr_name == "reloc":
reloc_type = attr_val
continue
if attr_name == "symbol":
symbol_name = attr_val
continue
if attr_name == "addend":
addend = int(attr_val, 0)
continue
except:
log.parsing_error_preamble(path, line_num, line)
log.write(f"value of attribute '{attr_name}' could not be read:")
log.write("")
raise
if rom_addr is None:
log.parsing_error_preamble(path, line_num, line)
log.error(f"Missing required 'rom' attribute for reloc")
if reloc_type is None:
log.parsing_error_preamble(path, line_num, line)
log.error(f"Missing required 'reloc' attribute for reloc")
if symbol_name is None:
log.parsing_error_preamble(path, line_num, line)
log.error(f"Missing required 'symbol' attribute for reloc")
reloc = Reloc(rom_addr, reloc_type, symbol_name)
if addend is not None:
reloc.addend = addend
add_reloc(reloc)
def initialize_spim_context():
for rom_address, reloc in all_relocs.items():
reloc_type = spimdisasm.common.RelocType.fromStr(reloc.reloc_type)
if reloc_type is None:
log.error(
f"Reloc type '{reloc.reloc_type}' is not valid. Rom address: 0x{rom_address:X}"
)
symbols.spim_context.addGlobalReloc(
rom_address, reloc_type, reloc.symbol_name, addend=reloc.addend
)