diff options
| author | Theofilos Augoustis <theofilos.augoustis@gmail.com> | 2023-11-26 11:56:49 +0100 |
|---|---|---|
| committer | Theofilos Augoustis <theofilos.augoustis@gmail.com> | 2023-11-26 11:56:49 +0100 |
| commit | 47894bb5d2e425f28d992aee6331b89b85b2058d (patch) | |
| tree | fd08c28c447fbb95e9d8d4122514227f9a48d0ad /snapshot.py | |
| parent | a4bf627c2440cbea392e27f138b07fa22cd9e6f1 (diff) | |
| download | focaccia-47894bb5d2e425f28d992aee6331b89b85b2058d.tar.gz focaccia-47894bb5d2e425f28d992aee6331b89b85b2058d.zip | |
Standardize X86 register names
Add some infrastructure for flexible register name matching (i.e. using 'PC' to look up RIP): - `Arch.to_regname` tries to look up a register's standard name from an arbitrary string. - `ArchX86` overrides `to_regname` to resolve alias names for registers. Currently just 'PC' for 'RIP'. - `ProgramState.read` and `ProgramState.write` use `to_regname` to make register access more convenient. Add all flags with their standard abbreviations to `x86.regnames`. Implement a full RFLAGS decomposition into its individual flags in `x86`. Replace the hacks in `run.py` and `miasm_test.py` with this more complete solution. Co-authored-by: Theofilos Augoustis <theofilos.augoustis@gmail.com> Co-authored-by: Nicola Crivellin <nicola.crivellin98@gmail.com>
Diffstat (limited to 'snapshot.py')
| -rw-r--r-- | snapshot.py | 48 |
1 files changed, 25 insertions, 23 deletions
diff --git a/snapshot.py b/snapshot.py index d5136ad..01c6446 100644 --- a/snapshot.py +++ b/snapshot.py @@ -1,38 +1,40 @@ from arch.arch import Arch -class ProgramState(): +class ProgramState: """A snapshot of the program's state.""" def __init__(self, arch: Arch): self.arch = arch - dict_t = dict[str, int] - self.regs = dict_t({ reg: None for reg in arch.regnames }) - self.has_backwards = False - self.matched = False + dict_t = dict[str, int | None] + self.regs: dict_t = { reg: None for reg in arch.regnames } - def set_backwards(self): - self.has_backwards = True + def read(self, reg: str) -> int: + """Read a register's value. + + :raise KeyError: If `reg` is not a register name. + :raise ValueError: If the register has no value. + """ + regname = self.arch.to_regname(reg) + if regname is None: + raise KeyError(f'Not a register name: {reg}') + + assert(regname in self.regs) + regval = self.regs[regname] + if regval is None: + raise ValueError(f'Unable to read value of register {reg} (aka.' + f' {regname}): The register contains no value.') + return regval def set(self, reg: str, value: int): """Assign a value to a register. - :raises RuntimeError: if the register already has a value. + :raise KeyError: If `reg` is not a register name. """ - assert(reg in self.arch.regnames) - - if self.regs[reg] != None: - raise RuntimeError("Reassigning register") - self.regs[reg] = value - - def as_repr(self, reg: str): - """Get a representational string of a register's value.""" - assert(reg in self.arch.regnames) + regname = self.arch.to_regname(reg) + if regname is None: + raise KeyError(f'Not a register name: {regname}') - value = self.regs[reg] - if value is not None: - return hex(value) - else: - return "<none>" + self.regs[regname] = value def __repr__(self): - return self.regs.__repr__() + return repr(self.regs) |