about summary refs log tree commit diff stats
path: root/snapshot.py
blob: 3170649f0c5f5737b566538f2a6a4d6a2d770fbc (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
from arch.arch import Arch

class ProgramState:
    """A snapshot of the program's state."""
    def __init__(self, arch: Arch):
        self.arch = arch

        dict_t = dict[str, int | None]
        self.regs: dict_t = { reg: None for reg in arch.regnames }

    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.

        :raise KeyError:   If `reg` is not a register name.
        """
        regname = self.arch.to_regname(reg)
        if regname is None:
            raise KeyError(f'Not a register name: {regname}')

        self.regs[regname] = value

    def __repr__(self):
        return repr(self.regs)

class SnapshotSymbolResolver(SymbolResolver):
    def __init__(self, snapshot: ProgramState):
        self._state = snapshot

    def resolve(self, symbol: str):
        if symbol not in self._state.arch.regnames:
            raise SymbolResolveError(symbol, 'Symbol is not a register name.')
        return self._state.read(symbol)