Source code for angr.state_plugins.light_registers

import claripy
import logging

from .plugin import SimStatePlugin
from ..errors import SimFastMemoryError
from ..misc.ux import once
from .. import sim_options as options

l = logging.getLogger(__name__)


[docs]class SimLightRegisters(SimStatePlugin):
[docs] def __init__(self, reg_map=None, registers=None): super().__init__() self.reg_map = {} if reg_map is None else reg_map self.registers = {} if registers is None else registers
@SimStatePlugin.memo def copy(self, _memo): o = type(self)(reg_map=self.reg_map, registers=dict(self.registers)) return o
[docs] def set_state(self, state): super().set_state(state) if not self.registers: ip_name = state.arch.register_names[state.arch.ip_offset] self.registers[ip_name] = claripy.BVV(0, state.arch.registers[ip_name][1]) if self.reg_map: return bw = state.arch.byte_width for reg in state.arch.register_list: self.reg_map[(reg.vex_offset, reg.size)] = reg.name, None, reg.size * bw for subreg_name, subreg_suboffset, subreg_size in reg.subregisters: # endian swap gets undone here if state.arch.register_endness == "Iend_BE": extract_high = (reg.size - 1 - subreg_suboffset) * bw + 7 extract_low = extract_high - subreg_size * bw + 1 else: extract_low = subreg_suboffset * bw extract_high = extract_low + subreg_size * bw - 1 self.reg_map[(reg.vex_offset + subreg_suboffset, subreg_size)] = ( reg.name, (extract_high, extract_low), subreg_size * bw, )
[docs] def resolve_register(self, offset, size): if type(offset) is str: offset, size = self.state.arch.registers[offset] else: if type(size) is not int: try: if size.symbolic: raise SimFastMemoryError("Can't handle symbolic register access") else: size = offset.args[0] except AttributeError: raise TypeError("Invalid size argument") from None if type(offset) is not int: try: if offset.symbolic: raise SimFastMemoryError("Can't handle symbolic register access") else: offset = offset.args[0] except AttributeError: raise TypeError("Invalid offset argument") from None if size is None: raise SimFastMemoryError("No size for register access available") try: return self.reg_map[(offset, size)] except KeyError as e: raise SimFastMemoryError("Register access to an unknown register or register slice") from e
[docs] def load(self, offset, size=None, **kwargs): name, extract, _ = self.resolve_register(offset, size) return self._complex_load(name, extract)
def _complex_load(self, name, extract): val = self._simple_load(name) if extract is not None: val = val[extract[0] : extract[1]] return val def _simple_load(self, name): try: return self.registers[name] except KeyError: pass try: size = self.state.arch.registers[name][1] except KeyError as e: raise KeyError("Critical programming error in SimLightRegisters - pls report") from e return self._fill(name, size)
[docs] def store(self, offset, value, size=None, endness=None, **kwargs): if size is None and type(offset) is not str and type(value) is not int: try: size = len(value) // self.state.arch.byte_width except TypeError: raise SimFastMemoryError("Invalid register store value") from None name, extract, xsize = self.resolve_register(offset, size) if size is not None: try: if not self.state.solver.is_true(size * self.state.arch.byte_width == xsize): raise SimFastMemoryError("Inconsistent register store size") except TypeError: raise SimFastMemoryError("Invalid register store value") from None if type(value) is int: value = self.state.solver.BVV(value, xsize) if endness is not None and endness != self.state.arch.register_endness: # ??????? value = value.reversed self._complex_store(name, value, extract)
def _complex_store(self, name, value, extract): if extract is not None: baseval = self._simple_load(name) if extract[0] != len(baseval) - 1: value = baseval[len(baseval) - 1 : extract[0] + 1].concat(value) if extract[1] != 0: value = value.concat(baseval[extract[1] - 1 : 0]) self._simple_store(name, value) def _simple_store(self, name, value): self.registers[name] = value def _fill(self, name, size): size_bits = size * self.state.arch.byte_width if options.ZERO_FILL_UNCONSTRAINED_REGISTERS in self.state.options: value = self.state.solver.BVV(0, size_bits) else: if options.SYMBOL_FILL_UNCONSTRAINED_REGISTERS not in self.state.options: if once("mem_fill_warning"): l.warning( "The program is accessing memory or registers with an unspecified value. " "This could indicate unwanted behavior." ) l.warning( "angr will cope with this by generating an unconstrained symbolic variable and continuing. " "You can resolve this by:" ) l.warning("1) setting a value to the initial state") l.warning( "2) adding the state option ZERO_FILL_UNCONSTRAINED_{MEMORY,REGISTERS}, " "to make unknown regions hold null" ) l.warning( "3) adding the state option SYMBOL_FILL_UNCONSTRAINED_{MEMORY_REGISTERS}, " "to suppress these messages." ) l.warning("Filling register %s with %d unconstrained bytes", name, size) return self.state.solver.Unconstrained("reg_%s" % name, size_bits, key=("reg", name), eternal=True) # :) self.registers[name] = value return value