diff options
| -rw-r--r-- | src/focaccia/symbolic.py | 25 |
1 files changed, 22 insertions, 3 deletions
diff --git a/src/focaccia/symbolic.py b/src/focaccia/symbolic.py index eff0c3b..77bedf5 100644 --- a/src/focaccia/symbolic.py +++ b/src/focaccia/symbolic.py @@ -611,8 +611,11 @@ class SpeculativeTracer(ReadableProgramState): self.pc = target.read_register('pc') self.speculative_pc: int | None = None self.speculative_count: int = 0 + + self.read_cache = {} def speculate(self, new_pc): + self.read_cache.clear() if new_pc is None: self.progress_execution() self.target.step() @@ -637,6 +640,8 @@ class SpeculativeTracer(ReadableProgramState): self.speculative_pc = None self.speculative_count = 0 + self.read_cache.clear() + def run_until(self, addr: int): if self.speculative_pc: raise Exception('Attempting manual execution with speculative execution enabled') @@ -650,25 +655,35 @@ class SpeculativeTracer(ReadableProgramState): self.target.step() self.pc = self.target.read_register('pc') + def _cache(self, name: str, value): + self.read_cache[name] = value + return value + def read_pc(self) -> int: if self.speculative_pc is not None: return self.speculative_pc return self.pc def read_flags(self) -> dict[str, int | bool]: + if 'flags' in self.read_cache: + return self.read_cache['flags'] self.progress_execution() - return self.target.read_flags() + return self._cache('flags', self.target.read_flags()) def read_register(self, reg: str) -> int: regname = self.arch.to_regname(reg) if regname is None: raise RegisterAccessError(reg, f'Not a register name: {reg}') + if reg in self.read_cache: + return self.read_cache[reg] + self.progress_execution() - return self.target.read_register(regname) + return self._cache(reg, self.target.read_register(regname)) def write_register(self, regname: str, value: int): self.progress_execution() + self.read_cache.pop(regname, None) self.target.write_register(regname, value) def read_instructions(self, addr: int, size: int) -> bytes: @@ -676,10 +691,14 @@ class SpeculativeTracer(ReadableProgramState): def read_memory(self, addr: int, size: int) -> bytes: self.progress_execution() - return self.target.read_memory(addr, size) + cache_name = f'{addr}_{size}' + if cache_name in self.read_cache: + return self.read_cache[cache_name] + return self._cache(cache_name, self.target.read_memory(addr, size)) def write_memory(self, addr: int, value: bytes): self.progress_execution() + self.read_cache.pop(addr, None) self.target.write_memory(addr, value) def __getattr__(self, name: str): |