Files
pancake 2c19d6c9dc Ported the remaining classes to use the command builder and _exec:
- Search: string/wide/case-insensitive/Rabin-Karp/JSON searches now use _cmd_arg so patterns with spaces/special chars are safe.
- Flags: removed leftover manual _tmp_off = "" cleanups (now automatic).
- Debugger: added _tmp_addr() helper, removed manual _tmp_off cleanup.
- Esil: ESIL expressions use _cmd_arg; EsilCPU.registers() returns {} on failure; emulateInstr resolves symbol names to numeric
addresses because aesp doesn't accept symbols.
- Config: cleaned up old-style super() and % formatting; config set now uses key=value.
- File: minor __getattr__ cleanup.
- IOMap: setName uses _cmd_arg for arbitrary map names.
- R2Api / Function: af, afn, afn., p8, aoj, axtj now rely on automatic _tmp_off handling; removed duplicated open/files definitions.
2026-08-28 17:05:58 +02:00

104 lines
2.7 KiB
Python

from r2papi.base import R2Base, ResultArray
class CPU(R2Base):
def __init__(self, r2):
super().__init__(r2)
def readRegister(self, reg_name):
res = self._exec_quiet("drj", json=True)
if res is None:
return None
return res.get(reg_name)
def writeRegister(self, reg_name, value):
res = self._exec_quiet(f"dr {reg_name}={value}")
if res is None or res == "":
raise ValueError(f"Invalid register {reg_name}")
def registers(self):
return self._exec_quiet("drj", json=True) or {}
def __str__(self):
regs = self.registers()
if not regs:
return ""
ret_str = ""
for r, v in regs.items():
if isinstance(v, int):
ret_str += f"{r:<10}{v:#016x}\n"
else:
ret_str += f"{r:<10}{v}\n"
return ret_str
def __getattr__(self, attr):
if attr in self.registers().keys():
return self.readRegister(attr)
def __setattr__(self, attr, value):
if attr in ("r2", "_tmp_off"):
self.__dict__[attr] = value
elif attr in self.registers().keys():
self.writeRegister(attr, value)
else:
self.__dict__[attr] = value
class Debugger(R2Base):
def __init__(self, r2):
super().__init__(r2)
self.cpu = CPU(r2)
self._untilCall = False
self._untilUnknownCall = False
self._untilRet = False
self.listBreakpoints = lambda: ResultArray(self._exec("dbj", json=True))
self.step = lambda: self._exec("ds")
self.memoryMaps = lambda: ResultArray(self._exec("dmj", json=True))
self.backtrace = lambda: self._exec("dbtj", json=True)
def start(self):
self._exec("doo")
def cont(self):
if self._untilCall:
self._exec("dcc")
elif self._untilUnknownCall:
self._exec("dccu")
elif self._untilRet:
self._exec("dcr")
else:
self._exec("dc")
self._untilCall = False
self._untilRet = False
self._untilUnknownCall = False
def untilCall(self):
self._untilCall = True
return self
def untilRet(self):
self._untilRet = True
return self
def untilUnknownCall(self):
self._untilUnknownCall = True
return self
def _tmp_addr(self):
"""Return the temporary seek target and clear it."""
if self._tmp_off:
return self._tmp_off[2:]
return ""
def setBreakpoint(self, addr=0):
addr = self._tmp_addr() or addr
self._exec(f"db {addr}")
def deleteBreakpoint(self, addr=0):
addr = self._tmp_addr() or addr
self._exec(f"db- {addr}")