def prepare(val, signext=False, size=SIZE) -> z3.BitVecRef: if z3.is_bv(val): szdiff = size - val.size() if szdiff > 0: if signext: result = z3.SignExt(szdiff, val) else: result = z3.ZeroExt(szdiff, val) elif szdiff < 0: result = z3.Extract(size - 1, 0, val) else: result = val elif type(val) == int: result = z3.BitVecVal(val, size) elif z3.is_int(val): result = z3.Int2BV(val, size) elif z3.is_fp(val): # changing up this logic to align with r2ghidra impl result = z3.fpToIEEEBV(val) #result = val else: result = z3.BitVecVal(val, size) #return z3.simplify(result) return result
def prepare(val, signext=False, size=SIZE) -> z3.BitVecRef: if z3.is_bv(val): szdiff = size-val.size() if szdiff == 0: result = val elif szdiff > 0: if signext: result = z3.SignExt(szdiff, val) else: result = z3.ZeroExt(szdiff, val) elif szdiff < 0: result = z3.Extract(size-1, 0, val) elif isinstance(val, int): result = z3.BitVecVal(val, size) elif z3.is_int(val): result = z3.Int2BV(val, size) elif z3.is_fp(val): result = z3.fpToIEEEBV(val) else: result = z3.BitVecVal(val, size) if not z3.is_bv_value(result): return z3.simplify(result) else: return result
def _(src, tgt, v): w = z3.fpToIEEEBV(v) i = z3.If(z3.Or(z3.fpIsZero(v), z3.fpIsSubnormal(v)), z3.BitVecVal(0,1), z3.BitVecVal(1,1)) return z3.Concat(z3.Extract(78,63,w), i, z3.Extract(62,0,w))
def get_bv_str(self): bv_str = bin(int(str(z3.simplify(z3.fpToIEEEBV(self.z3_ds))))) assert bv_str[0:2] == '0b', bv_str[0:2] + ' vs ' + '0b' bv_str = bv_str[2:] while len(bv_str) < self.ne + self.ns: bv_str = '0' + bv_str return bv_str
def pack_f32(n: f32): if utils.is_all_real(n): float_bytes = struct.pack('<f', n) return [float_bytes for float_byte in float_bytes] f32_bv = z3.fpToIEEEBV(n) return [ z3.Extract(7, 0, f32_bv), z3.Extract(15, 8, f32_bv), z3.Extract(23, 16, f32_bv), z3.Extract(31, 24, f32_bv) ]
def pack_f64(n: f64): if utils.is_all_real(n): double_bytes = struct.pack('<d', n) return [double_byte for double_byte in double_bytes] f64_bv = z3.fpToIEEEBV(n) return [ z3.Extract(7, 0, f64_bv), z3.Extract(15, 8, f64_bv), z3.Extract(23, 16, f64_bv), z3.Extract(31, 24, f64_bv), z3.Extract(39, 32, f64_bv), z3.Extract(47, 40, f64_bv), z3.Extract(55, 48, f64_bv), z3.Extract(63, 56, f64_bv) ]
def _op_raw_fpToIEEEBV(self, x): return z3.fpToIEEEBV(x, ctx=self._context)
import z3 # We do float16 because it lets the solver run much faster. These results # should generalize to fp32 and fp64, and you can verify this by changing the # value of FLOAT_TY (and then waiting a while). FLOAT_TY = z3.Float16 a = z3.FP("a", FLOAT_TY()) b = z3.FP("b", FLOAT_TY()) c = z3.FP("c", FLOAT_TY()) s = z3.Solver() # C must be a power of 2, i.e. significand bits must all be 0. s.add(z3.Extract(FLOAT_TY().sbits() - 1, 0, z3.fpToIEEEBV(c)) == 0) for rm in [z3.RTZ(), z3.RNE()]: z3.set_default_rounding_mode(rm) before = a * c + b * c after = (a + b) * c # Check that before == after, allowing that 0 == -0. s.add( z3.Not( z3.Or( before == after, # z3.And(z3.fpIsZero(before), z3.fpIsZero(after))))) for x in [ (a * c),
def _(src, tgt, v): return z3.fpToIEEEBV(v)
def f642i64(f: f64) -> i64: if utils.is_all_real(f): return struct.unpack('<q', struct.pack('<d', f))[0] return z3.fpToIEEEBV(f, z3.Float64())
def f322i32(f: f32) -> i32: if utils.is_all_real(f): return struct.unpack('<i', struct.pack('<f', f))[0] return z3.fpToIEEEBV(f, z3.Float32())
def do_F2I(op, stack, state): val, = pop_values(stack, state) stack.append(z3.fpToIEEEBV(val))
from __future__ import print_function import z3 # We do float16 because it lets the solver run much faster. These results # should generalize to fp32 and fp64, and you can verify this by changing the # value of FLOAT_TY (and then waiting a while). FLOAT_TY = z3.Float16 a = z3.FP("a", FLOAT_TY()) b = z3.FP("b", FLOAT_TY()) c = z3.FP("c", FLOAT_TY()) s = z3.Solver() # C must be a power of 2, i.e. significand bits must all be 0. s.add(z3.Extract(FLOAT_TY().sbits() - 1, 0, z3.fpToIEEEBV(c)) == 0) for rm in [z3.RTZ(), z3.RNE()]: z3.set_default_rounding_mode(rm) before = a * c + b * c after = (a + b) * c # Check that before == after, allowing that 0 == -0. s.add( z3.Not( z3.Or( before == after, # z3.And(z3.fpIsZero(before), z3.fpIsZero(after))))) for x in [ (a * c),
def interp(tree, lookup, z3_mode): """Evaluate the arithmetic expression. Pass a tree as a Lark `Tree` object for the parsed expression. For `lookup`, provide a function for mapping variable names to values. """ op = tree.data if op in ('add', 'sub', 'mul', 'div', 'shl', 'shr'): # Binary operators. lhs = interp(tree.children[0], lookup, z3_mode) rhs = interp(tree.children[1], lookup, z3_mode) if op == 'add': return lhs + rhs elif op == 'sub': return lhs - rhs elif op == 'mul': return lhs * rhs elif op == 'div': return lhs / rhs elif op == 'shl': return lhs << rhs elif op == 'shr': return lhs >> rhs elif op == 'neg': # Negation. sub = interp(tree.children[0], lookup, z3_mode) return -sub elif op == 'int': # Literal number. if z3_mode: return z3.BitVecVal(int(tree.children[0]), 32) else: return int(tree.children[0]) elif op == 'float': # Literal number. if z3_mode: return z3.BitVecVal(float(tree.children[0]), 32) else: return float(tree.children[0]) elif op == 'var': # Variable lookup. return lookup(tree.children[0]) elif op == 'if': # Conditional. cond = interp(tree.children[0], lookup, z3_mode) true = interp(tree.children[1], lookup, z3_mode) false = interp(tree.children[2], lookup, z3_mode) return (cond != 0) * true + (cond == 0) * false elif op == "intcast": child = interp(tree.children[0], lookup, z3_mode) if z3_mode: return z3.BV2Int(child) else: return int(child) elif op == "floatcast": child = interp(tree.children[0], lookup, z3_mode) if z3_mode: return z3.fpBVToFP(child, z3.Float32()) else: return float(child) elif op == "int2bv": child = interp(tree.children[0], lookup, z3_mode) if z3_mode: return z3.Int2BV(child, 32) else: return child elif op == "float2bv": child = interp(tree.children[0], lookup, z3_mode) if z3_mode: return z3.fpToIEEEBV(child) else: return child