def _set_value(self, var_data: VarnodeData, value: BV) -> None: """ Store a value for a given varnode. This method stores to the appropriate register, or unique space, depending on the space indicated by the varnode. :param var_data: The varnode to store into. :param value: The value to store. """ space_name = var_data.space.getName() # FIXME: Consider moving into behavior.py value = self._adjust_value_size(var_data.size * 8, value) assert var_data.size * 8 == value.size() l.debug("Storing %s %x %s %d", space_name, var_data.offset, value, var_data.size) if space_name == "register": self.state.registers.store(self._map_register_name(var_data), value, size=var_data.size) elif space_name == "unique": self._pcode_tmps[var_data.offset] = value elif space_name == "ram": l.debug("Storing %s to offset %s", value, var_data.offset) self.state.memory.store(var_data.offset, value, endness=self.project.arch.memory_endness) else: raise NotImplementedError()
def _adjust_value_size(num_bits: int, v_in: BV) -> BV: """ Ensure given bv is num_bits bits long by either zero extending or truncating. """ if v_in.size() > num_bits: v_out = v_in[num_bits - 1:0] l.debug('Truncating value %s (%d bits) to %s (%d bits)', v_in, v_in.size(), v_out, num_bits) return v_out elif v_in.size() < num_bits: v_out = v_in.zero_extend(num_bits - v_in.size()) l.debug('Extending value %s (%d bits) to %s (%d bits)', v_in, v_in.size(), v_out, num_bits) return v_out else: return v_in
def make_bv_sizes_equal(bv1: BV, bv2: BV) -> Tuple[BV, BV]: """ Makes two BVs equal in length through sign extension. """ if bv1.size() < bv2.size(): return (bv1.sign_extend(bv2.size() - bv1.size()), bv2) elif bv1.size() > bv2.size(): return (bv1, bv2.sign_extend(bv1.size() - bv2.size())) else: return (bv1, bv2)
def evaluate_binary(self, size_out: int, size_in: int, in1: BV, in2: BV) -> BV: if in2.size() < in1.size(): in2 = in2.sign_extend(in1.size() - in2.size()) return (in1 >> (in2 * 8)) & (2**(size_out * 8) - 1)
def booleanize(cls, in1: BV) -> BV: """ Reduce input BV to a single bit of truth: out <- 1 if (in1 != 0) else 0. """ return cls.generic_compare((in1, claripy.BVV(0, in1.size())), operator.ne)
def evaluate_unary(self, size_out: int, size_in: int, in1: BV) -> BV: return self.generic_compare((in1, claripy.BVV(0, in1.size())), operator.eq)
def evaluate_binary(self, size_out: int, size_in: int, in1: BV, in2: BV) -> BV: if in2.size() < in1.size(): in2 = in2.sign_extend(in1.size() - in2.size()) return in1.LShR(in2)