def _op_divmod(self, args): if self.is_signed: quotient = (args[0].SDiv(claripy.SignExt(self._from_size - self._to_size, args[1]))) remainder = (args[0].SMod(claripy.SignExt(self._from_size - self._to_size, args[1]))) quotient_size = self._to_size remainder_size = self._to_size return claripy.Concat( claripy.Extract(remainder_size - 1, 0, remainder), claripy.Extract(quotient_size - 1, 0, quotient) ) else: quotient = (args[0] // claripy.ZeroExt(self._from_size - self._to_size, args[1])) remainder = (args[0] % claripy.ZeroExt(self._from_size - self._to_size, args[1])) quotient_size = self._to_size remainder_size = self._to_size return claripy.Concat( claripy.Extract(remainder_size - 1, 0, remainder), claripy.Extract(quotient_size - 1, 0, quotient) )
def _handle_DivMod(self, expr): arg0, arg1 = expr.args r0 = self._expr(arg0) r1 = self._expr(arg1) result_size = expr.result_size(self.tyenv) if r0.data.concrete and r1.data.concrete: # constants try: signed = "U" in expr.op # Iop_DivModU64to32 vs Iop_DivMod from_size = r0.data.size() to_size = r1.data.size() if signed: quotient = (r0.data.SDiv( claripy.SignExt(from_size - to_size, r1.data))) remainder = (r0.data.SMod( claripy.SignExt(from_size - to_size, r1.data))) quotient_size = to_size remainder_size = to_size result = claripy.Concat( claripy.Extract(remainder_size - 1, 0, remainder), claripy.Extract(quotient_size - 1, 0, quotient)) else: quotient = (r0.data // claripy.ZeroExt(from_size - to_size, r1.data)) remainder = (r0.data % claripy.ZeroExt(from_size - to_size, r1.data)) quotient_size = to_size remainder_size = to_size result = claripy.Concat( claripy.Extract(remainder_size - 1, 0, remainder), claripy.Extract(quotient_size - 1, 0, quotient)) return RichR(result) except ZeroDivisionError: pass r = self.state.top(result_size) return RichR(r)
def extend_size(self, o): cur_size = o.size() if cur_size < self._output_size_bits: l.debug("Extending output of %s from %d to %d bits", self.name, cur_size, self._output_size_bits) ext_size = self._output_size_bits - cur_size if self._to_signed == 'S' or (self._from_signed == 'S' and self._to_signed is None): return claripy.SignExt(ext_size, o) else: return claripy.ZeroExt(ext_size, o) elif cur_size > self._output_size_bits: __import__('ipdb').set_trace() raise SimOperationError('output of %s is too big', self.name) else: return o
def extend_size(self, o): cur_size = o.size() if cur_size == self._output_size_bits: return o if cur_size < self._output_size_bits: ext_size = self._output_size_bits - cur_size if self._to_signed == 'S' or (self._from_signed == 'S' and self._to_signed is None): return claripy.SignExt(ext_size, o) else: return claripy.ZeroExt(ext_size, o) # if cur_size > self._output_size_bits: # breakpoint here. it should never happen! __import__('ipdb').set_trace() raise SimOperationError('output of %s is too big' % self.name)
def _ail_handle_Div(self, expr): arg0, arg1 = expr.operands r0 = self._expr(arg0) r1 = self._expr(arg1) from_size = expr.bits to_size = r1.bits if expr.signed: remainder = r0.data.SMod(claripy.SignExt(from_size - to_size, r1.data)) else: remainder = r0.data % claripy.ZeroExt(from_size - to_size, r1.data) return RichR(remainder, # typevar=r0.typevar, # FIXME: Handle typevars for Div )
def extend_size(self, o): cur_size = o.size() target_size = self._output_size_bits if self._vector_count is not None: # phrased this awkward way to account for vectorized widening multiply target_size //= self._vector_count if cur_size == target_size: return o if cur_size < target_size: ext_size = target_size - cur_size if self._to_signed == 'S' or (self._to_signed is None and self._from_signed == 'S') or (self._to_signed is None and self._vector_signed == 'S'): return claripy.SignExt(ext_size, o) else: return claripy.ZeroExt(ext_size, o) # if cur_size > target_size: # it should never happen! raise SimOperationError('output of %s is too big' % self.name)
def _op_mapped(self, args): if self._from_size is not None: sized_args = [ ] for a in args: s = a.size() if s == self._from_size: sized_args.append(a) elif s < self._from_size: if self.is_signed: sized_args.append(claripy.SignExt(self._from_size - s, a)) else: sized_args.append(claripy.ZeroExt(self._from_size - s, a)) elif s > self._from_size: raise SimOperationError("operation %s received too large an argument" % self.name) else: sized_args = args if self._generic_name in operation_map: # bitwise/arithmetic/shift operations o = operation_map[self._generic_name] else: raise SimOperationError("op_mapped called with invalid mapping, for %s" % self.name) return getattr(claripy.ast.BV, o)(*sized_args)
def _op_sign_extend(self, args): return claripy.SignExt(self._to_size - args[0].size(), args[0])
def _ail_handle_Convert(self, expr: Expr.Convert) -> PropValue: o_value = self._expr(expr.operand) if o_value is None or self.state.is_top(o_value.value): new_value = self.state.top(expr.to_bits) else: if expr.from_bits < expr.to_bits: if expr.is_signed: new_value = claripy.SignExt(expr.to_bits - expr.from_bits, o_value.value) else: new_value = claripy.ZeroExt(expr.to_bits - expr.from_bits, o_value.value) elif expr.from_bits > expr.to_bits: new_value = claripy.Extract(expr.to_bits - 1, 0, o_value.value) else: new_value = o_value.value o_expr = o_value.one_expr o_defat = o_value.one_defat if o_expr is not None: # easy cases if type(o_expr) is Expr.Convert: if expr.from_bits == o_expr.to_bits and expr.to_bits == o_expr.from_bits: # eliminate the redundant Convert new_expr = o_expr.operand else: new_expr = Expr.Convert(expr.idx, o_expr.from_bits, expr.to_bits, expr.is_signed, o_expr.operand) elif type(o_expr) is Expr.Const: # do the conversion right away value = o_expr.value mask = (2 ** expr.to_bits) - 1 value &= mask new_expr = Expr.Const(expr.idx, o_expr.variable, value, expr.to_bits) else: new_expr = Expr.Convert(expr.idx, expr.from_bits, expr.to_bits, expr.is_signed, o_expr, **expr.tags) if isinstance(new_expr, Expr.Convert) and not new_expr.is_signed \ and new_expr.to_bits > new_expr.from_bits and new_expr.from_bits % self.arch.byte_width == 0: # special handling for zero-extension: it simplifies the code if we explicitly model zeros new_size = new_expr.from_bits // self.arch.byte_width offset_and_details = { 0: Detail(new_size, new_expr.operand, o_defat), new_size: Detail( new_expr.size - new_size, Expr.Const(expr.idx, None, 0, new_expr.to_bits - new_expr.from_bits), self._codeloc()), } else: offset_and_details = {0: Detail(expr.size, new_expr, self._codeloc())} return PropValue(new_value, offset_and_details=offset_and_details) elif o_value.offset_and_details: # hard cases... we will keep certain labels and eliminate other labels start_offset = 0 end_offset = expr.to_bits // self.arch.byte_width # end_offset is exclusive offset_and_details = {} max_offset = max(o_value.offset_and_details.keys()) for offset_, detail_ in o_value.offset_and_details.items(): if offset_ < start_offset < offset_ + detail_.size: # we start here off = 0 siz = min(end_offset, offset_ + detail_.size) - start_offset expr_ = PropValue.extract_ail_expression( (start_offset - offset_) * self.arch.byte_width, siz * self.arch.byte_width, detail_.expr ) offset_and_details[off] = Detail(siz, expr_, detail_.def_at) elif offset_ >= start_offset and offset_ + detail_.size <= end_offset: # we include the whole thing off = offset_ - start_offset siz = detail_.size if off == max_offset and off + siz < end_offset: # extend the expr expr_ = PropValue.extend_ail_expression( (end_offset - (off + siz)) * self.arch.byte_width, detail_.expr ) siz = end_offset - off else: expr_ = detail_.expr offset_and_details[off] = Detail(siz, expr_, detail_.def_at) elif offset_ < end_offset <= offset_ + detail_.size: # we include all the way until end_offset if offset_ < start_offset: off = 0 siz = end_offset - start_offset else: off = offset_ - start_offset siz = end_offset - offset_ expr_ = PropValue.extract_ail_expression(0, siz * self.arch.byte_width, detail_.expr) offset_and_details[off] = Detail(siz, expr_, detail_.def_at) return PropValue( new_value, offset_and_details=offset_and_details ) else: # it's empty... no expression is available for whatever reason return PropValue.from_value_and_details(new_value, expr.size, expr, self._codeloc())