botw/tools/util/dsym.py

63 lines
1.7 KiB
Python

import csv
from pathlib import Path
import typing as tp
import util.elf
class DataSymbol(tp.NamedTuple):
addr: int # without the 0x7100000000 base
name: str
size: int
_IDA_BASE = 0x7100000000
class DataSymbolContainer:
def __init__(self) -> None:
self.symbols: tp.List[DataSymbol] = []
def load_from_csv(self, path: Path):
symtab = util.elf.build_name_to_symbol_table(util.elf.my_symtab)
with path.open("r") as f:
for i, line in enumerate(csv.reader(f)):
if len(line) != 2:
raise RuntimeError(f"Invalid line format at line {i}")
addr = int(line[0], 16) - _IDA_BASE
name = line[1]
if name not in symtab:
continue
size = symtab[name].size
self.symbols.append(DataSymbol(addr, name, size))
# Sort the list, just in case the entries were not sorted in the CSV.
self.symbols.sort(key=lambda sym: sym.addr)
def get_symbol(self, addr: int) -> tp.Optional[DataSymbol]:
"""If addr is part of a known data symbol, this function returns the corresponding symbol."""
# Perform a binary search on self.symbols.
a = 0
b = len(self.symbols) - 1
while a <= b:
m = (a + b) // 2
symbol: DataSymbol = self.symbols[m]
addr_begin = symbol.addr
addr_end = addr_begin + symbol.size
if addr_begin <= addr < addr_end:
return symbol
if addr <= addr_begin:
b = m - 1
elif addr >= addr_end:
a = m + 1
else:
return None
return None