about summary refs log tree commit diff stats
path: root/snapshot.py
diff options
context:
space:
mode:
authorTheofilos Augoustis <theofilos.augoustis@gmail.com>2023-11-26 11:56:49 +0100
committerTheofilos Augoustis <theofilos.augoustis@gmail.com>2023-11-26 11:56:49 +0100
commit47894bb5d2e425f28d992aee6331b89b85b2058d (patch)
treefd08c28c447fbb95e9d8d4122514227f9a48d0ad /snapshot.py
parenta4bf627c2440cbea392e27f138b07fa22cd9e6f1 (diff)
downloadfocaccia-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.py48
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)