Fix aglib reg_write to correctly handle writing to the "pc" register (#2539)

* Fix aglib reg_write to correctly handle writing to the "pc" register

* refactor pc/sp
pull/2738/head
patryk4815 10 months ago committed by GitHub
parent f85ac5e825
commit 3a41911390
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -13,7 +13,9 @@ from typing import Any
from typing import Callable from typing import Callable
from typing import Dict from typing import Dict
from typing import Generator from typing import Generator
from typing import Iterator
from typing import List from typing import List
from typing import Set
from typing import Tuple from typing import Tuple
from typing import cast from typing import cast
@ -127,7 +129,8 @@ class module(ModuleType):
if attr in ("last", "previous"): if attr in ("last", "previous"):
super().__setattr__(attr, val) super().__setattr__(attr, val)
else: else:
pwndbg.dbg.selected_frame().reg_write(attr, int(val)) if not pwndbg.dbg.selected_frame().reg_write(attr, int(val)):
raise RuntimeError(f"Attempted to write to a non-existent register '{attr}'")
@pwndbg.lib.cache.cache_until("stop", "prompt") @pwndbg.lib.cache.cache_until("stop", "prompt")
def __getitem__(self, item: Any) -> int | None: def __getitem__(self, item: Any) -> int | None:
@ -138,12 +141,10 @@ class module(ModuleType):
return self.read_reg(item) return self.read_reg(item)
def __contains__(self, reg: str) -> bool: def __contains__(self, reg: str) -> bool:
regs = set(reg_sets[pwndbg.aglib.arch.name]) | {"pc", "sp"} return reg_sets[pwndbg.aglib.arch.name].__contains__(reg)
return reg in regs
def __iter__(self) -> Generator[str, None, None]: def __iter__(self) -> Iterator[str]:
regs = set(reg_sets[pwndbg.aglib.arch.name]) | {"pc", "sp"} return reg_sets[pwndbg.aglib.arch.name].__iter__()
yield from regs
@property @property
def current(self) -> RegisterSet: def current(self) -> RegisterSet:
@ -183,31 +184,11 @@ class module(ModuleType):
return reg_sets[pwndbg.aglib.arch.name].retval return reg_sets[pwndbg.aglib.arch.name].retval
@property @property
def all(self) -> List[str]: def all(self) -> Set[str]:
regs = reg_sets[pwndbg.aglib.arch.name] return reg_sets[pwndbg.aglib.arch.name].all
retval: List[str] = []
for regset in (
regs.pc,
regs.stack,
regs.frame,
regs.retaddr,
regs.flags,
regs.gpr,
regs.misc,
):
if regset is None:
continue
if isinstance(regset, (list, tuple)): # regs.retaddr
retval.extend(regset)
elif isinstance(regset, dict): # regs.flags
retval.extend(regset.keys())
else:
retval.append(regset)
return retval
def fix(self, expression: str) -> str: def fix(self, expression: str) -> str:
for regname in set(self.all + ["sp", "pc"]): for regname in self.all:
expression = re.sub(rf"\$?\b{regname}\b", r"$" + regname, expression) expression = re.sub(rf"\$?\b{regname}\b", r"$" + regname, expression)
return expression return expression

@ -163,7 +163,7 @@ class GDBFrame(pwndbg.dbg_mod.Frame):
@override @override
def reg_write(self, name: str, val: int) -> bool: def reg_write(self, name: str, val: int) -> bool:
if name not in pwndbg.aglib.regs.all: if name not in pwndbg.aglib.regs:
return False return False
with selection(self.inner, lambda: gdb.selected_frame(), lambda f: f.select()): with selection(self.inner, lambda: gdb.selected_frame(), lambda f: f.select()):

@ -156,11 +156,16 @@ class LLDBFrame(pwndbg.dbg_mod.Frame):
if val < 0: if val < 0:
raise RuntimeError("Tried to write a register with a negative value") raise RuntimeError("Tried to write a register with a negative value")
if name not in pwndbg.aglib.regs:
return False
# Writing to the PC using the normal register write flow causes the # Writing to the PC using the normal register write flow causes the
# inner object to be automatically invalidated by LLDB, so we have to # inner object to be automatically invalidated by LLDB, so we have to
# handle jumps manually using SBFrame::SetPC. # handle jumps manually using SBFrame::SetPC.
if name.lower() == reg_sets[pwndbg.aglib.arch.name].pc: if name in (reg_sets[pwndbg.aglib.arch.name].pc, "pc"):
return self.inner.SetPC(val) ret = self.inner.SetPC(val)
self.proc.dbg._trigger_event(pwndbg.dbg_mod.EventType.REGISTER_CHANGED)
return ret
name = rename_register(name, self.proc) name = rename_register(name, self.proc)

@ -95,6 +95,10 @@ class RegisterSet:
self.all = set(misc) | set(flags) | set(extra_flags) | set(self.retaddr) | set(self.common) self.all = set(misc) | set(flags) | set(extra_flags) | set(self.retaddr) | set(self.common)
self.all -= {None} self.all -= {None}
self.all |= {"pc", "sp"}
def __contains__(self, reg: str) -> bool:
return reg in self.all
def __iter__(self) -> Iterator[str]: def __iter__(self) -> Iterator[str]:
yield from self.all yield from self.all

Loading…
Cancel
Save