Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def do_memory(self, addr: str, size: str, step: str) -> None:
"""Show an hex view of a region of ROM, starting from
ADDR and spanning SIZE bytes, in groups of STEP bytes."""
def build_header(step: int) -> str:
s = []
for n in range(0, (16 // step) * step, step):
s.append(f"{n:02X}")
s.append("")
return (" " * ((2 * step) - 1)).join(s)
addr_int = self._label_to_pc(addr)
size_int = int(size[1:] if size[0] == "$" else int(size))
step_int = int(step)
if step_int > 16:
raise GilgameshError("Can only build groups up to 16 bytes.")
s = []
header = build_header(step_int)
s += ["" + (" " * 8) + "│ "]
s += [header]
s += ["\n" + ("─" * 8) + "┼" + ("─" * len(header)) + "\n"]
colors, color_idx = ["lightgrey", "cyan"], 0
nl_threshold = (16 // step_int) * step_int
for i in range(addr_int, addr_int + size_int, step_int):
if (i - addr_int) % nl_threshold == 0:
if i - addr_int:
s.append("\n")
s.append("${:06X} │ ".format(i))
def do_edit(self) -> None:
"""Interactively edit the subroutine(s) using an external editor."""
if not self.subroutine:
raise GilgameshError("No selected subroutine.")
disassembly = SubroutineDisassembly(self.subroutine)
disassembly.edit()
if self.log.dirty:
self.do_analyze()
def _label_to_pc(self, label_or_pc: str) -> int:
if label_or_pc.startswith("$"):
try:
pc = sum(int(x, 16) for x in label_or_pc[1:].split("+"))
except ValueError:
raise GilgameshError("Provided value is not a label or an address.")
try:
self.rom._translate(pc)
except ValueError:
raise GilgameshError("The given PC is not valid for this ROM.")
return pc
label_pc = self.log.get_label_value(label_or_pc, self.subroutine)
if label_pc is None:
raise GilgameshError("Unknown label.")
return label_pc
def _rename_local_label(
self, old: str, new: str, subroutine_pc: int, dry=False
) -> None:
local_labels = self.local_labels[subroutine_pc]
pc = local_labels.get(old, None)
if pc is None:
raise GilgameshError(f'Unknown local label: "{old}".')
if new in local_labels:
raise GilgameshError("The provided label is already in use.")
if not new.isidentifier():
raise GilgameshError("The provided label is not a valid identifier.")
if new.startswith("sub_") or new.startswith("loc_") or new in hw_registers:
raise GilgameshError("The provided label is reserved.")
if not dry:
del local_labels[old]
local_labels[new] = pc
def _rename_local_label(
self, old: str, new: str, subroutine_pc: int, dry=False
) -> None:
local_labels = self.local_labels[subroutine_pc]
pc = local_labels.get(old, None)
if pc is None:
raise GilgameshError(f'Unknown local label: "{old}".')
if new in local_labels:
raise GilgameshError("The provided label is already in use.")
if not new.isidentifier():
raise GilgameshError("The provided label is not a valid identifier.")
if new.startswith("sub_") or new.startswith("loc_") or new in hw_registers:
raise GilgameshError("The provided label is reserved.")
if not dry:
del local_labels[old]
local_labels[new] = pc
if address & 0x800000:
pc = ((address & 0x7F0000) >> 1) | (address & 0x7FFF)
else:
pc = (((address & 0x7F0000) >> 1) | (address & 0x7FFF)) + 0x400000
elif self.type == ROMType.HiROM:
pc = address & 0x3FFFFF
elif self.type == ROMType.ExHiROM:
if (address & 0xC00000) != 0xC00000:
pc = (address & 0x3FFFFF) | 0x400000
else:
pc = address & 0x3FFFFF
if address > 0xFFFFFF or pc >= self.real_size:
raise GilgameshError(f"Invalid address: ${address:X}.")
return pc
def _rename_subroutine(self, old: str, new: str, dry=False) -> None:
subroutine = self.subroutines_by_label.get(old, None)
if subroutine is None:
raise GilgameshError(f'Unknown subroutine label: "{old}".')
if new in self.subroutines_by_label:
raise GilgameshError("The provided label is already in use.")
if not new.isidentifier():
raise GilgameshError("The provided label is not a valid identifier.")
if new.startswith("sub_") or new.startswith("loc_") or new in hw_registers:
raise GilgameshError("The provided label is reserved.")
if not dry:
del self.subroutines_by_label[old]
subroutine.label = new
self.subroutines_by_label[new] = subroutine
def add_entry_point(self, pc: int, name: str, state: State):
if (pc in self.entry_points) or (pc in self.instructions):
raise GilgameshError("This address is already covered by the analysis.")
self.entry_points[pc] = EntryPoint(name, state.p)
self.dirty = True
def _rename_subroutine(self, old: str, new: str, dry=False) -> None:
subroutine = self.subroutines_by_label.get(old, None)
if subroutine is None:
raise GilgameshError(f'Unknown subroutine label: "{old}".')
if new in self.subroutines_by_label:
raise GilgameshError("The provided label is already in use.")
if not new.isidentifier():
raise GilgameshError("The provided label is not a valid identifier.")
if new.startswith("sub_") or new.startswith("loc_") or new in hw_registers:
raise GilgameshError("The provided label is reserved.")
if not dry:
del self.subroutines_by_label[old]
subroutine.label = new
self.subroutines_by_label[new] = subroutine
def any_instruction(self, instr_pc: int) -> Instruction:
subroutines = self.instruction_subroutines(instr_pc)
if not subroutines:
raise GilgameshError("No instruction at the given address.")
return subroutines[0].instructions[instr_pc]