mirror of https://github.com/zeldaret/botw.git
63 lines
1.7 KiB
Python
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
|