Source code for angr.storage.memory_mixins.regioned_memory.regioned_address_concretization_mixin

from typing import Optional, Generator

import claripy

from ....sim_options import HYBRID_SOLVER, APPROXIMATE_FIRST
from .... import concretization_strategies
from ....errors import SimMergeError, SimMemoryAddressError
from .. import MemoryMixin
from .abstract_address_descriptor import AbstractAddressDescriptor
from .region_data import AddressWrapper


[docs]class RegionedAddressConcretizationMixin(MemoryMixin):
[docs] def __init__(self, read_strategies=None, write_strategies=None, **kwargs): super().__init__(**kwargs) self.read_strategies = read_strategies self.write_strategies = write_strategies
[docs] def set_state(self, state): super().set_state(state) if self.state is not None: if self.read_strategies is None: self._create_default_read_strategies() if self.write_strategies is None: self._create_default_write_strategies()
@MemoryMixin.memo def copy(self, memo): o = super().copy(memo) o.read_strategies = list(self.read_strategies) o.write_strategies = list(self.write_strategies) return o
[docs] def merge(self, others, merge_conditions, common_ancestor=None) -> bool: r = super().merge(others, merge_conditions, common_ancestor=common_ancestor) self.read_strategies = self._merge_strategies(self.read_strategies, *[o.read_strategies for o in others]) self.write_strategies = self._merge_strategies(self.write_strategies, *[o.write_strategies for o in others]) return r
def _create_default_read_strategies(self): """ This function is used to populate `self.read_strategies` if by set-state time none have been provided It uses state options to pick defaults. """ self.read_strategies = [ concretization_strategies.SimConcretizationStrategyUnlimitedRange(self._read_targets_limit) ] def _create_default_write_strategies(self): """ This function is used to populate `self.write_strategies` if by set-state time none have been provided. It uses state options to pick defaults. """ self.write_strategies = [ concretization_strategies.SimConcretizationStrategyUnlimitedRange(self._write_targets_limit) ] @staticmethod def _merge_strategies(*strategy_lists): """ Utility function for merging. Does the merge operation on lists of strategies """ if len({len(sl) for sl in strategy_lists}) != 1: raise SimMergeError("unable to merge memories with amounts of strategies") merged_strategies = [] for strategies in zip(*strategy_lists): if len({s.__class__ for s in strategies}) != 1: raise SimMergeError("unable to merge memories with different types of strategies") unique = list(set(strategies)) if len(unique) > 1: unique[0].merge(unique[1:]) merged_strategies.append(unique[0]) return merged_strategies def _apply_concretization_strategies(self, addr, strategies): """ Applies concretization strategies on the address until one of them succeeds. """ for s in strategies: a = s.concretize(self, addr) # return the result if not None! if a is not None: return a # well, we tried raise SimMemoryAddressError("Unable to concretize address with the provided strategies.") def _concretize_address_descriptor( self, desc: AbstractAddressDescriptor, original_addr: claripy.ast.Bits, is_write: bool = False, target_region: Optional[str] = None, ) -> Generator[AddressWrapper, None, None]: strategies = self.write_strategies if is_write else self.read_strategies targets_limit = self._write_targets_limit if is_write else self._read_targets_limit for region, addr_si in desc: concrete_addrs = self._apply_concretization_strategies(addr_si, strategies) if len(concrete_addrs) == targets_limit and HYBRID_SOLVER in self.state.options: exact = True if APPROXIMATE_FIRST not in self.state.options else None solutions = self.state.solver.eval_upto(original_addr, targets_limit, exact=exact) if len(solutions) < len(concrete_addrs): concrete_addrs = [addr_si.intersection(s).eval(1)[0] for s in solutions] for c in concrete_addrs: yield self._normalize_address_core(region, c, target_region=target_region) def _normalize_address_core( self, region_id: str, relative_address: int, target_region: Optional[str] = None ) -> AddressWrapper: return super()._normalize_address_core(region_id, relative_address, target_region)