miasm2.arch.x86.sem module
# # Copyright (C) 2011 EADS France, Fabrice Desclaux <fabrice.desclaux@eads.net> # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along # with this program; if not, write to the Free Software Foundation, Inc., # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. # import logging import miasm2.expression.expression as m2_expr from miasm2.expression.simplifications import expr_simp from miasm2.arch.x86.regs import * from miasm2.arch.x86.arch import mn_x86, repeat_mn, replace_regs from miasm2.ir.ir import IntermediateRepresentation, IRBlock, AssignBlock from miasm2.core.sembuilder import SemBuilder from miasm2.jitter.csts import EXCEPT_DIV_BY_ZERO, EXCEPT_ILLEGAL_INSN, \ EXCEPT_PRIV_INSN, EXCEPT_SOFT_BP, EXCEPT_INT_XX import math import struct LOG_X86_SEM = logging.getLogger("x86_sem") CONSOLE_HANDLER = logging.StreamHandler() CONSOLE_HANDLER.setFormatter(logging.Formatter("%(levelname)-5s: %(message)s")) LOG_X86_SEM.addHandler(CONSOLE_HANDLER) LOG_X86_SEM.setLevel(logging.WARNING) # SemBuilder context ctx = {'mRAX': mRAX, 'mRBX': mRBX, 'mRCX': mRCX, 'mRDX': mRDX, 'zf': zf, } sbuild = SemBuilder(ctx) """ http://www.emulators.com/docs/nx11_flags.htm CF(A+B) = (((A XOR B) XOR D) < 0) XOR (((A XOR D) AND NOT (A XOR B)) < 0) CF(A-B) = (((A XOR B) XOR D) < 0) XOR (((A XOR D) AND (A XOR B)) < 0) OF(A+B) = ((A XOR D) AND NOT (A XOR B)) < 0 OF(A-B) = ((A XOR D) AND (A XOR B)) < 0 """ # XXX TODO make default check against 0 or not 0 (same eq as in C) def update_flag_zf_eq(a, b): return [m2_expr.ExprAff(zf, m2_expr.ExprOp("FLAG_EQ_CMP", a, b))] def update_flag_zf(a): return [ m2_expr.ExprAff( zf, m2_expr.ExprCond( a, m2_expr.ExprInt(0, zf.size), m2_expr.ExprInt(1, zf.size) ) ) ] def update_flag_nf(arg): return [ m2_expr.ExprAff( nf, m2_expr.ExprOp("FLAG_SIGN_SUB", arg, m2_expr.ExprInt(0, arg.size)) ) ] def update_flag_pf(a): return [m2_expr.ExprAff(pf, m2_expr.ExprOp('parity', a & m2_expr.ExprInt(0xFF, a.size)))] def update_flag_af(op1, op2, res): return [m2_expr.ExprAff(af, (op1 ^ op2 ^ res)[4:5])] def update_flag_znp(a): e = [] e += update_flag_zf(a) e += update_flag_nf(a) e += update_flag_pf(a) return e def update_flag_np(result): e = [] e += update_flag_nf(result) e += update_flag_pf(result) return e def null_flag_co(): e = [] e.append(m2_expr.ExprAff(of, m2_expr.ExprInt(0, of.size))) e.append(m2_expr.ExprAff(cf, m2_expr.ExprInt(0, cf.size))) return e def update_flag_arith(a): e = [] e += update_flag_znp(a) return e def update_flag_zfaddwc_eq(arg1, arg2, arg3): return [m2_expr.ExprAff(zf, m2_expr.ExprOp("FLAG_EQ_ADDWC", arg1, arg2, arg3))] def update_flag_zfsubwc_eq(arg1, arg2, arg3): return [m2_expr.ExprAff(zf, m2_expr.ExprOp("FLAG_EQ_SUBWC", arg1, arg2, arg3))] def update_flag_arith_add_znp(arg1, arg2): """ Compute znp flags for (arg1 + arg2) """ e = [] e += update_flag_zf_eq(arg1, -arg2) e += [m2_expr.ExprAff(nf, m2_expr.ExprOp("FLAG_SIGN_SUB", arg1, -arg2))] e += update_flag_pf(arg1+arg2) return e def update_flag_arith_addwc_znp(arg1, arg2, arg3): """ Compute znp flags for (arg1 + arg2 + cf) """ e = [] e += update_flag_zfaddwc_eq(arg1, arg2, arg3) e += [m2_expr.ExprAff(nf, m2_expr.ExprOp("FLAG_SIGN_ADDWC", arg1, arg2, arg3))] e += update_flag_pf(arg1+arg2+arg3.zeroExtend(arg2.size)) return e def update_flag_arith_sub_znp(arg1, arg2): """ Compute znp flags for (arg1 - arg2) """ e = [] e += update_flag_zf_eq(arg1, arg2) e += [m2_expr.ExprAff(nf, m2_expr.ExprOp("FLAG_SIGN_SUB", arg1, arg2))] e += update_flag_pf(arg1 - arg2) return e def update_flag_arith_subwc_znp(arg1, arg2, arg3): """ Compute znp flags for (arg1 - (arg2 + cf)) """ e = [] e += update_flag_zfsubwc_eq(arg1, arg2, arg3) e += [m2_expr.ExprAff(nf, m2_expr.ExprOp("FLAG_SIGN_SUBWC", arg1, arg2, arg3))] e += update_flag_pf(arg1 - (arg2+arg3.zeroExtend(arg2.size))) return e def check_ops_msb(a, b, c): if not a or not b or not c or a != b or a != c: raise ValueError('bad ops size %s %s %s' % (a, b, c)) def arith_flag(a, b, c): a_s, b_s, c_s = a.size, b.size, c.size check_ops_msb(a_s, b_s, c_s) a_s, b_s, c_s = a.msb(), b.msb(), c.msb() return a_s, b_s, c_s # checked: ok for adc add because b & c before +cf def update_flag_add_cf(op1, op2, res): "Compute cf in @res = @op1 + @op2" #return [m2_expr.ExprAff(cf, m2_expr.ExprOp("FLAG_SUB_CF", op1, -op2))] return [m2_expr.ExprAff(cf, m2_expr.ExprOp("FLAG_ADD_CF", op1, op2))] def update_flag_add_of(op1, op2, res): "Compute of in @res = @op1 + @op2" return [m2_expr.ExprAff(of, m2_expr.ExprOp("FLAG_ADD_OF", op1, op2))] # checked: ok for sbb add because b & c before +cf def update_flag_sub_cf(op1, op2, res): "Compote CF in @res = @op1 - @op2" return [m2_expr.ExprAff(cf, m2_expr.ExprOp("FLAG_SUB_CF", op1, op2))] def update_flag_sub_of(op1, op2, res): "Compote OF in @res = @op1 - @op2" return [m2_expr.ExprAff(of, m2_expr.ExprOp("FLAG_SUB_OF", op1, op2))] def update_flag_addwc_cf(op1, op2, op3): "Compute cf in @res = @op1 + @op2 + @op3" return [m2_expr.ExprAff(cf, m2_expr.ExprOp("FLAG_ADDWC_CF", op1, op2, op3))] def update_flag_addwc_of(op1, op2, op3): "Compute of in @res = @op1 + @op2 + @op3" return [m2_expr.ExprAff(of, m2_expr.ExprOp("FLAG_ADDWC_OF", op1, op2, op3))] def update_flag_subwc_cf(op1, op2, op3): "Compute cf in @res = @op1 + @op2 + @op3" return [m2_expr.ExprAff(cf, m2_expr.ExprOp("FLAG_SUBWC_CF", op1, op2, op3))] def update_flag_subwc_of(op1, op2, op3): "Compute of in @res = @op1 + @op2 + @op3" return [m2_expr.ExprAff(of, m2_expr.ExprOp("FLAG_SUBWC_OF", op1, op2, op3))] def update_flag_arith_add_co(x, y, z): e = [] e += update_flag_add_cf(x, y, z) e += update_flag_add_of(x, y, z) return e def update_flag_arith_sub_co(x, y, z): e = [] e += update_flag_sub_cf(x, y, z) e += update_flag_sub_of(x, y, z) return e def update_flag_arith_addwc_co(arg1, arg2, arg3): e = [] e += update_flag_addwc_cf(arg1, arg2, arg3) e += update_flag_addwc_of(arg1, arg2, arg3) return e def update_flag_arith_subwc_co(arg1, arg2, arg3): e = [] e += update_flag_subwc_cf(arg1, arg2, arg3) e += update_flag_subwc_of(arg1, arg2, arg3) return e def set_float_cs_eip(instr): e = [] # XXX TODO check float updt e.append(m2_expr.ExprAff(float_eip, m2_expr.ExprInt(instr.offset, float_eip.size))) e.append(m2_expr.ExprAff(float_cs, CS)) return e def mode2addrsize(mode): """Returns the address size for a given @mode""" mode2size = {16:32, 32:32, 64:64} if mode not in mode2size: raise RuntimeError("Unknown size %s", mode) return mode2size[mode] def instr2addrsize(instr): """Returns the address size for a given @instr""" return mode2addrsize(instr.mode) def expraddr(mode, ptr): """Returns memory address pointer with size according to current @mode""" return ptr.zeroExtend(mode2addrsize(mode)) def fix_mem_args_size(instr, *args): out = [] for arg in args: if not arg.is_mem(): out.append(arg) continue ptr = arg.arg size = arg.size if ptr.is_op('segm'): ptr = m2_expr.ExprOp( 'segm', ptr.args[0], expraddr(instr.mode, ptr.args[1])) else: ptr = expraddr(instr.mode, ptr) out.append(m2_expr.ExprMem(ptr, size)) return out def mem2double(instr, arg): """ Add float convertion if argument is an ExprMem @arg: argument to tranform """ if isinstance(arg, m2_expr.ExprMem): if arg.size > 64: # TODO: move to 80 bits arg = m2_expr.ExprMem(expraddr(instr.mode, arg.arg), size=64) return m2_expr.ExprOp('mem_%.2d_to_double' % arg.size, arg) else: return arg def float_implicit_st0(arg1, arg2): """ Generate full float operators if one argument is implicit (float_st0) """ if arg2 is None: arg2 = arg1 arg1 = float_st0 return arg1, arg2 def gen_jcc(ir, instr, cond, dst, jmp_if): """ Macro to generate jcc semantic @ir: ir instance @instr: instruction @cond: condtion of the jcc @dst: the dstination if jcc is taken @jmp_if: jump if/notif cond """ e = [] meip = mRIP[ir.IRDst.size] loc_next = ir.get_next_loc_key(instr) loc_next_expr = m2_expr.ExprLoc(loc_next, dst.size) if jmp_if: dstA, dstB = dst, loc_next_expr else: dstA, dstB = loc_next_expr, dst mn_dst = m2_expr.ExprCond(cond, dstA.zeroExtend(ir.IRDst.size), dstB.zeroExtend(ir.IRDst.size)) e.append(m2_expr.ExprAff(meip, mn_dst)) e.append(m2_expr.ExprAff(ir.IRDst, mn_dst)) return e, [] def gen_fcmov(ir, instr, cond, arg1, arg2, mov_if): """Generate fcmov @ir: ir instance @instr: instruction instance @cond: condition @mov_if: invert condition if False""" loc_do, loc_do_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) loc_skip = ir.get_next_loc_key(instr) loc_skip_expr = m2_expr.ExprLoc(loc_skip, ir.IRDst.size) if mov_if: dstA, dstB = loc_do_expr, loc_skip_expr else: dstA, dstB = loc_skip_expr, loc_do_expr e = [] e_do, extra_irs = [m2_expr.ExprAff(arg1, arg2)], [] e_do.append(m2_expr.ExprAff(ir.IRDst, loc_skip_expr)) e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(cond, dstA, dstB))) return e, [IRBlock(loc_do, [AssignBlock(e_do, instr)])] def gen_cmov(ir, instr, cond, dst, src, mov_if): """Generate cmov @ir: ir instance @instr: instruction instance @cond: condition @mov_if: invert condition if False""" loc_do, loc_do_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) loc_skip = ir.get_next_loc_key(instr) loc_skip_expr = m2_expr.ExprLoc(loc_skip, ir.IRDst.size) if mov_if: dstA, dstB = loc_do_expr, loc_skip_expr else: dstA, dstB = loc_skip_expr, loc_do_expr e = [] e_do, extra_irs = mov(ir, instr, dst, src) e_do.append(m2_expr.ExprAff(ir.IRDst, loc_skip_expr)) e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(cond, dstA, dstB))) return e, [IRBlock(loc_do, [AssignBlock(e_do, instr)])] def mov(_, instr, dst, src): if dst in [ES, CS, SS, DS, FS, GS]: src = src[:dst.size] if src in [ES, CS, SS, DS, FS, GS]: src = src.zeroExtend(dst.size) e = [m2_expr.ExprAff(dst, src)] return e, [] def movq(_, instr, dst, src): src_final = (src.zeroExtend(dst.size) if dst.size >= src.size else src[:dst.size]) return [m2_expr.ExprAff(dst, src_final)], [] @sbuild.parse def xchg(arg1, arg2): arg1 = arg2 arg2 = arg1 def movzx(_, instr, dst, src): e = [m2_expr.ExprAff(dst, src.zeroExtend(dst.size))] return e, [] def movsx(_, instr, dst, src): e = [m2_expr.ExprAff(dst, src.signExtend(dst.size))] return e, [] def lea(_, instr, dst, src): ptr = src.arg if src.is_mem_segm(): # Do not use segmentation here ptr = ptr.args[1] if ptr.size > dst.size: ptr = ptr[:dst.size] e = [m2_expr.ExprAff(dst, ptr.zeroExtend(dst.size))] return e, [] def add(_, instr, dst, src): e = [] result = dst + src e += update_flag_arith_add_znp(dst, src) e += update_flag_arith_add_co(dst, src, result) e += update_flag_af(dst, src, result) e.append(m2_expr.ExprAff(dst, result)) return e, [] def xadd(_, instr, dst, src): e = [] result = dst + src e += update_flag_arith_add_znp(dst, src) e += update_flag_arith_add_co(src, dst, result) e += update_flag_af(dst, src, result) if dst != src: e.append(m2_expr.ExprAff(src, dst)) e.append(m2_expr.ExprAff(dst, result)) return e, [] def adc(_, instr, dst, src): e = [] arg1 = dst arg2 = src result = arg1 + (arg2 + cf.zeroExtend(src.size)) e += update_flag_arith_addwc_znp(arg1, arg2, cf) e += update_flag_arith_addwc_co(arg1, arg2, cf) e += update_flag_af(arg1, arg2, result) e.append(m2_expr.ExprAff(dst, result)) return e, [] def sub(_, instr, dst, src): e = [] arg1, arg2 = dst, src result = dst - src e += update_flag_arith_sub_znp(arg1, arg2) e += update_flag_arith_sub_co(arg1, arg2, result) e += update_flag_af(dst, src, result) e.append(m2_expr.ExprAff(dst, result)) return e, [] # a-(b+cf) def sbb(_, instr, dst, src): e = [] arg1 = dst arg2 = src result = arg1 - (arg2 + cf.zeroExtend(src.size)) e += update_flag_arith_subwc_znp(arg1, arg2, cf) e += update_flag_af(arg1, arg2, result) e += update_flag_arith_subwc_co(arg1, arg2, cf) e.append(m2_expr.ExprAff(dst, result)) return e, [] def neg(_, instr, src): e = [] dst = m2_expr.ExprInt(0, src.size) arg1, arg2 = dst, src result = arg1 - arg2 e += update_flag_arith_sub_znp(arg1, arg2) e += update_flag_arith_sub_co(arg1, arg2, result) e += update_flag_af(arg1, arg2, result) e.append(m2_expr.ExprAff(src, result)) return (e, []) def l_not(_, instr, dst): e = [] result = (~dst) e.append(m2_expr.ExprAff(dst, result)) return (e, []) def l_cmp(_, instr, dst, src): e = [] arg1, arg2 = dst, src result = dst - src e += update_flag_arith_sub_znp(arg1, arg2) e += update_flag_arith_sub_co(arg1, arg2, result) e += update_flag_af(dst, src, result) return (e, []) def xor(_, instr, dst, src): e = [] result = dst ^ src e += [m2_expr.ExprAff(zf, m2_expr.ExprOp('FLAG_EQ_CMP', dst, src))] e += update_flag_np(result) e += null_flag_co() e.append(m2_expr.ExprAff(dst, result)) return (e, []) def pxor(_, instr, dst, src): e = [] result = dst ^ src e.append(m2_expr.ExprAff(dst, result)) return (e, []) def l_or(_, instr, dst, src): e = [] result = dst | src e += [m2_expr.ExprAff(zf, m2_expr.ExprOp('FLAG_EQ', dst | src))] e += update_flag_np(result) e += null_flag_co() e.append(m2_expr.ExprAff(dst, result)) return (e, []) def l_and(_, instr, dst, src): e = [] result = dst & src e += [m2_expr.ExprAff(zf, m2_expr.ExprOp('FLAG_EQ_AND', dst, src))] e += update_flag_np(result) e += null_flag_co() e.append(m2_expr.ExprAff(dst, result)) return (e, []) def l_test(_, instr, dst, src): e = [] result = dst & src e += [m2_expr.ExprAff(zf, m2_expr.ExprOp('FLAG_EQ_CMP', result, m2_expr.ExprInt(0, result.size)))] e += [m2_expr.ExprAff(nf, m2_expr.ExprOp("FLAG_SIGN_SUB", result, m2_expr.ExprInt(0, result.size)))] e += update_flag_pf(result) e += null_flag_co() return (e, []) def get_shift(dst, src): if isinstance(src, m2_expr.ExprInt): src = m2_expr.ExprInt(int(src), dst.size) else: src = src.zeroExtend(dst.size) if dst.size == 64: shift = src & m2_expr.ExprInt(63, src.size) else: shift = src & m2_expr.ExprInt(31, src.size) shift = expr_simp(shift) return shift def _rotate_tpl(ir, instr, dst, src, op, left=False): '''Template to generate a rotater with operation @op A temporary basic block is generated to handle 0-rotate @op: operation to execute @left (optional): indicates a left rotate if set, default is False ''' # Compute results shifter = get_shift(dst, src) res = m2_expr.ExprOp(op, dst, shifter) # CF is computed with 1-less round than `res` new_cf = m2_expr.ExprOp( op, dst, shifter - m2_expr.ExprInt(1, size=shifter.size)) new_cf = new_cf.msb() if left else new_cf[:1] # OF is defined only for @b == 1 new_of = m2_expr.ExprCond(src - m2_expr.ExprInt(1, size=src.size), m2_expr.ExprInt(0, size=of.size), res.msb() ^ new_cf if left else (dst ^ res).msb()) # Build basic blocks e_do = [m2_expr.ExprAff(cf, new_cf), m2_expr.ExprAff(of, new_of), m2_expr.ExprAff(dst, res) ] # Don't generate conditional shifter on constant if isinstance(shifter, m2_expr.ExprInt): if int(shifter) != 0: return (e_do, []) else: return ([], []) e = [] loc_do, loc_do_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) loc_skip = ir.get_next_loc_key(instr) loc_skip_expr = m2_expr.ExprLoc(loc_skip, ir.IRDst.size) e_do.append(m2_expr.ExprAff(ir.IRDst, loc_skip_expr)) e.append(m2_expr.ExprAff( ir.IRDst, m2_expr.ExprCond(shifter, loc_do_expr, loc_skip_expr))) return (e, [IRBlock(loc_do, [AssignBlock(e_do, instr)])]) def l_rol(ir, instr, dst, src): return _rotate_tpl(ir, instr, dst, src, '<<<', left=True) def l_ror(ir, instr, dst, src): return _rotate_tpl(ir, instr, dst, src, '>>>') def rotate_with_carry_tpl(ir, instr, op, dst, src): # Compute results shifter = get_shift(dst, src).zeroExtend(dst.size + 1) result = m2_expr.ExprOp(op, m2_expr.ExprCompose(dst, cf), shifter) new_cf = result[dst.size:dst.size +1] new_dst = result[:dst.size] result_trunc = result[:dst.size] if op == '<<<': of_value = result_trunc.msb() ^ new_cf else: of_value = (dst ^ result_trunc).msb() # OF is defined only for @b == 1 new_of = m2_expr.ExprCond(src - m2_expr.ExprInt(1, size=src.size), m2_expr.ExprInt(0, size=of.size), of_value) # Build basic blocks e_do = [m2_expr.ExprAff(cf, new_cf), m2_expr.ExprAff(of, new_of), m2_expr.ExprAff(dst, new_dst) ] # Don't generate conditional shifter on constant if isinstance(shifter, m2_expr.ExprInt): if int(shifter) != 0: return (e_do, []) else: return ([], []) e = [] loc_do, loc_do_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) loc_skip = ir.get_next_loc_key(instr) loc_skip_expr = m2_expr.ExprLoc(loc_skip, ir.IRDst.size) e_do.append(m2_expr.ExprAff(ir.IRDst, loc_skip_expr)) e.append(m2_expr.ExprAff( ir.IRDst, m2_expr.ExprCond(shifter, loc_do_expr, loc_skip_expr))) return (e, [IRBlock(loc_do, [AssignBlock(e_do, instr)])]) def rcl(ir, instr, dst, src): return rotate_with_carry_tpl(ir, instr, '<<<', dst, src) def rcr(ir, instr, dst, src): return rotate_with_carry_tpl(ir, instr, '>>>', dst, src) def _shift_tpl(op, ir, instr, a, b, c=None, op_inv=None, left=False, custom_of=None): """Template to generate a shifter with operation @op A temporary basic block is generated to handle 0-shift @op: operation to execute @c (optional): if set, instruction has a bit provider @op_inv (optional): opposite operation of @op. Must be provided if @c @left (optional): indicates a left shift if set, default is False @custom_of (optional): if set, override the computed value of OF """ if c is not None: shifter = get_shift(a, c) else: shifter = get_shift(a, b) res = m2_expr.ExprOp(op, a, shifter) cf_from_dst = m2_expr.ExprOp(op, a, (shifter - m2_expr.ExprInt(1, a.size))) cf_from_dst = cf_from_dst.msb() if left else cf_from_dst[:1] new_cf = cf_from_dst i1 = m2_expr.ExprInt(1, size=a.size) if c is not None: # There is a source for new bits isize = m2_expr.ExprInt(a.size, size=a.size) mask = m2_expr.ExprOp(op_inv, i1, (isize - shifter)) - i1 # An overflow can occured, emulate the 'undefined behavior' # Overflow behavior if (shift / size % 2) base_cond_overflow = c if left else ( c - m2_expr.ExprInt(1, size=c.size)) cond_overflow = base_cond_overflow & m2_expr.ExprInt(a.size, c.size) if left: # Overflow occurs one round before right mask = m2_expr.ExprCond(cond_overflow, mask, ~mask) else: mask = m2_expr.ExprCond(cond_overflow, ~mask, mask) # Build res with dst and src res = ((m2_expr.ExprOp(op, a, shifter) & mask) | (m2_expr.ExprOp(op_inv, b, (isize - shifter)) & ~mask)) # Overflow case: cf come from src (bit number shifter % size) cf_from_src = m2_expr.ExprOp(op, b, (c.zeroExtend(b.size) & m2_expr.ExprInt(a.size - 1, b.size)) - i1) cf_from_src = cf_from_src.msb() if left else cf_from_src[:1] new_cf = m2_expr.ExprCond(cond_overflow, cf_from_src, cf_from_dst) # Overflow flag, only occured when shifter is equal to 1 if custom_of is None: value_of = a.msb() ^ a[-2:-1] if left else b[:1] ^ a.msb() else: value_of = custom_of # Build basic blocks e_do = [ m2_expr.ExprAff(cf, new_cf), m2_expr.ExprAff(of, m2_expr.ExprCond(shifter - i1, m2_expr.ExprInt(0, of.size), value_of)), m2_expr.ExprAff(a, res), ] e_do += update_flag_znp(res) # Don't generate conditional shifter on constant if isinstance(shifter, m2_expr.ExprInt): if int(shifter) != 0: return e_do, [] else: return [], [] e = [] loc_do, loc_do_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) loc_skip = ir.get_next_loc_key(instr) loc_skip_expr = m2_expr.ExprLoc(loc_skip, ir.IRDst.size) e_do.append(m2_expr.ExprAff(ir.IRDst, loc_skip_expr)) e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(shifter, loc_do_expr, loc_skip_expr))) return e, [IRBlock(loc_do, [AssignBlock(e_do, instr)])] def sar(ir, instr, dst, src): # Fixup OF, always cleared if src != 0 i0 = m2_expr.ExprInt(0, size=of.size) return _shift_tpl("a>>", ir, instr, dst, src, custom_of=i0) def shr(ir, instr, dst, src): return _shift_tpl(">>", ir, instr, dst, src, custom_of=dst.msb()) def shrd(ir, instr, dst, src1, src2): return _shift_tpl(">>>", ir, instr, dst, src1, src2, "<<<") def shl(ir, instr, dst, src): return _shift_tpl("<<", ir, instr, dst, src, left=True) def shld(ir, instr, dst, src1, src2): return _shift_tpl("<<<", ir, instr, dst, src1, src2, ">>>", left=True) # XXX todo ### def cmc(_, instr): e = [m2_expr.ExprAff(cf, m2_expr.ExprCond(cf, m2_expr.ExprInt(0, cf.size), m2_expr.ExprInt(1, cf.size)))] return e, [] def clc(_, instr): e = [m2_expr.ExprAff(cf, m2_expr.ExprInt(0, cf.size))] return e, [] def stc(_, instr): e = [m2_expr.ExprAff(cf, m2_expr.ExprInt(1, cf.size))] return e, [] def cld(_, instr): e = [m2_expr.ExprAff(df, m2_expr.ExprInt(0, df.size))] return e, [] def std(_, instr): e = [m2_expr.ExprAff(df, m2_expr.ExprInt(1, df.size))] return e, [] def cli(_, instr): e = [m2_expr.ExprAff(i_f, m2_expr.ExprInt(0, i_f.size))] return e, [] def sti(_, instr): e = [m2_expr.ExprAff(exception_flags, m2_expr.ExprInt(EXCEPT_PRIV_INSN, 32))] return e, [] def inc(_, instr, dst): e = [] src = m2_expr.ExprInt(1, dst.size) arg1, arg2 = dst, src result = dst + src e += update_flag_arith_add_znp(arg1, arg2) e += update_flag_af(arg1, arg2, result) e += update_flag_add_of(arg1, arg2, result) e.append(m2_expr.ExprAff(dst, result)) return e, [] def dec(_, instr, dst): e = [] src = m2_expr.ExprInt(1, dst.size) arg1, arg2 = dst, src result = dst - src e += update_flag_arith_sub_znp(arg1, arg2) e += update_flag_af(arg1, arg2, result) e += update_flag_sub_of(arg1, arg2, result) e.append(m2_expr.ExprAff(dst, result)) return e, [] def push_gen(ir, instr, src, size): e = [] if not size in [16, 32, 64]: raise ValueError('bad size stacker!') if src.size < size: src = src.zeroExtend(size) off_size = src.size sp = mRSP[instr.mode] new_sp = sp - m2_expr.ExprInt(off_size / 8, sp.size) e.append(m2_expr.ExprAff(sp, new_sp)) if ir.do_stk_segm: new_sp = ir.gen_segm_expr(SS, new_sp) e.append(m2_expr.ExprAff(ir.ExprMem(new_sp, off_size), src)) return e, [] def push(ir, instr, src): return push_gen(ir, instr, src, instr.mode) def pushw(ir, instr, src): return push_gen(ir, instr, src, 16) def pop_gen(ir, instr, src, size): e = [] if not size in [16, 32, 64]: raise ValueError('bad size stacker!') sp = mRSP[instr.mode] new_sp = sp + m2_expr.ExprInt(src.size / 8, sp.size) # don't generate ESP incrementation on POP ESP if src != ir.sp: e.append(m2_expr.ExprAff(sp, new_sp)) # XXX FIX XXX for pop [esp] if isinstance(src, m2_expr.ExprMem): src = expr_simp(src.replace_expr({sp: new_sp})) result = sp if ir.do_stk_segm: result = ir.gen_segm_expr(SS, result) e.append(m2_expr.ExprAff(src, ir.ExprMem(result, src.size))) return e, [] def pop(ir, instr, src): return pop_gen(ir, instr, src, instr.mode) def popw(ir, instr, src): return pop_gen(ir, instr, src, 16) def sete(_, instr, dst): e = [] e.append( m2_expr.ExprAff( dst, m2_expr.ExprOp("CC_EQ", zf).zeroExtend(dst.size), ) ) return e, [] def setnz(_, instr, dst): e = [] e.append( m2_expr.ExprAff( dst, m2_expr.ExprOp("CC_EQ", ~zf).zeroExtend(dst.size), ) ) return e, [] def setl(_, instr, dst): e = [] e.append( m2_expr.ExprAff( dst, m2_expr.ExprOp("CC_S<", nf, of).zeroExtend(dst.size), ) ) return e, [] def setg(_, instr, dst): e = [] e.append( m2_expr.ExprAff( dst, m2_expr.ExprOp("CC_S>", nf, of, zf).zeroExtend(dst.size), ) ) return e, [] def setge(_, instr, dst): e = [] e.append( m2_expr.ExprAff( dst, m2_expr.ExprOp("CC_S>=", nf, of).zeroExtend(dst.size), ) ) return e, [] def seta(_, instr, dst): e = [] e.append( m2_expr.ExprAff( dst, m2_expr.ExprOp("CC_U>", cf, zf).zeroExtend(dst.size), ) ) return e, [] def setae(_, instr, dst): e = [] e.append( m2_expr.ExprAff( dst, m2_expr.ExprOp("CC_U>=", cf).zeroExtend(dst.size), ) ) return e, [] def setb(_, instr, dst): e = [] e.append( m2_expr.ExprAff( dst, m2_expr.ExprOp("CC_U<", cf).zeroExtend(dst.size), ) ) return e, [] def setbe(_, instr, dst): e = [] e.append( m2_expr.ExprAff( dst, m2_expr.ExprOp("CC_U<=", cf, zf).zeroExtend(dst.size), ) ) return e, [] def setns(_, instr, dst): e = [] e.append( m2_expr.ExprAff( dst, m2_expr.ExprOp("CC_NEG", ~nf).zeroExtend(dst.size), ) ) return e, [] def sets(_, instr, dst): e = [] e.append( m2_expr.ExprAff( dst, m2_expr.ExprOp("CC_NEG", nf).zeroExtend(dst.size), ) ) return e, [] def seto(_, instr, dst): e = [] e.append( m2_expr.ExprAff( dst, of.zeroExtend(dst.size) ) ) return e, [] def setp(_, instr, dst): e = [] e.append( m2_expr.ExprAff( dst, pf.zeroExtend(dst.size) ) ) return e, [] def setnp(_, instr, dst): e = [] e.append( m2_expr.ExprAff( dst, m2_expr.ExprCond( pf, m2_expr.ExprInt(0, dst.size), m2_expr.ExprInt(1, dst.size) ) ) ) return e, [] def setle(_, instr, dst): e = [] e.append( m2_expr.ExprAff( dst, m2_expr.ExprOp("CC_S<=", nf, of, zf).zeroExtend(dst.size), ) ) return e, [] def setna(_, instr, dst): e = [] e.append( m2_expr.ExprAff( dst, m2_expr.ExprOp("CC_U<=", cf, zf).zeroExtend(dst.size), ) ) return e, [] def setnbe(_, instr, dst): e = [] e.append( m2_expr.ExprAff( dst, m2_expr.ExprOp("CC_U>", cf, zf).zeroExtend(dst.size), ) ) return e, [] def setno(_, instr, dst): e = [] e.append( m2_expr.ExprAff( dst, m2_expr.ExprCond( of, m2_expr.ExprInt(0, dst.size), m2_expr.ExprInt(1, dst.size) ) ) ) return e, [] def setnb(_, instr, dst): e = [] e.append( m2_expr.ExprAff( dst, m2_expr.ExprOp("CC_U>=", cf).zeroExtend(dst.size), ) ) return e, [] def setalc(_, instr): dst = mRAX[instr.mode][0:8] e = [] e.append( m2_expr.ExprAff(dst, m2_expr.ExprCond(cf, m2_expr.ExprInt(0xff, dst.size), m2_expr.ExprInt(0, dst.size)))) return e, [] def bswap(_, instr, dst): e = [] if dst.size == 16: result = m2_expr.ExprCompose(dst[8:16], dst[:8]) elif dst.size == 32: result = m2_expr.ExprCompose( dst[24:32], dst[16:24], dst[8:16], dst[:8]) elif dst.size == 64: result = m2_expr.ExprCompose(dst[56:64], dst[48:56], dst[40:48], dst[32:40], dst[24:32], dst[16:24], dst[8:16], dst[:8]) else: raise ValueError('the size DOES matter') e.append(m2_expr.ExprAff(dst, result)) return e, [] def cmps(ir, instr, size): loc_df_0, loc_df_0_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) loc_df_1, loc_df_1_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) loc_next_expr = m2_expr.ExprLoc(ir.get_next_loc_key(instr), ir.IRDst.size) src1 = mRSI[instr.mode][:instr.v_admode()] src2 = mRDI[instr.mode][:instr.v_admode()] if ir.do_str_segm: if instr.additional_info.g2.value: raise NotImplementedError("add segm support") src1_sgm = ir.gen_segm_expr(DS, src1) src2_sgm = ir.gen_segm_expr(ES, src2) else: src1_sgm = src1 src2_sgm = src2 offset = m2_expr.ExprInt(size / 8, src1.size) e, _ = l_cmp(ir, instr, ir.ExprMem(src1_sgm, size), ir.ExprMem(src2_sgm, size)) e0 = [] e0.append(m2_expr.ExprAff(src1, src1 + offset)) e0.append(m2_expr.ExprAff(src2, src2 + offset)) e0.append(m2_expr.ExprAff(ir.IRDst, loc_next_expr)) e0 = IRBlock(loc_df_0, [AssignBlock(e0, instr)]) e1 = [] e1.append(m2_expr.ExprAff(src1, src1 - offset)) e1.append(m2_expr.ExprAff(src2, src2 - offset)) e1.append(m2_expr.ExprAff(ir.IRDst, loc_next_expr)) e1 = IRBlock(loc_df_1, [AssignBlock(e1, instr)]) e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(df, loc_df_1_expr, loc_df_0_expr))) return e, [e0, e1] def scas(ir, instr, size): loc_df_0, loc_df_0_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) loc_df_1, loc_df_1_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) loc_next_expr = m2_expr.ExprLoc(ir.get_next_loc_key(instr), ir.IRDst.size) src = mRDI[instr.mode][:instr.v_admode()] if ir.do_str_segm: if instr.additional_info.g2.value: raise NotImplementedError("add segm support") src_sgm = ir.gen_segm_expr(ES, src) else: src_sgm = src offset = m2_expr.ExprInt(size / 8, src.size) e, extra = l_cmp(ir, instr, mRAX[instr.mode][:size], ir.ExprMem(src_sgm, size)) e0 = [] e0.append(m2_expr.ExprAff(src, src + offset)) e0.append(m2_expr.ExprAff(ir.IRDst, loc_next_expr)) e0 = IRBlock(loc_df_0, [AssignBlock(e0, instr)]) e1 = [] e1.append(m2_expr.ExprAff(src, src - offset)) e1.append(m2_expr.ExprAff(ir.IRDst, loc_next_expr)) e1 = IRBlock(loc_df_1, [AssignBlock(e1, instr)]) e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(df, loc_df_1_expr, loc_df_0_expr))) return e, [e0, e1] def compose_eflag(s=32): args = [] args = [cf, m2_expr.ExprInt(1, 1), pf, m2_expr.ExprInt(0, 1), af, m2_expr.ExprInt(0, 1), zf, nf, tf, i_f, df, of, iopl] if s == 32: args += [nt, m2_expr.ExprInt(0, 1), rf, vm, ac, vif, vip, i_d] elif s == 16: args += [nt, m2_expr.ExprInt(0, 1)] else: raise ValueError('unk size') if s == 32: args.append(m2_expr.ExprInt(0, 10)) return m2_expr.ExprCompose(*args) def pushfd(ir, instr): return push(ir, instr, compose_eflag()) def pushfq(ir, instr): return push(ir, instr, compose_eflag().zeroExtend(64)) def pushfw(ir, instr): return pushw(ir, instr, compose_eflag(16)) def popfd(ir, instr): tmp = ir.ExprMem(mRSP[instr.mode], 32) e = [] e.append(m2_expr.ExprAff(cf, m2_expr.ExprSlice(tmp, 0, 1))) e.append(m2_expr.ExprAff(pf, m2_expr.ExprSlice(tmp, 2, 3))) e.append(m2_expr.ExprAff(af, m2_expr.ExprSlice(tmp, 4, 5))) e.append(m2_expr.ExprAff(zf, m2_expr.ExprSlice(tmp, 6, 7))) e.append(m2_expr.ExprAff(nf, m2_expr.ExprSlice(tmp, 7, 8))) e.append(m2_expr.ExprAff(tf, m2_expr.ExprSlice(tmp, 8, 9))) e.append(m2_expr.ExprAff(i_f, m2_expr.ExprSlice(tmp, 9, 10))) e.append(m2_expr.ExprAff(df, m2_expr.ExprSlice(tmp, 10, 11))) e.append(m2_expr.ExprAff(of, m2_expr.ExprSlice(tmp, 11, 12))) e.append(m2_expr.ExprAff(iopl, m2_expr.ExprSlice(tmp, 12, 14))) e.append(m2_expr.ExprAff(nt, m2_expr.ExprSlice(tmp, 14, 15))) e.append(m2_expr.ExprAff(rf, m2_expr.ExprSlice(tmp, 16, 17))) e.append(m2_expr.ExprAff(vm, m2_expr.ExprSlice(tmp, 17, 18))) e.append(m2_expr.ExprAff(ac, m2_expr.ExprSlice(tmp, 18, 19))) e.append(m2_expr.ExprAff(vif, m2_expr.ExprSlice(tmp, 19, 20))) e.append(m2_expr.ExprAff(vip, m2_expr.ExprSlice(tmp, 20, 21))) e.append(m2_expr.ExprAff(i_d, m2_expr.ExprSlice(tmp, 21, 22))) e.append(m2_expr.ExprAff(mRSP[instr.mode], mRSP[instr.mode] + m2_expr.ExprInt(instr.mode / 8, mRSP[instr.mode].size))) e.append(m2_expr.ExprAff(exception_flags, m2_expr.ExprCond(m2_expr.ExprSlice(tmp, 8, 9), m2_expr.ExprInt( EXCEPT_SOFT_BP, 32), exception_flags ) ) ) return e, [] def _tpl_eflags(tmp): """Extract eflags from @tmp @tmp: Expr instance with a size >= 16 """ return [m2_expr.ExprAff(dest, tmp[base:base + dest.size]) for base, dest in ((0, cf), (2, pf), (4, af), (6, zf), (7, nf), (8, tf), (9, i_f), (10, df), (11, of), (12, iopl), (14, nt))] def popfw(ir, instr): tmp = ir.ExprMem(mRSP[instr.mode], 32) e = _tpl_eflags(tmp) e.append( m2_expr.ExprAff(mRSP[instr.mode], mRSP[instr.mode] + m2_expr.ExprInt(2, mRSP[instr.mode].size))) return e, [] pa_regs = [ mRAX, mRCX, mRDX, mRBX, mRSP, mRBP, mRSI, mRDI ] def pusha_gen(ir, instr, size): e = [] cur_sp = mRSP[instr.mode] for i, reg in enumerate(pa_regs): stk_ptr = cur_sp + m2_expr.ExprInt(-(size / 8) * (i + 1), instr.mode) e.append(m2_expr.ExprAff(ir.ExprMem(stk_ptr, size), reg[size])) e.append(m2_expr.ExprAff(cur_sp, stk_ptr)) return e, [] def pusha(ir, instr): return pusha_gen(ir, instr, 16) def pushad(ir, instr): return pusha_gen(ir, instr, 32) def popa_gen(ir, instr, size): e = [] cur_sp = mRSP[instr.mode] for i, reg in enumerate(reversed(pa_regs)): if reg == mRSP: continue stk_ptr = cur_sp + m2_expr.ExprInt((size / 8) * i, instr.mode) e.append(m2_expr.ExprAff(reg[size], ir.ExprMem(stk_ptr, size))) stk_ptr = cur_sp + m2_expr.ExprInt((size / 8) * (i + 1), instr.mode) e.append(m2_expr.ExprAff(cur_sp, stk_ptr)) return e, [] def popa(ir, instr): return popa_gen(ir, instr, 16) def popad(ir, instr): return popa_gen(ir, instr, 32) def call(ir, instr, dst): e = [] # opmode, admode = instr.opmode, instr.admode s = dst.size meip = mRIP[ir.IRDst.size] opmode, admode = s, instr.v_admode() myesp = mRSP[instr.mode][:opmode] n = m2_expr.ExprLoc(ir.get_next_loc_key(instr), ir.IRDst.size) if isinstance(dst, m2_expr.ExprOp): if dst.op == "segm": # Far call segm:addr if instr.mode not in [16, 32]: raise RuntimeError('not supported') segm = dst.args[0] base = dst.args[1] m1 = segm.zeroExtend(CS.size) m2 = base.zeroExtend(meip.size) elif dst.op == "far": # Far call far [eax] addr = dst.args[0].arg m1 = ir.ExprMem(addr, CS.size) m2 = ir.ExprMem(addr + m2_expr.ExprInt(2, addr.size), meip.size) else: raise RuntimeError("bad call operator") e.append(m2_expr.ExprAff(CS, m1)) e.append(m2_expr.ExprAff(meip, m2)) e.append(m2_expr.ExprAff(ir.IRDst, m2)) c = myesp + m2_expr.ExprInt(-s / 8, s) e.append(m2_expr.ExprAff(ir.ExprMem(c, size=s).zeroExtend(s), CS.zeroExtend(s))) c = myesp + m2_expr.ExprInt(-2 * s / 8, s) e.append(m2_expr.ExprAff(ir.ExprMem(c, size=s).zeroExtend(s), meip.zeroExtend(s))) c = myesp + m2_expr.ExprInt((-2 * s) / 8, s) e.append(m2_expr.ExprAff(myesp, c)) return e, [] c = myesp + m2_expr.ExprInt((-s / 8), s) e.append(m2_expr.ExprAff(myesp, c)) if ir.do_stk_segm: c = ir.gen_segm_expr(SS, c) e.append(m2_expr.ExprAff(ir.ExprMem(c, size=s), n)) e.append(m2_expr.ExprAff(meip, dst.zeroExtend(ir.IRDst.size))) e.append(m2_expr.ExprAff(ir.IRDst, dst.zeroExtend(ir.IRDst.size))) return e, [] def ret(ir, instr, src=None): e = [] meip = mRIP[ir.IRDst.size] size, admode = instr.v_opmode(), instr.v_admode() myesp = mRSP[instr.mode][:size] if src is None: src = m2_expr.ExprInt(0, size) value = (myesp + (m2_expr.ExprInt((size / 8), size))) else: src = m2_expr.ExprInt(int(src), size) value = (myesp + (m2_expr.ExprInt((size / 8), size) + src)) e.append(m2_expr.ExprAff(myesp, value)) result = myesp if ir.do_stk_segm: result = ir.gen_segm_expr(SS, result) e.append(m2_expr.ExprAff(meip, ir.ExprMem( result, size=size).zeroExtend(size))) e.append(m2_expr.ExprAff(ir.IRDst, ir.ExprMem(result, size=size).zeroExtend(size))) return e, [] def retf(ir, instr, src=None): e = [] meip = mRIP[ir.IRDst.size] size, admode = instr.v_opmode(), instr.v_admode() if src is None: src = m2_expr.ExprInt(0, instr.mode) myesp = mRSP[instr.mode][:size] src = src.zeroExtend(size) result = myesp if ir.do_stk_segm: result = ir.gen_segm_expr(SS, result) e.append(m2_expr.ExprAff(meip, ir.ExprMem( result, size=size).zeroExtend(size))) e.append(m2_expr.ExprAff(ir.IRDst, ir.ExprMem(result, size=size).zeroExtend(size))) # e.append(m2_expr.ExprAff(meip, ir.ExprMem(c, size = s))) result = myesp + m2_expr.ExprInt(size / 8, size) if ir.do_stk_segm: result = ir.gen_segm_expr(SS, result) e.append(m2_expr.ExprAff(CS, ir.ExprMem(result, size=16))) value = myesp + (m2_expr.ExprInt((2 * size) / 8, size) + src) e.append(m2_expr.ExprAff(myesp, value)) return e, [] def leave(ir, instr): opmode, admode = instr.v_opmode(), instr.v_admode() size = instr.mode myesp = mRSP[size] e = [] e.append(m2_expr.ExprAff(mRBP[size], ir.ExprMem(mRBP[size], size=size))) e.append(m2_expr.ExprAff(myesp, m2_expr.ExprInt(size / 8, size) + mRBP[size])) return e, [] def enter(ir, instr, src1, src2): size, admode = instr.v_opmode(), instr.v_admode() myesp = mRSP[instr.mode][:size] myebp = mRBP[instr.mode][:size] src1 = src1.zeroExtend(size) e = [] esp_tmp = myesp - m2_expr.ExprInt(size / 8, size) e.append(m2_expr.ExprAff(ir.ExprMem(esp_tmp, size=size), myebp)) e.append(m2_expr.ExprAff(myebp, esp_tmp)) e.append(m2_expr.ExprAff(myesp, myesp - (src1 + m2_expr.ExprInt(size / 8, size)))) return e, [] def jmp(ir, instr, dst): e = [] meip = mRIP[ir.IRDst.size] if isinstance(dst, m2_expr.ExprOp): if dst.op == "segm": # Far jmp segm:addr segm = dst.args[0] base = dst.args[1] m1 = segm.zeroExtend(CS.size) m2 = base.zeroExtend(meip.size) elif dst.op == "far": # Far jmp far [eax] addr = dst.args[0].arg m1 = ir.ExprMem(addr, CS.size) m2 = ir.ExprMem(addr + m2_expr.ExprInt(2, addr.size), meip.size) else: raise RuntimeError("bad jmp operator") e.append(m2_expr.ExprAff(CS, m1)) e.append(m2_expr.ExprAff(meip, m2)) e.append(m2_expr.ExprAff(ir.IRDst, m2)) else: # Classic jmp e.append(m2_expr.ExprAff(meip, dst)) e.append(m2_expr.ExprAff(ir.IRDst, dst)) if isinstance(dst, m2_expr.ExprMem): dst = meip return e, [] def jz(ir, instr, dst): #return gen_jcc(ir, instr, zf, dst, True) return gen_jcc(ir, instr, m2_expr.ExprOp("CC_EQ", zf), dst, True) def jcxz(ir, instr, dst): return gen_jcc(ir, instr, mRCX[instr.mode][:16], dst, False) def jecxz(ir, instr, dst): return gen_jcc(ir, instr, mRCX[instr.mode][:32], dst, False) def jrcxz(ir, instr, dst): return gen_jcc(ir, instr, mRCX[instr.mode], dst, False) def jnz(ir, instr, dst): #return gen_jcc(ir, instr, zf, dst, False) return gen_jcc(ir, instr, m2_expr.ExprOp("CC_EQ", zf), dst, False) def jp(ir, instr, dst): return gen_jcc(ir, instr, pf, dst, True) def jnp(ir, instr, dst): return gen_jcc(ir, instr, pf, dst, False) def ja(ir, instr, dst): #return gen_jcc(ir, instr, cf | zf, dst, False) return gen_jcc(ir, instr, m2_expr.ExprOp("CC_U>", cf, zf), dst, True) def jae(ir, instr, dst): #return gen_jcc(ir, instr, cf, dst, False) return gen_jcc(ir, instr, m2_expr.ExprOp("CC_U>=", cf), dst, True) def jb(ir, instr, dst): #return gen_jcc(ir, instr, cf, dst, True) return gen_jcc(ir, instr, m2_expr.ExprOp("CC_U<", cf), dst, True) def jbe(ir, instr, dst): #return gen_jcc(ir, instr, cf | zf, dst, True) return gen_jcc(ir, instr, m2_expr.ExprOp("CC_U<=", cf, zf), dst, True) def jge(ir, instr, dst): #return gen_jcc(ir, instr, nf - of, dst, False) return gen_jcc(ir, instr, m2_expr.ExprOp("CC_S>=", nf, of), dst, True) def jg(ir, instr, dst): #return gen_jcc(ir, instr, zf | (nf - of), dst, False) return gen_jcc(ir, instr, m2_expr.ExprOp("CC_S>", nf, of, zf), dst, True) def jl(ir, instr, dst): #return gen_jcc(ir, instr, nf - of, dst, True) return gen_jcc(ir, instr, m2_expr.ExprOp("CC_S<", nf, of), dst, True) def jle(ir, instr, dst): #return gen_jcc(ir, instr, zf | (nf - of), dst, True) return gen_jcc(ir, instr, m2_expr.ExprOp("CC_S<=", nf, of, zf), dst, True) def js(ir, instr, dst): #return gen_jcc(ir, instr, nf, dst, True) return gen_jcc(ir, instr, m2_expr.ExprOp("CC_NEG", nf), dst, True) def jns(ir, instr, dst): #return gen_jcc(ir, instr, nf, dst, False) return gen_jcc(ir, instr, m2_expr.ExprOp("CC_NEG", nf), dst, False) def jo(ir, instr, dst): return gen_jcc(ir, instr, of, dst, True) def jno(ir, instr, dst): return gen_jcc(ir, instr, of, dst, False) def loop(ir, instr, dst): e = [] meip = mRIP[ir.IRDst.size] admode = instr.v_admode() myecx = mRCX[instr.mode][:admode] n = m2_expr.ExprLoc(ir.get_next_loc_key(instr), ir.IRDst.size) c = myecx - m2_expr.ExprInt(1, myecx.size) dst_o = m2_expr.ExprCond(c, dst.zeroExtend(ir.IRDst.size), n.zeroExtend(ir.IRDst.size)) e.append(m2_expr.ExprAff(myecx, c)) e.append(m2_expr.ExprAff(meip, dst_o)) e.append(m2_expr.ExprAff(ir.IRDst, dst_o)) return e, [] def loopne(ir, instr, dst): e = [] meip = mRIP[ir.IRDst.size] admode = instr.v_admode() myecx = mRCX[instr.mode][:admode] n = m2_expr.ExprLoc(ir.get_next_loc_key(instr), ir.IRDst.size) c = m2_expr.ExprCond(myecx - m2_expr.ExprInt(1, size=myecx.size), m2_expr.ExprInt(1, 1), m2_expr.ExprInt(0, 1)) c &= zf ^ m2_expr.ExprInt(1, 1) e.append(m2_expr.ExprAff(myecx, myecx - m2_expr.ExprInt(1, myecx.size))) dst_o = m2_expr.ExprCond(c, dst.zeroExtend(ir.IRDst.size), n.zeroExtend(ir.IRDst.size)) e.append(m2_expr.ExprAff(meip, dst_o)) e.append(m2_expr.ExprAff(ir.IRDst, dst_o)) return e, [] def loope(ir, instr, dst): e = [] meip = mRIP[ir.IRDst.size] admode = instr.v_admode() myecx = mRCX[instr.mode][:admode] n = m2_expr.ExprLoc(ir.get_next_loc_key(instr), ir.IRDst.size) c = m2_expr.ExprCond(myecx - m2_expr.ExprInt(1, size=myecx.size), m2_expr.ExprInt(1, 1), m2_expr.ExprInt(0, 1)) c &= zf e.append(m2_expr.ExprAff(myecx, myecx - m2_expr.ExprInt(1, myecx.size))) dst_o = m2_expr.ExprCond(c, dst.zeroExtend(ir.IRDst.size), n.zeroExtend(ir.IRDst.size)) e.append(m2_expr.ExprAff(meip, dst_o)) e.append(m2_expr.ExprAff(ir.IRDst, dst_o)) return e, [] # XXX size to do; eflag def div(ir, instr, src1): e = [] size = src1.size if size == 8: src2 = mRAX[instr.mode][:16] elif size in [16, 32, 64]: s1, s2 = mRDX[size], mRAX[size] src2 = m2_expr.ExprCompose(s2, s1) else: raise ValueError('div arg not impl', src1) c_d = m2_expr.ExprOp('udiv', src2, src1.zeroExtend(src2.size)) c_r = m2_expr.ExprOp('umod', src2, src1.zeroExtend(src2.size)) # if 8 bit div, only ax is affected if size == 8: e.append(m2_expr.ExprAff(src2, m2_expr.ExprCompose(c_d[:8], c_r[:8]))) else: e.append(m2_expr.ExprAff(s1, c_r[:size])) e.append(m2_expr.ExprAff(s2, c_d[:size])) loc_div, loc_div_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) loc_except, loc_except_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) loc_next = ir.get_next_loc_key(instr) loc_next_expr = m2_expr.ExprLoc(loc_next, ir.IRDst.size) do_div = [] do_div += e do_div.append(m2_expr.ExprAff(ir.IRDst, loc_next_expr)) blk_div = IRBlock(loc_div, [AssignBlock(do_div, instr)]) do_except = [] do_except.append(m2_expr.ExprAff(exception_flags, m2_expr.ExprInt( EXCEPT_DIV_BY_ZERO, exception_flags.size))) do_except.append(m2_expr.ExprAff(ir.IRDst, loc_next_expr)) blk_except = IRBlock(loc_except, [AssignBlock(do_except, instr)]) e = [] e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(src1, loc_div_expr, loc_except_expr))) return e, [blk_div, blk_except] # XXX size to do; eflag def idiv(ir, instr, src1): e = [] size = src1.size if size == 8: src2 = mRAX[instr.mode][:16] elif size in [16, 32, 64]: s1, s2 = mRDX[size], mRAX[size] src2 = m2_expr.ExprCompose(s2, s1) else: raise ValueError('div arg not impl', src1) c_d = m2_expr.ExprOp('idiv', src2, src1.signExtend(src2.size)) c_r = m2_expr.ExprOp('imod', src2, src1.signExtend(src2.size)) # if 8 bit div, only ax is affected if size == 8: e.append(m2_expr.ExprAff(src2, m2_expr.ExprCompose(c_d[:8], c_r[:8]))) else: e.append(m2_expr.ExprAff(s1, c_r[:size])) e.append(m2_expr.ExprAff(s2, c_d[:size])) loc_div, loc_div_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) loc_except, loc_except_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) loc_next = ir.get_next_loc_key(instr) loc_next_expr = m2_expr.ExprLoc(loc_next, ir.IRDst.size) do_div = [] do_div += e do_div.append(m2_expr.ExprAff(ir.IRDst, loc_next_expr)) blk_div = IRBlock(loc_div, [AssignBlock(do_div, instr)]) do_except = [] do_except.append(m2_expr.ExprAff(exception_flags, m2_expr.ExprInt( EXCEPT_DIV_BY_ZERO, exception_flags.size))) do_except.append(m2_expr.ExprAff(ir.IRDst, loc_next_expr)) blk_except = IRBlock(loc_except, [AssignBlock(do_except, instr)]) e = [] e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(src1, loc_div_expr, loc_except_expr))) return e, [blk_div, blk_except] # XXX size to do; eflag def mul(_, instr, src1): e = [] size = src1.size if src1.size in [16, 32, 64]: result = m2_expr.ExprOp('*', mRAX[size].zeroExtend(size * 2), src1.zeroExtend(size * 2)) e.append(m2_expr.ExprAff(mRAX[size], result[:size])) e.append(m2_expr.ExprAff(mRDX[size], result[size:size * 2])) elif src1.size == 8: result = m2_expr.ExprOp('*', mRAX[instr.mode][:8].zeroExtend(16), src1.zeroExtend(16)) e.append(m2_expr.ExprAff(mRAX[instr.mode][:16], result)) else: raise ValueError('unknow size') e.append(m2_expr.ExprAff(of, m2_expr.ExprCond(result[size:size * 2], m2_expr.ExprInt(1, 1), m2_expr.ExprInt(0, 1)))) e.append(m2_expr.ExprAff(cf, m2_expr.ExprCond(result[size:size * 2], m2_expr.ExprInt(1, 1), m2_expr.ExprInt(0, 1)))) return e, [] def imul(_, instr, src1, src2=None, src3=None): e = [] size = src1.size if src2 is None: if size in [16, 32, 64]: result = m2_expr.ExprOp('*', mRAX[size].signExtend(size * 2), src1.signExtend(size * 2)) e.append(m2_expr.ExprAff(mRAX[size], result[:size])) e.append(m2_expr.ExprAff(mRDX[size], result[size:size * 2])) elif size == 8: dst = mRAX[instr.mode][:16] result = m2_expr.ExprOp('*', mRAX[instr.mode][:8].signExtend(16), src1.signExtend(16)) e.append(m2_expr.ExprAff(dst, result)) value = m2_expr.ExprCond(result - result[:size].signExtend(size * 2), m2_expr.ExprInt(1, 1), m2_expr.ExprInt(0, 1)) e.append(m2_expr.ExprAff(cf, value)) value = m2_expr.ExprCond(result - result[:size].signExtend(size * 2), m2_expr.ExprInt(1, 1), m2_expr.ExprInt(0, 1)) e.append(m2_expr.ExprAff(of, value)) else: if src3 is None: src3 = src2 src2 = src1 result = m2_expr.ExprOp('*', src2.signExtend(size * 2), src3.signExtend(size * 2)) e.append(m2_expr.ExprAff(src1, result[:size])) value = m2_expr.ExprCond(result - result[:size].signExtend(size * 2), m2_expr.ExprInt(1, 1), m2_expr.ExprInt(0, 1)) e.append(m2_expr.ExprAff(cf, value)) value = m2_expr.ExprCond(result - result[:size].signExtend(size * 2), m2_expr.ExprInt(1, 1), m2_expr.ExprInt(0, 1)) e.append(m2_expr.ExprAff(of, value)) return e, [] def cbw(_, instr): # Only in 16 bit e = [] tempAL = mRAX[instr.v_opmode()][:8] tempAX = mRAX[instr.v_opmode()][:16] e.append(m2_expr.ExprAff(tempAX, tempAL.signExtend(16))) return e, [] def cwde(_, instr): # Only in 32/64 bit e = [] tempAX = mRAX[instr.v_opmode()][:16] tempEAX = mRAX[instr.v_opmode()][:32] e.append(m2_expr.ExprAff(tempEAX, tempAX.signExtend(32))) return e, [] def cdqe(_, instr): # Only in 64 bit e = [] tempEAX = mRAX[instr.mode][:32] tempRAX = mRAX[instr.mode][:64] e.append(m2_expr.ExprAff(tempRAX, tempEAX.signExtend(64))) return e, [] def cwd(_, instr): # Only in 16 bit e = [] tempAX = mRAX[instr.mode][:16] tempDX = mRDX[instr.mode][:16] result = tempAX.signExtend(32) e.append(m2_expr.ExprAff(tempAX, result[:16])) e.append(m2_expr.ExprAff(tempDX, result[16:32])) return e, [] def cdq(_, instr): # Only in 32/64 bit e = [] tempEAX = mRAX[instr.v_opmode()] tempEDX = mRDX[instr.v_opmode()] result = tempEAX.signExtend(64) e.append(m2_expr.ExprAff(tempEDX, result[32:64])) return e, [] def cqo(_, instr): # Only in 64 bit e = [] tempRAX = mRAX[instr.mode][:64] tempRDX = mRDX[instr.mode][:64] result = tempRAX.signExtend(128) e.append(m2_expr.ExprAff(tempRAX, result[:64])) e.append(m2_expr.ExprAff(tempRDX, result[64:128])) return e, [] def stos(ir, instr, size): loc_df_0, loc_df_0_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) loc_df_1, loc_df_1_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) loc_next_expr = m2_expr.ExprLoc(ir.get_next_loc_key(instr), ir.IRDst.size) addr_o = mRDI[instr.mode][:instr.v_admode()] addr = addr_o addr_p = addr + m2_expr.ExprInt(size / 8, addr.size) addr_m = addr - m2_expr.ExprInt(size / 8, addr.size) if ir.do_str_segm: mss = ES if instr.additional_info.g2.value: raise NotImplementedError("add segm support") addr = ir.gen_segm_expr(mss, addr) b = mRAX[instr.mode][:size] e0 = [] e0.append(m2_expr.ExprAff(addr_o, addr_p)) e0.append(m2_expr.ExprAff(ir.IRDst, loc_next_expr)) e0 = IRBlock(loc_df_0, [AssignBlock(e0, instr)]) e1 = [] e1.append(m2_expr.ExprAff(addr_o, addr_m)) e1.append(m2_expr.ExprAff(ir.IRDst, loc_next_expr)) e1 = IRBlock(loc_df_1, [AssignBlock(e1, instr)]) e = [] e.append(m2_expr.ExprAff(ir.ExprMem(addr, size), b)) e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(df, loc_df_1_expr, loc_df_0_expr))) return e, [e0, e1] def lods(ir, instr, size): loc_df_0, loc_df_0_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) loc_df_1, loc_df_1_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) loc_next_expr = m2_expr.ExprLoc(ir.get_next_loc_key(instr), ir.IRDst.size) e = [] addr_o = mRSI[instr.mode][:instr.v_admode()] addr = addr_o addr_p = addr + m2_expr.ExprInt(size / 8, addr.size) addr_m = addr - m2_expr.ExprInt(size / 8, addr.size) if ir.do_str_segm: mss = DS if instr.additional_info.g2.value: raise NotImplementedError("add segm support") addr = ir.gen_segm_expr(mss, addr) b = mRAX[instr.mode][:size] e0 = [] e0.append(m2_expr.ExprAff(addr_o, addr_p)) e0.append(m2_expr.ExprAff(ir.IRDst, loc_next_expr)) e0 = IRBlock(loc_df_0, [AssignBlock(e0, instr)]) e1 = [] e1.append(m2_expr.ExprAff(addr_o, addr_m)) e1.append(m2_expr.ExprAff(ir.IRDst, loc_next_expr)) e1 = IRBlock(loc_df_1, [AssignBlock(e1, instr)]) e = [] if instr.mode == 64 and b.size == 32: e.append(m2_expr.ExprAff(mRAX[instr.mode], ir.ExprMem(addr, size).zeroExtend(64))) else: e.append(m2_expr.ExprAff(b, ir.ExprMem(addr, size))) e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(df, loc_df_1_expr, loc_df_0_expr))) return e, [e0, e1] def movs(ir, instr, size): loc_df_0, loc_df_0_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) loc_df_1, loc_df_1_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) loc_next_expr = m2_expr.ExprLoc(ir.get_next_loc_key(instr), ir.IRDst.size) dst = mRDI[instr.mode][:instr.v_admode()] src = mRSI[instr.mode][:instr.v_admode()] e = [] if ir.do_str_segm: if instr.additional_info.g2.value: raise NotImplementedError("add segm support") src_sgm = ir.gen_segm_expr(DS, src) dst_sgm = ir.gen_segm_expr(ES, dst) else: src_sgm = src dst_sgm = dst offset = m2_expr.ExprInt(size / 8, src.size) e.append(m2_expr.ExprAff(ir.ExprMem(dst_sgm, size), ir.ExprMem(src_sgm, size))) e0 = [] e0.append(m2_expr.ExprAff(src, src + offset)) e0.append(m2_expr.ExprAff(dst, dst + offset)) e0.append(m2_expr.ExprAff(ir.IRDst, loc_next_expr)) e0 = IRBlock(loc_df_0, [AssignBlock(e0, instr)]) e1 = [] e1.append(m2_expr.ExprAff(src, src - offset)) e1.append(m2_expr.ExprAff(dst, dst - offset)) e1.append(m2_expr.ExprAff(ir.IRDst, loc_next_expr)) e1 = IRBlock(loc_df_1, [AssignBlock(e1, instr)]) e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(df, loc_df_1_expr, loc_df_0_expr))) return e, [e0, e1] def movsd(_, instr, dst, src): # 64 bits access if dst.is_id() and src.is_id(): src = src[:64] dst = dst[:64] elif dst.is_mem() and src.is_id(): dst = m2_expr.ExprMem(dst.arg, 64) src = src[:64] else: src = m2_expr.ExprMem(src.arg, 64) # Erase dst high bits src = src.zeroExtend(dst.size) return [m2_expr.ExprAff(dst, src)], [] def movsd_dispatch(ir, instr, dst=None, src=None): if dst is None and src is None: return movs(ir, instr, 32) else: return movsd(ir, instr, dst, src) def float_prev(flt, popcount=1): if not flt in float_list: return None i = float_list.index(flt) if i < popcount: # Drop value (ex: FSTP ST(0)) return None flt = float_list[i - popcount] return flt def float_pop(avoid_flt=None, popcount=1): """ Generate floatpop semantic (@popcount times), avoiding the avoid_flt@ float @avoid_flt: float avoided in the generated semantic @popcount: pop count """ avoid_flt = float_prev(avoid_flt, popcount) e = [] for i in xrange(8 - popcount): if avoid_flt != float_list[i]: e.append(m2_expr.ExprAff(float_list[i], float_list[i + popcount])) fill_value = m2_expr.ExprOp("sint_to_fp64", m2_expr.ExprInt(0, float_list[i].size)) for i in xrange(8 - popcount, 8): e.append(m2_expr.ExprAff(float_list[i], fill_value)) e.append( m2_expr.ExprAff(float_stack_ptr, float_stack_ptr - m2_expr.ExprInt(popcount, 3))) return e # XXX TODO def fcom(_, instr, dst=None, src=None): if dst is None and src is None: dst, src = float_st0, float_st1 elif src is None: src = mem2double(instr, dst) dst = float_st0 e = [] e.append(m2_expr.ExprAff(float_c0, m2_expr.ExprOp('fcom_c0', dst, src))) e.append(m2_expr.ExprAff(float_c1, m2_expr.ExprOp('fcom_c1', dst, src))) e.append(m2_expr.ExprAff(float_c2, m2_expr.ExprOp('fcom_c2', dst, src))) e.append(m2_expr.ExprAff(float_c3, m2_expr.ExprOp('fcom_c3', dst, src))) e += set_float_cs_eip(instr) return e, [] def ftst(_, instr): dst = float_st0 e = [] src = m2_expr.ExprOp('sint_to_fp64', m2_expr.ExprInt(0, 32)) e.append(m2_expr.ExprAff(float_c0, m2_expr.ExprOp('fcom_c0', dst, src))) e.append(m2_expr.ExprAff(float_c1, m2_expr.ExprOp('fcom_c1', dst, src))) e.append(m2_expr.ExprAff(float_c2, m2_expr.ExprOp('fcom_c2', dst, src))) e.append(m2_expr.ExprAff(float_c3, m2_expr.ExprOp('fcom_c3', dst, src))) e += set_float_cs_eip(instr) return e, [] def fxam(_, instr): dst = float_st0 e = [] e.append(m2_expr.ExprAff(float_c0, m2_expr.ExprOp('fxam_c0', dst))) e.append(m2_expr.ExprAff(float_c1, m2_expr.ExprOp('fxam_c1', dst))) e.append(m2_expr.ExprAff(float_c2, m2_expr.ExprOp('fxam_c2', dst))) e.append(m2_expr.ExprAff(float_c3, m2_expr.ExprOp('fxam_c3', dst))) e += set_float_cs_eip(instr) return e, [] def ficom(_, instr, dst, src=None): dst, src = float_implicit_st0(dst, src) e = [] e.append(m2_expr.ExprAff(float_c0, m2_expr.ExprOp('fcom_c0', dst, src.zeroExtend(dst.size)))) e.append(m2_expr.ExprAff(float_c1, m2_expr.ExprOp('fcom_c1', dst, src.zeroExtend(dst.size)))) e.append(m2_expr.ExprAff(float_c2, m2_expr.ExprOp('fcom_c2', dst, src.zeroExtend(dst.size)))) e.append(m2_expr.ExprAff(float_c3, m2_expr.ExprOp('fcom_c3', dst, src.zeroExtend(dst.size)))) e += set_float_cs_eip(instr) return e, [] def fcomi(_, instr, dst=None, src=None): # TODO unordered float if dst is None and src is None: dst, src = float_st0, float_st1 elif src is None: src = dst dst = float_st0 e = [] e.append(m2_expr.ExprAff(cf, m2_expr.ExprOp('fcom_c0', dst, src))) e.append(m2_expr.ExprAff(pf, m2_expr.ExprOp('fcom_c2', dst, src))) e.append(m2_expr.ExprAff(zf, m2_expr.ExprOp('fcom_c3', dst, src))) e.append(m2_expr.ExprAff(of, m2_expr.ExprInt(0, 1))) e.append(m2_expr.ExprAff(nf, m2_expr.ExprInt(0, 1))) e.append(m2_expr.ExprAff(af, m2_expr.ExprInt(0, 1))) e += set_float_cs_eip(instr) return e, [] def fcomip(ir, instr, dst=None, src=None): e, extra = fcomi(ir, instr, dst, src) e += float_pop() e += set_float_cs_eip(instr) return e, extra def fucomi(ir, instr, dst=None, src=None): # TODO unordered float return fcomi(ir, instr, dst, src) def fucomip(ir, instr, dst=None, src=None): # TODO unordered float return fcomip(ir, instr, dst, src) def fcomp(ir, instr, dst=None, src=None): e, extra = fcom(ir, instr, dst, src) e += float_pop() e += set_float_cs_eip(instr) return e, extra def fcompp(ir, instr, dst=None, src=None): e, extra = fcom(ir, instr, dst, src) e += float_pop(popcount=2) e += set_float_cs_eip(instr) return e, extra def ficomp(ir, instr, dst, src=None): e, extra = ficom(ir, instr, dst, src) e += float_pop() e += set_float_cs_eip(instr) return e, extra def fucom(ir, instr, dst=None, src=None): # TODO unordered float return fcom(ir, instr, dst, src) def fucomp(ir, instr, dst=None, src=None): # TODO unordered float return fcomp(ir, instr, dst, src) def fucompp(ir, instr, dst=None, src=None): # TODO unordered float return fcompp(ir, instr, dst, src) def comiss(_, instr, dst, src): # TODO unordered float e = [] dst = m2_expr.ExprOp('sint_to_fp32', dst[:32]) src = m2_expr.ExprOp('sint_to_fp32', src[:32]) e.append(m2_expr.ExprAff(cf, m2_expr.ExprOp('fcom_c0', dst, src))) e.append(m2_expr.ExprAff(pf, m2_expr.ExprOp('fcom_c2', dst, src))) e.append(m2_expr.ExprAff(zf, m2_expr.ExprOp('fcom_c3', dst, src))) e.append(m2_expr.ExprAff(of, m2_expr.ExprInt(0, 1))) e.append(m2_expr.ExprAff(nf, m2_expr.ExprInt(0, 1))) e.append(m2_expr.ExprAff(af, m2_expr.ExprInt(0, 1))) e += set_float_cs_eip(instr) return e, [] def comisd(_, instr, dst, src): # TODO unordered float e = [] dst = m2_expr.ExprOp('sint_to_fp64', dst[:64]) src = m2_expr.ExprOp('sint_to_fp64', src[:64]) e.append(m2_expr.ExprAff(cf, m2_expr.ExprOp('fcom_c0', dst, src))) e.append(m2_expr.ExprAff(pf, m2_expr.ExprOp('fcom_c2', dst, src))) e.append(m2_expr.ExprAff(zf, m2_expr.ExprOp('fcom_c3', dst, src))) e.append(m2_expr.ExprAff(of, m2_expr.ExprInt(0, 1))) e.append(m2_expr.ExprAff(nf, m2_expr.ExprInt(0, 1))) e.append(m2_expr.ExprAff(af, m2_expr.ExprInt(0, 1))) e += set_float_cs_eip(instr) return e, [] def fld(_, instr, src): if src.size == 32: src = m2_expr.ExprOp("fpconvert_fp64", src) e = [] e.append(m2_expr.ExprAff(float_st7, float_st6)) e.append(m2_expr.ExprAff(float_st6, float_st5)) e.append(m2_expr.ExprAff(float_st5, float_st4)) e.append(m2_expr.ExprAff(float_st4, float_st3)) e.append(m2_expr.ExprAff(float_st3, float_st2)) e.append(m2_expr.ExprAff(float_st2, float_st1)) e.append(m2_expr.ExprAff(float_st1, float_st0)) e.append(m2_expr.ExprAff(float_st0, src)) e.append( m2_expr.ExprAff(float_stack_ptr, float_stack_ptr + m2_expr.ExprInt(1, 3))) e += set_float_cs_eip(instr) return e, [] def fst(_, instr, dst): e = [] if isinstance(dst, m2_expr.ExprMem) and dst.size > 64: raise NotImplementedError('convert to 80bits') src = float_st0 if dst.size == 32: src = m2_expr.ExprOp("fpconvert_fp32", src) e.append(m2_expr.ExprAff(dst, src)) e += set_float_cs_eip(instr) return e, [] def fstp(ir, instr, dst): e = [] if isinstance(dst, m2_expr.ExprMem) and dst.size > 64: raise NotImplementedError('convert to 80bits') if isinstance(dst, m2_expr.ExprMem): src = float_st0 if dst.size == 32: src = m2_expr.ExprOp("fpconvert_fp32", src) e.append(m2_expr.ExprAff(dst, src)) else: src = float_st0 if float_list.index(dst) > 1: # a = st0 -> st0 is dropped # a = st1 -> st0 = st0, useless e.append(m2_expr.ExprAff(float_prev(dst), src)) e += set_float_cs_eip(instr) e += float_pop(dst) return e, [] def fist(_, instr, dst): e = [] e.append(m2_expr.ExprAff(dst, m2_expr.ExprOp('fp_to_sint%d' % dst.size, float_st0))) e += set_float_cs_eip(instr) return e, [] def fistp(ir, instr, dst): e, extra = fist(ir, instr, dst) e += float_pop(dst) return e, extra def fisttp(_, instr, dst): e = [] e.append(m2_expr.ExprAff( dst, m2_expr.ExprOp('fp_to_sint%d' % dst.size, m2_expr.ExprOp('fpround_towardszero', float_st0) ))) e += set_float_cs_eip(instr) e += float_pop(dst) return e, [] def fild(ir, instr, src): # XXXXX src = m2_expr.ExprOp('sint_to_fp64', src) e = [] e += set_float_cs_eip(instr) e_fld, extra = fld(ir, instr, src) e += e_fld return e, extra def fldz(ir, instr): return fld(ir, instr, m2_expr.ExprOp('sint_to_fp64', m2_expr.ExprInt(0, 32))) def fld1(ir, instr): return fld(ir, instr, m2_expr.ExprOp('sint_to_fp64', m2_expr.ExprInt(1, 32))) def fldl2t(ir, instr): value_f = math.log(10) / math.log(2) value = struct.unpack('I', struct.pack('f', value_f))[0] return fld(ir, instr, m2_expr.ExprOp('sint_to_fp64', m2_expr.ExprInt(value, 32))) def fldpi(ir, instr): value_f = math.pi value = struct.unpack('I', struct.pack('f', value_f))[0] return fld(ir, instr, m2_expr.ExprOp('sint_to_fp64', m2_expr.ExprInt(value, 32))) def fldln2(ir, instr): value_f = math.log(2) value = struct.unpack('Q', struct.pack('d', value_f))[0] return fld(ir, instr, m2_expr.ExprOp('mem_64_to_double', m2_expr.ExprInt(value, 64))) def fldl2e(ir, instr): x = struct.pack('d', 1 / math.log(2)) x = struct.unpack('Q', x)[0] return fld(ir, instr, m2_expr.ExprOp('mem_64_to_double', m2_expr.ExprInt(x, 64))) def fldlg2(ir, instr): x = struct.pack('d', math.log10(2)) x = struct.unpack('Q', x)[0] return fld(ir, instr, m2_expr.ExprOp('mem_64_to_double', m2_expr.ExprInt(x, 64))) def fadd(_, instr, dst, src=None): dst, src = float_implicit_st0(dst, src) e = [] src = mem2double(instr, src) e.append(m2_expr.ExprAff(dst, m2_expr.ExprOp('fadd', dst, src))) e += set_float_cs_eip(instr) return e, [] def fiadd(_, instr, dst, src=None): dst, src = float_implicit_st0(dst, src) e = [] src = mem2double(instr, src) e.append(m2_expr.ExprAff(dst, m2_expr.ExprOp('fiadd', dst, src))) e += set_float_cs_eip(instr) return e, [] def fisub(_, instr, dst, src=None): dst, src = float_implicit_st0(dst, src) e = [] src = mem2double(instr, src) e.append(m2_expr.ExprAff(dst, m2_expr.ExprOp('fisub', dst, src))) e += set_float_cs_eip(instr) return e, [] def fisubr(_, instr, dst, src=None): dst, src = float_implicit_st0(dst, src) e = [] src = mem2double(instr, src) e.append(m2_expr.ExprAff(dst, m2_expr.ExprOp('fisub', src, dst))) e += set_float_cs_eip(instr) return e, [] def fpatan(_, instr): e = [] a = float_st1 e.append(m2_expr.ExprAff(float_prev(a), m2_expr.ExprOp('fpatan', float_st0, float_st1))) e += set_float_cs_eip(instr) e += float_pop(a) return e, [] def fprem(_, instr): e = [] e.append( m2_expr.ExprAff(float_st0, m2_expr.ExprOp('fprem', float_st0, float_st1))) # Remaining bits (ex: used in argument reduction in tan) remain = m2_expr.ExprOp('fprem_lsb', float_st0, float_st1) e += [m2_expr.ExprAff(float_c0, remain[2:3]), m2_expr.ExprAff(float_c3, remain[1:2]), m2_expr.ExprAff(float_c1, remain[0:1]), # Consider the reduction is always completed m2_expr.ExprAff(float_c2, m2_expr.ExprInt(0, 1)), ] e += set_float_cs_eip(instr) return e, [] def fprem1(_, instr): e = [] e.append( m2_expr.ExprAff(float_st0, m2_expr.ExprOp('fprem1', float_st0, float_st1))) e += set_float_cs_eip(instr) return e, [] def faddp(_, instr, dst, src=None): dst, src = float_implicit_st0(dst, src) e = [] src = mem2double(instr, src) e.append(m2_expr.ExprAff(float_prev(dst), m2_expr.ExprOp('fadd', dst, src))) e += set_float_cs_eip(instr) e += float_pop(dst) return e, [] def fninit(_, instr): e = [] e += set_float_cs_eip(instr) return e, [] def fyl2x(_, instr): e = [] a = float_st1 e.append( m2_expr.ExprAff(float_prev(a), m2_expr.ExprOp('fyl2x', float_st0, float_st1))) e += set_float_cs_eip(instr) e += float_pop(a) return e, [] def fnstenv(ir, instr, dst): e = [] # XXX TODO tag word, ... status_word = m2_expr.ExprCompose(m2_expr.ExprInt(0, 8), float_c0, float_c1, float_c2, float_stack_ptr, float_c3, m2_expr.ExprInt(0, 1)) s = instr.mode # The behaviour in 64bit is identical to 32 bit # This will truncate addresses size = min(32, s) ad = ir.ExprMem(dst.arg, size=16) e.append(m2_expr.ExprAff(ad, float_control)) ad = ir.ExprMem(dst.arg + m2_expr.ExprInt(size / 8 * 1, dst.arg.size), size=16) e.append(m2_expr.ExprAff(ad, status_word)) ad = ir.ExprMem(dst.arg + m2_expr.ExprInt(size / 8 * 3, dst.arg.size), size=size) e.append(m2_expr.ExprAff(ad, float_eip[:size])) ad = ir.ExprMem(dst.arg + m2_expr.ExprInt(size / 8 * 4, dst.arg.size), size=16) e.append(m2_expr.ExprAff(ad, float_cs)) ad = ir.ExprMem(dst.arg + m2_expr.ExprInt(size / 8 * 5, dst.arg.size), size=size) e.append(m2_expr.ExprAff(ad, float_address[:size])) ad = ir.ExprMem(dst.arg + m2_expr.ExprInt(size / 8 * 6, dst.arg.size), size=16) e.append(m2_expr.ExprAff(ad, float_ds)) return e, [] def fldenv(ir, instr, src): e = [] # Inspired from fnstenv (same TODOs / issues) s = instr.mode # The behaviour in 64bit is identical to 32 bit # This will truncate addresses size = min(32, s) # Float control ad = ir.ExprMem(src.arg, size=16) e.append(m2_expr.ExprAff(float_control, ad)) # Status word ad = ir.ExprMem(src.arg + m2_expr.ExprInt(size / 8 * 1, size=src.arg.size), size=16) e += [m2_expr.ExprAff(x, y) for x, y in ((float_c0, ad[8:9]), (float_c1, ad[9:10]), (float_c2, ad[10:11]), (float_stack_ptr, ad[11:14]), (float_c3, ad[14:15])) ] # EIP, CS, Address, DS for offset, target in ((3, float_eip[:size]), (4, float_cs), (5, float_address[:size]), (6, float_ds)): ad = ir.ExprMem(src.arg + m2_expr.ExprInt(size / 8 * offset, size=src.arg.size), size=target.size) e.append(m2_expr.ExprAff(target, ad)) return e, [] def fsub(_, instr, dst, src=None): dst, src = float_implicit_st0(dst, src) e = [] src = mem2double(instr, src) e.append(m2_expr.ExprAff(dst, m2_expr.ExprOp('fsub', dst, src))) e += set_float_cs_eip(instr) return e, [] def fsubp(_, instr, dst, src=None): dst, src = float_implicit_st0(dst, src) e = [] src = mem2double(instr, src) e.append(m2_expr.ExprAff(float_prev(dst), m2_expr.ExprOp('fsub', dst, src))) e += set_float_cs_eip(instr) e += float_pop(dst) return e, [] def fsubr(_, instr, dst, src=None): dst, src = float_implicit_st0(dst, src) e = [] src = mem2double(instr, src) e.append(m2_expr.ExprAff(dst, m2_expr.ExprOp('fsub', src, dst))) e += set_float_cs_eip(instr) return e, [] def fsubrp(_, instr, dst, src=None): dst, src = float_implicit_st0(dst, src) e = [] src = mem2double(instr, src) e.append(m2_expr.ExprAff(float_prev(dst), m2_expr.ExprOp('fsub', src, dst))) e += set_float_cs_eip(instr) e += float_pop(dst) return e, [] def fmul(_, instr, dst, src=None): dst, src = float_implicit_st0(dst, src) e = [] src = mem2double(instr, src) e.append(m2_expr.ExprAff(dst, m2_expr.ExprOp('fmul', dst, src))) e += set_float_cs_eip(instr) return e, [] def fimul(_, instr, dst, src=None): dst, src = float_implicit_st0(dst, src) e = [] src = mem2double(instr, src) e.append(m2_expr.ExprAff(dst, m2_expr.ExprOp('fimul', dst, src))) e += set_float_cs_eip(instr) return e, [] def fdiv(_, instr, dst, src=None): dst, src = float_implicit_st0(dst, src) e = [] src = mem2double(instr, src) e.append(m2_expr.ExprAff(dst, m2_expr.ExprOp('fdiv', dst, src))) e += set_float_cs_eip(instr) return e, [] def fdivr(_, instr, dst, src=None): dst, src = float_implicit_st0(dst, src) e = [] src = mem2double(instr, src) e.append(m2_expr.ExprAff(dst, m2_expr.ExprOp('fdiv', src, dst))) e += set_float_cs_eip(instr) return e, [] def fdivrp(_, instr, dst, src=None): dst, src = float_implicit_st0(dst, src) e = [] src = mem2double(instr, src) e.append(m2_expr.ExprAff(float_prev(dst), m2_expr.ExprOp('fdiv', src, dst))) e += set_float_cs_eip(instr) e += float_pop(dst) return e, [] def fidiv(_, instr, dst, src=None): dst, src = float_implicit_st0(dst, src) e = [] src = mem2double(instr, src) e.append(m2_expr.ExprAff(dst, m2_expr.ExprOp('fidiv', dst, src))) e += set_float_cs_eip(instr) return e, [] def fidivr(_, instr, dst, src=None): dst, src = float_implicit_st0(dst, src) e = [] src = mem2double(instr, src) e.append(m2_expr.ExprAff(dst, m2_expr.ExprOp('fidiv', src, dst))) e += set_float_cs_eip(instr) return e, [] def fdivp(_, instr, dst, src=None): # Invalid emulation dst, src = float_implicit_st0(dst, src) e = [] src = mem2double(instr, src) e.append(m2_expr.ExprAff(float_prev(dst), m2_expr.ExprOp('fdiv', dst, src))) e += set_float_cs_eip(instr) e += float_pop(dst) return e, [] def fmulp(_, instr, dst, src=None): # Invalid emulation dst, src = float_implicit_st0(dst, src) e = [] src = mem2double(instr, src) e.append(m2_expr.ExprAff(float_prev(dst), m2_expr.ExprOp('fmul', dst, src))) e += set_float_cs_eip(instr) e += float_pop(dst) return e, [] def ftan(_, instr, src): e = [] src = mem2double(instr, src) e.append(m2_expr.ExprAff(float_st0, m2_expr.ExprOp('ftan', src))) e += set_float_cs_eip(instr) return e, [] def fxch(_, instr, src): e = [] src = mem2double(instr, src) e.append(m2_expr.ExprAff(float_st0, src)) e.append(m2_expr.ExprAff(src, float_st0)) e += set_float_cs_eip(instr) return e, [] def fptan(_, instr): e = [] e.append(m2_expr.ExprAff(float_st7, float_st6)) e.append(m2_expr.ExprAff(float_st6, float_st5)) e.append(m2_expr.ExprAff(float_st5, float_st4)) e.append(m2_expr.ExprAff(float_st4, float_st3)) e.append(m2_expr.ExprAff(float_st3, float_st2)) e.append(m2_expr.ExprAff(float_st2, float_st1)) e.append(m2_expr.ExprAff(float_st1, m2_expr.ExprOp('ftan', float_st0))) e.append(m2_expr.ExprAff(float_st0, m2_expr.ExprOp('sint_to_fp64', m2_expr.ExprInt(1, 32)))) e.append( m2_expr.ExprAff(float_stack_ptr, float_stack_ptr + m2_expr.ExprInt(1, 3))) return e, [] def frndint(_, instr): e = [] e.append(m2_expr.ExprAff(float_st0, m2_expr.ExprOp('frndint', float_st0))) e += set_float_cs_eip(instr) return e, [] def fsin(_, instr): e = [] e.append(m2_expr.ExprAff(float_st0, m2_expr.ExprOp('fsin', float_st0))) e += set_float_cs_eip(instr) return e, [] def fcos(_, instr): e = [] e.append(m2_expr.ExprAff(float_st0, m2_expr.ExprOp('fcos', float_st0))) e += set_float_cs_eip(instr) return e, [] def fsincos(_, instr): e = [] e.append(m2_expr.ExprAff(float_st7, float_st6)) e.append(m2_expr.ExprAff(float_st6, float_st5)) e.append(m2_expr.ExprAff(float_st5, float_st4)) e.append(m2_expr.ExprAff(float_st4, float_st3)) e.append(m2_expr.ExprAff(float_st3, float_st2)) e.append(m2_expr.ExprAff(float_st2, float_st1)) e.append(m2_expr.ExprAff(float_st1, m2_expr.ExprOp('fsin', float_st0))) e.append(m2_expr.ExprAff(float_st0, m2_expr.ExprOp('fcos', float_st0))) e.append( m2_expr.ExprAff(float_stack_ptr, float_stack_ptr + m2_expr.ExprInt(1, 3))) return e, [] def fscale(_, instr): e = [] e.append(m2_expr.ExprAff(float_st0, m2_expr.ExprOp('fscale', float_st0, float_st1))) e += set_float_cs_eip(instr) return e, [] def f2xm1(_, instr): e = [] e.append(m2_expr.ExprAff(float_st0, m2_expr.ExprOp('f2xm1', float_st0))) e += set_float_cs_eip(instr) return e, [] def fchs(_, instr): e = [] e.append(m2_expr.ExprAff(float_st0, m2_expr.ExprOp('fchs', float_st0))) e += set_float_cs_eip(instr) return e, [] def fsqrt(_, instr): e = [] e.append(m2_expr.ExprAff(float_st0, m2_expr.ExprOp('fsqrt', float_st0))) e += set_float_cs_eip(instr) return e, [] def fabs(_, instr): e = [] e.append(m2_expr.ExprAff(float_st0, m2_expr.ExprOp('fabs', float_st0))) e += set_float_cs_eip(instr) return e, [] def fnstsw(_, instr, dst): args = [ # Exceptions -> 0 m2_expr.ExprInt(0, 8), float_c0, float_c1, float_c2, float_stack_ptr, float_c3, # B: FPU is not busy -> 0 m2_expr.ExprInt(0, 1)] e = [m2_expr.ExprAff(dst, m2_expr.ExprCompose(*args))] return e, [] def fnstcw(_, instr, dst): e = [] e.append(m2_expr.ExprAff(dst, float_control)) return e, [] def fldcw(_, instr, src): e = [] e.append(m2_expr.ExprAff(float_control, src)) return e, [] def fwait(_, instr): return [], [] def fcmovb(ir, instr, arg1, arg2): return gen_fcmov(ir, instr, cf, arg1, arg2, True) def fcmove(ir, instr, arg1, arg2): return gen_fcmov(ir, instr, zf, arg1, arg2, True) def fcmovbe(ir, instr, arg1, arg2): return gen_fcmov(ir, instr, cf | zf, arg1, arg2, True) def fcmovu(ir, instr, arg1, arg2): return gen_fcmov(ir, instr, pf, arg1, arg2, True) def fcmovnb(ir, instr, arg1, arg2): return gen_fcmov(ir, instr, cf, arg1, arg2, False) def fcmovne(ir, instr, arg1, arg2): return gen_fcmov(ir, instr, zf, arg1, arg2, False) def fcmovnbe(ir, instr, arg1, arg2): return gen_fcmov(ir, instr, cf | zf, arg1, arg2, False) def fcmovnu(ir, instr, arg1, arg2): return gen_fcmov(ir, instr, pf, arg1, arg2, False) def nop(_, instr, a=None): return [], [] def prefetch0(_, instr, src=None): # see 4-198 on this documentation # https://www-ssl.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf return [], [] def prefetch1(_, instr, src=None): # see 4-198 on this documentation # https://www-ssl.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf return [], [] def prefetch2(_, instr, src=None): # see 4-198 on this documentation # https://www-ssl.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf return [], [] def prefetchw(_, instr, src=None): # see 4-201 on this documentation # https://www-ssl.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf return [], [] def prefetchnta(_, instr, src=None): # see 4-201 on this documentation # https://www-ssl.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf return [], [] def lfence(_, instr, src=None): # see 3-485 on this documentation # https://www-ssl.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf return [], [] def mfence(_, instr, src=None): # see 3-516 on this documentation # https://www-ssl.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf return [], [] def sfence(_, instr, src=None): # see 3-356 on this documentation # https://www-ssl.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf return [], [] def ud2(_, instr, src=None): e = [m2_expr.ExprAff(exception_flags, m2_expr.ExprInt( EXCEPT_ILLEGAL_INSN, exception_flags.size))] return e, [] def hlt(_, instr): e = [] except_int = EXCEPT_PRIV_INSN e.append(m2_expr.ExprAff(exception_flags, m2_expr.ExprInt(except_int, 32))) return e, [] def rdtsc(_, instr): e = [] e.append(m2_expr.ExprAff(tsc1, tsc1 + m2_expr.ExprInt(1, 32))) e.append(m2_expr.ExprAff(tsc2, tsc2 + m2_expr.ExprCond(tsc1 - tsc1.mask, m2_expr.ExprInt(0, 32), m2_expr.ExprInt(1, 32)))) e.append(m2_expr.ExprAff(mRAX[32], tsc1)) e.append(m2_expr.ExprAff(mRDX[32], tsc2)) return e, [] def daa(_, instr): e = [] r_al = mRAX[instr.mode][:8] cond1 = m2_expr.expr_is_unsigned_greater(r_al[:4], m2_expr.ExprInt(0x9, 4)) | af e.append(m2_expr.ExprAff(af, cond1)) cond2 = m2_expr.expr_is_unsigned_greater(m2_expr.ExprInt(6, 8), r_al) cond3 = m2_expr.expr_is_unsigned_greater(r_al, m2_expr.ExprInt(0x99, 8)) | cf cf_c1 = m2_expr.ExprCond(cond1, cf | (cond2), m2_expr.ExprInt(0, 1)) new_cf = m2_expr.ExprCond(cond3, m2_expr.ExprInt(1, 1), m2_expr.ExprInt(0, 1)) e.append(m2_expr.ExprAff(cf, new_cf)) al_c1 = m2_expr.ExprCond(cond1, r_al + m2_expr.ExprInt(6, 8), r_al) new_al = m2_expr.ExprCond(cond3, al_c1 + m2_expr.ExprInt(0x60, 8), al_c1) e.append(m2_expr.ExprAff(r_al, new_al)) e += update_flag_znp(new_al) return e, [] def das(_, instr): e = [] r_al = mRAX[instr.mode][:8] cond1 = m2_expr.expr_is_unsigned_greater(r_al[:4], m2_expr.ExprInt(0x9, 4)) | af e.append(m2_expr.ExprAff(af, cond1)) cond2 = m2_expr.expr_is_unsigned_greater(m2_expr.ExprInt(6, 8), r_al) cond3 = m2_expr.expr_is_unsigned_greater(r_al, m2_expr.ExprInt(0x99, 8)) | cf cf_c1 = m2_expr.ExprCond(cond1, cf | (cond2), m2_expr.ExprInt(0, 1)) new_cf = m2_expr.ExprCond(cond3, m2_expr.ExprInt(1, 1), cf_c1) e.append(m2_expr.ExprAff(cf, new_cf)) al_c1 = m2_expr.ExprCond(cond1, r_al - m2_expr.ExprInt(6, 8), r_al) new_al = m2_expr.ExprCond(cond3, al_c1 - m2_expr.ExprInt(0x60, 8), al_c1) e.append(m2_expr.ExprAff(r_al, new_al)) e += update_flag_znp(new_al) return e, [] def aam(_, instr, src): e = [] tempAL = mRAX[instr.mode][0:8] newEAX = m2_expr.ExprCompose(m2_expr.ExprOp("umod", tempAL, src), m2_expr.ExprOp("udiv", tempAL, src), mRAX[instr.mode][16:]) e += [m2_expr.ExprAff(mRAX[instr.mode], newEAX)] e += update_flag_arith(newEAX) e.append(m2_expr.ExprAff(af, m2_expr.ExprInt(0, 1))) return e, [] def aad(_, instr, src): e = [] tempAL = mRAX[instr.mode][0:8] tempAH = mRAX[instr.mode][8:16] newEAX = m2_expr.ExprCompose((tempAL + (tempAH * src)) & m2_expr.ExprInt(0xFF, 8), m2_expr.ExprInt(0, 8), mRAX[instr.mode][16:]) e += [m2_expr.ExprAff(mRAX[instr.mode], newEAX)] e += update_flag_arith(newEAX) e.append(m2_expr.ExprAff(af, m2_expr.ExprInt(0, 1))) return e, [] def _tpl_aaa(_, instr, op): """Templating for aaa, aas with operation @op @op: operation to apply """ e = [] r_al = mRAX[instr.mode][:8] r_ah = mRAX[instr.mode][8:16] r_ax = mRAX[instr.mode][:16] i0 = m2_expr.ExprInt(0, 1) i1 = m2_expr.ExprInt(1, 1) # cond: if (al & 0xf) > 9 OR af == 1 cond = (r_al & m2_expr.ExprInt(0xf, 8)) - m2_expr.ExprInt(9, 8) cond = ~cond.msb() & m2_expr.ExprCond(cond, i1, i0) cond |= af & i1 to_add = m2_expr.ExprInt(0x106, size=r_ax.size) if op == "-": # Avoid ExprOp("-", A, B), should be ExprOp("+", A, ExprOp("-", B)) first_part = r_ax - to_add else: first_part = m2_expr.ExprOp(op, r_ax, to_add) new_ax = first_part & m2_expr.ExprInt(0xff0f, size=r_ax.size) # set AL e.append(m2_expr.ExprAff(r_ax, m2_expr.ExprCond(cond, new_ax, r_ax))) e.append(m2_expr.ExprAff(af, cond)) e.append(m2_expr.ExprAff(cf, cond)) return e, [] def aaa(ir, instr): return _tpl_aaa(ir, instr, "+") def aas(ir, instr): return _tpl_aaa(ir, instr, "-") def bsr_bsf(ir, instr, dst, src, op_func): """ IF SRC == 0 ZF = 1 DEST is left unchanged ELSE ZF = 0 DEST = @op_func(SRC) """ loc_src_null, loc_src_null_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) loc_src_not_null, loc_src_not_null_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) loc_next = ir.get_next_loc_key(instr) loc_next_expr = m2_expr.ExprLoc(loc_next, ir.IRDst.size) aff_dst = m2_expr.ExprAff(ir.IRDst, loc_next_expr) e = [m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(src, loc_src_not_null_expr, loc_src_null_expr))] e_src_null = [] e_src_null.append(m2_expr.ExprAff(zf, m2_expr.ExprInt(1, zf.size))) # XXX destination is undefined e_src_null.append(aff_dst) e_src_not_null = [] e_src_not_null.append(m2_expr.ExprAff(zf, m2_expr.ExprInt(0, zf.size))) e_src_not_null.append(m2_expr.ExprAff(dst, op_func(src))) e_src_not_null.append(aff_dst) return e, [IRBlock(loc_src_null, [AssignBlock(e_src_null, instr)]), IRBlock(loc_src_not_null, [AssignBlock(e_src_not_null, instr)])] def bsf(ir, instr, dst, src): return bsr_bsf(ir, instr, dst, src, lambda src: m2_expr.ExprOp("cnttrailzeros", src)) def bsr(ir, instr, dst, src): return bsr_bsf( ir, instr, dst, src, lambda src: m2_expr.ExprInt(src.size - 1, src.size) - m2_expr.ExprOp("cntleadzeros", src) ) def arpl(_, instr, dst, src): e = [] e.append(m2_expr.ExprAff(exception_flags, m2_expr.ExprInt(1 << 7, 32))) return e, [] def ins(_, instr, size): e = [] e.append(m2_expr.ExprAff(exception_flags, m2_expr.ExprInt(1 << 7, 32))) return e, [] def sidt(ir, instr, dst): e = [] if not isinstance(dst, m2_expr.ExprMem) or dst.size != 32: raise ValueError('not exprmem 32bit instance!!') ptr = dst.arg LOG_X86_SEM.warning("DEFAULT SIDT ADDRESS %s!!", str(dst)) e.append(m2_expr.ExprAff(ir.ExprMem(ptr, 32), m2_expr.ExprInt(0xe40007ff, 32))) e.append( m2_expr.ExprAff(ir.ExprMem(ptr + m2_expr.ExprInt(4, ptr.size), 16), m2_expr.ExprInt(0x8245, 16))) return e, [] def sldt(_, instr, dst): LOG_X86_SEM.warning("DEFAULT SLDT ADDRESS %s!!", str(dst)) e = [m2_expr.ExprAff(dst, m2_expr.ExprInt(0, dst.size))] return e, [] def cmovz(ir, instr, dst, src): #return gen_cmov(ir, instr, zf, dst, src, True) return gen_cmov(ir, instr, m2_expr.ExprOp("CC_EQ", zf), dst, src, True) def cmovnz(ir, instr, dst, src): #return gen_cmov(ir, instr, zf, dst, src, False) return gen_cmov(ir, instr, m2_expr.ExprOp("CC_EQ", zf), dst, src, False) def cmovpe(ir, instr, dst, src): return gen_cmov(ir, instr, pf, dst, src, True) def cmovnp(ir, instr, dst, src): return gen_cmov(ir, instr, pf, dst, src, False) def cmovge(ir, instr, dst, src): #return gen_cmov(ir, instr, nf ^ of, dst, src, False) return gen_cmov(ir, instr, m2_expr.ExprOp("CC_S>=", nf, of), dst, src, True) def cmovg(ir, instr, dst, src): #return gen_cmov(ir, instr, zf | (nf ^ of), dst, src, False) return gen_cmov(ir, instr, m2_expr.ExprOp("CC_S>", nf, of, zf), dst, src, True) def cmovl(ir, instr, dst, src): #return gen_cmov(ir, instr, nf ^ of, dst, src, True) return gen_cmov(ir, instr, m2_expr.ExprOp("CC_S<", nf, of), dst, src, True) def cmovle(ir, instr, dst, src): #return gen_cmov(ir, instr, zf | (nf ^ of), dst, src, True) return gen_cmov(ir, instr, m2_expr.ExprOp("CC_S<=", nf, of, zf), dst, src, True) def cmova(ir, instr, dst, src): #return gen_cmov(ir, instr, cf | zf, dst, src, False) return gen_cmov(ir, instr, m2_expr.ExprOp("CC_U>", cf, zf), dst, src, True) def cmovae(ir, instr, dst, src): #return gen_cmov(ir, instr, cf, dst, src, False) return gen_cmov(ir, instr, m2_expr.ExprOp("CC_U>=", cf), dst, src, True) def cmovbe(ir, instr, dst, src): #return gen_cmov(ir, instr, cf | zf, dst, src, True) return gen_cmov(ir, instr, m2_expr.ExprOp("CC_U<=", cf, zf), dst, src, True) def cmovb(ir, instr, dst, src): #return gen_cmov(ir, instr, cf, dst, src, True) return gen_cmov(ir, instr, m2_expr.ExprOp("CC_U<", cf), dst, src, True) def cmovo(ir, instr, dst, src): return gen_cmov(ir, instr, of, dst, src, True) def cmovno(ir, instr, dst, src): return gen_cmov(ir, instr, of, dst, src, False) def cmovs(ir, instr, dst, src): #return gen_cmov(ir, instr, nf, dst, src, True) return gen_cmov(ir, instr, m2_expr.ExprOp("CC_NEG", nf), dst, src, True) def cmovns(ir, instr, dst, src): #return gen_cmov(ir, instr, nf, dst, src, False) return gen_cmov(ir, instr, m2_expr.ExprOp("CC_NEG", nf), dst, src, False) def icebp(_, instr): e = [] e.append(m2_expr.ExprAff(exception_flags, m2_expr.ExprInt(EXCEPT_SOFT_BP, 32))) return e, [] # XXX def l_int(_, instr, src): e = [] # XXX if src.arg in [1, 3]: except_int = EXCEPT_SOFT_BP else: except_int = EXCEPT_INT_XX e.append(m2_expr.ExprAff(exception_flags, m2_expr.ExprInt(except_int, 32))) e.append(m2_expr.ExprAff(interrupt_num, src)) return e, [] def l_sysenter(_, instr): e = [] e.append(m2_expr.ExprAff(exception_flags, m2_expr.ExprInt(EXCEPT_PRIV_INSN, 32))) return e, [] def l_syscall(_, instr): e = [] e.append(m2_expr.ExprAff(exception_flags, m2_expr.ExprInt(EXCEPT_PRIV_INSN, 32))) return e, [] # XXX def l_out(_, instr, src1, src2): e = [] e.append(m2_expr.ExprAff(exception_flags, m2_expr.ExprInt(EXCEPT_PRIV_INSN, 32))) return e, [] # XXX def l_outs(_, instr, size): e = [] e.append(m2_expr.ExprAff(exception_flags, m2_expr.ExprInt(EXCEPT_PRIV_INSN, 32))) return e, [] # XXX actually, xlat performs al = (ds:[e]bx + ZeroExtend(al)) def xlat(ir, instr): e = [] ptr = mRAX[instr.mode][0:8].zeroExtend(mRBX[instr.mode].size) src = ir.ExprMem(mRBX[instr.mode] + ptr, 8) e.append(m2_expr.ExprAff(mRAX[instr.mode][0:8], src)) return e, [] def cpuid(_, instr): e = [] e.append( m2_expr.ExprAff(mRAX[instr.mode], m2_expr.ExprOp('x86_cpuid', mRAX[instr.mode], m2_expr.ExprInt(0, instr.mode)))) e.append( m2_expr.ExprAff(mRBX[instr.mode], m2_expr.ExprOp('x86_cpuid', mRAX[instr.mode], m2_expr.ExprInt(1, instr.mode)))) e.append( m2_expr.ExprAff(mRCX[instr.mode], m2_expr.ExprOp('x86_cpuid', mRAX[instr.mode], m2_expr.ExprInt(2, instr.mode)))) e.append( m2_expr.ExprAff(mRDX[instr.mode], m2_expr.ExprOp('x86_cpuid', mRAX[instr.mode], m2_expr.ExprInt(3, instr.mode)))) return e, [] def bittest_get(ir, instr, src, index): index = index.zeroExtend(src.size) if isinstance(src, m2_expr.ExprMem): b_mask = {16: 4, 32: 5, 64: 6} b_decal = {16: 1, 32: 3, 64: 7} ptr = src.arg segm = src.is_mem_segm() if segm: ptr = ptr.args[1] off_bit = index.zeroExtend( src.size) & m2_expr.ExprInt((1 << b_mask[src.size]) - 1, src.size) off_byte = ((index.zeroExtend(ptr.size) >> m2_expr.ExprInt(3, ptr.size)) & m2_expr.ExprInt(((1 << src.size) - 1) ^ b_decal[src.size], ptr.size)) addr = ptr + off_byte if segm: addr = ir.gen_segm_expr(src.arg.args[0], addr) d = ir.ExprMem(addr, src.size) else: off_bit = m2_expr.ExprOp( '&', index, m2_expr.ExprInt(src.size - 1, src.size)) d = src return d, off_bit def bt(ir, instr, src, index): e = [] index = index.zeroExtend(src.size) d, off_bit = bittest_get(ir, instr, src, index) d = d >> off_bit e.append(m2_expr.ExprAff(cf, d[:1])) return e, [] def btc(ir, instr, src, index): e = [] d, off_bit = bittest_get(ir, instr, src, index) e.append(m2_expr.ExprAff(cf, (d >> off_bit)[:1])) m = m2_expr.ExprInt(1, src.size) << off_bit e.append(m2_expr.ExprAff(d, d ^ m)) return e, [] def bts(ir, instr, src, index): e = [] d, off_bit = bittest_get(ir, instr, src, index) e.append(m2_expr.ExprAff(cf, (d >> off_bit)[:1])) m = m2_expr.ExprInt(1, src.size) << off_bit e.append(m2_expr.ExprAff(d, d | m)) return e, [] def btr(ir, instr, src, index): e = [] d, off_bit = bittest_get(ir, instr, src, index) e.append(m2_expr.ExprAff(cf, (d >> off_bit)[:1])) m = ~(m2_expr.ExprInt(1, src.size) << off_bit) e.append(m2_expr.ExprAff(d, d & m)) return e, [] def into(_, instr): return [], [] def l_in(_, instr, src1, src2): e = [] e.append(m2_expr.ExprAff(exception_flags, m2_expr.ExprInt(EXCEPT_PRIV_INSN, 32))) return e, [] @sbuild.parse def cmpxchg(arg1, arg2): accumulator = mRAX[instr.v_opmode()][:arg1.size] if (accumulator - arg1): zf = i1(0) accumulator = arg1 else: zf = i1(1) arg1 = arg2 @sbuild.parse def cmpxchg8b(arg1): accumulator = {mRAX[32], mRDX[32]} if accumulator - arg1: zf = i1(0) mRAX[32] = arg1[:32] mRDX[32] = arg1[32:] else: zf = i1(1) arg1 = {mRBX[32], mRCX[32]} @sbuild.parse def cmpxchg16b(arg1): accumulator = {mRAX[64], mRDX[64]} if accumulator - arg1: zf = i1(0) mRAX[64] = arg1[:64] mRDX[64] = arg1[64:] else: zf = i1(1) arg1 = {mRBX[64], mRCX[64]} def lds(ir, instr, dst, src): e = [] e.append(m2_expr.ExprAff(dst, ir.ExprMem(src.arg, size=dst.size))) DS_value = ir.ExprMem(src.arg + m2_expr.ExprInt(dst.size / 8, src.arg.size), size=16) e.append(m2_expr.ExprAff(DS, DS_value)) return e, [] def les(ir, instr, dst, src): e = [] e.append(m2_expr.ExprAff(dst, ir.ExprMem(src.arg, size=dst.size))) ES_value = ir.ExprMem(src.arg + m2_expr.ExprInt(dst.size / 8, src.arg.size), size=16) e.append(m2_expr.ExprAff(ES, ES_value)) return e, [] def lss(ir, instr, dst, src): e = [] e.append(m2_expr.ExprAff(dst, ir.ExprMem(src.arg, size=dst.size))) SS_value = ir.ExprMem(src.arg + m2_expr.ExprInt(dst.size / 8, src.arg.size), size=16) e.append(m2_expr.ExprAff(SS, SS_value)) return e, [] def lfs(ir, instr, dst, src): e = [] e.append(m2_expr.ExprAff(dst, ir.ExprMem(src.arg, size=dst.size))) FS_value = ir.ExprMem(src.arg + m2_expr.ExprInt(dst.size / 8, src.arg.size), size=16) e.append(m2_expr.ExprAff(FS, FS_value)) return e, [] def lgs(ir, instr, dst, src): e = [] e.append(m2_expr.ExprAff(dst, ir.ExprMem(src.arg, size=dst.size))) GS_value = ir.ExprMem(src.arg + m2_expr.ExprInt(dst.size / 8, src.arg.size), size=16) e.append(m2_expr.ExprAff(GS, GS_value)) return e, [] def lahf(_, instr): e = [] args = [cf, m2_expr.ExprInt(1, 1), pf, m2_expr.ExprInt(0, 1), af, m2_expr.ExprInt(0, 1), zf, nf] e.append( m2_expr.ExprAff(mRAX[instr.mode][8:16], m2_expr.ExprCompose(*args))) return e, [] def sahf(_, instr): tmp = mRAX[instr.mode][8:16] e = [] e.append(m2_expr.ExprAff(cf, tmp[0:1])) e.append(m2_expr.ExprAff(pf, tmp[2:3])) e.append(m2_expr.ExprAff(af, tmp[4:5])) e.append(m2_expr.ExprAff(zf, tmp[6:7])) e.append(m2_expr.ExprAff(nf, tmp[7:8])) return e, [] def lar(_, instr, dst, src): e = [] e.append(m2_expr.ExprAff(dst, m2_expr.ExprOp('access_segment', src))) e.append(m2_expr.ExprAff(zf, m2_expr.ExprOp('access_segment_ok', src))) return e, [] def lsl(_, instr, dst, src): e = [] e.append(m2_expr.ExprAff(dst, m2_expr.ExprOp('load_segment_limit', src))) e.append(m2_expr.ExprAff(zf, m2_expr.ExprOp('load_segment_limit_ok', src))) return e, [] def fclex(_, instr): # XXX TODO return [], [] def fnclex(_, instr): # XXX TODO return [], [] def l_str(_, instr, dst): e = [] e.append(m2_expr.ExprAff(dst, m2_expr.ExprOp('load_tr_segment_selector', m2_expr.ExprInt(0, 32)))) return e, [] def movd(_, instr, dst, src): e = [] if dst in regs_mm_expr: e.append(m2_expr.ExprAff( dst, m2_expr.ExprCompose(src, m2_expr.ExprInt(0, 32)))) elif dst in regs_xmm_expr: e.append(m2_expr.ExprAff( dst, m2_expr.ExprCompose(src, m2_expr.ExprInt(0, 96)))) else: e.append(m2_expr.ExprAff(dst, src[:32])) return e, [] def movdqu(_, instr, dst, src): # XXX TODO alignement check return [m2_expr.ExprAff(dst, src)], [] def movapd(_, instr, dst, src): # XXX TODO alignement check return [m2_expr.ExprAff(dst, src)], [] def andps(_, instr, dst, src): e = [] e.append(m2_expr.ExprAff(dst, m2_expr.ExprOp('&', dst, src))) return e, [] def andnps(_, instr, dst, src): e = [] e.append(m2_expr.ExprAff(dst, m2_expr.ExprOp('&', dst ^ dst.mask, src))) return e, [] def orps(_, instr, dst, src): e = [] e.append(m2_expr.ExprAff(dst, m2_expr.ExprOp('|', dst, src))) return e, [] def xorps(_, instr, dst, src): e = [] e.append(m2_expr.ExprAff(dst, m2_expr.ExprOp('^', dst, src))) return e, [] def rdmsr(ir, instr): msr_addr = m2_expr.ExprId('MSR', 64) + m2_expr.ExprInt(8, 64) * mRCX[32].zeroExtend(64) e = [] e.append(m2_expr.ExprAff(mRAX[32], ir.ExprMem(msr_addr, 32))) e.append(m2_expr.ExprAff(mRDX[32], ir.ExprMem(msr_addr + m2_expr.ExprInt(4, 64), 32))) return e, [] def wrmsr(ir, instr): msr_addr = m2_expr.ExprId('MSR', 64) + m2_expr.ExprInt(8, 64) * mRCX[32].zeroExtend(64) e = [] src = m2_expr.ExprCompose(mRAX[32], mRDX[32]) e.append(m2_expr.ExprAff(ir.ExprMem(msr_addr, 64), src)) return e, [] # MMX/SSE/AVX operations # def vec_op_clip(op, size, callback=None): """ Generate simd operations @op: the operator @size: size of an element """ def vec_op_clip_instr(ir, instr, dst, src): if op == '-': result = dst[:size] - src[:size] else: result = m2_expr.ExprOp(op, dst[:size], src[:size]) if callback is not None: result = callback(result) return [m2_expr.ExprAff(dst[:size], result)], [] return vec_op_clip_instr # Generic vertical operation def vec_vertical_sem(op, elt_size, reg_size, dst, src, apply_on_output): assert reg_size % elt_size == 0 n = reg_size / elt_size if op == '-': ops = [ apply_on_output((dst[i * elt_size:(i + 1) * elt_size] - src[i * elt_size:(i + 1) * elt_size])) for i in xrange(0, n) ] else: ops = [ apply_on_output(m2_expr.ExprOp(op, dst[i * elt_size:(i + 1) * elt_size], src[i * elt_size:(i + 1) * elt_size])) for i in xrange(0, n) ] return m2_expr.ExprCompose(*ops) def __vec_vertical_instr_gen(op, elt_size, sem, apply_on_output): def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, [] return vec_instr def vec_vertical_instr(op, elt_size, apply_on_output=lambda x: x): return __vec_vertical_instr_gen(op, elt_size, vec_vertical_sem, apply_on_output) def _keep_mul_high(expr, signed=False): assert expr.is_op("*") and len(expr.args) == 2 if signed: arg1 = expr.args[0].signExtend(expr.size * 2) arg2 = expr.args[1].signExtend(expr.size * 2) else: arg1 = expr.args[0].zeroExtend(expr.size * 2) arg2 = expr.args[1].zeroExtend(expr.size * 2) return m2_expr.ExprOp("*", arg1, arg2)[expr.size:] # Op, signed => associated comparison _min_max_func = { ("min", False): m2_expr.expr_is_unsigned_lower, ("min", True): m2_expr.expr_is_signed_lower, ("max", False): m2_expr.expr_is_unsigned_greater, ("max", True): m2_expr.expr_is_signed_greater, } def _min_max(expr, signed): assert (expr.is_op("min") or expr.is_op("max")) and len(expr.args) == 2 return m2_expr.ExprCond( _min_max_func[(expr.op, signed)](expr.args[1], expr.args[0]), expr.args[1], expr.args[0], ) def _float_min_max(expr): assert (expr.is_op("fmin") or expr.is_op("fmax")) and len(expr.args) == 2 src1 = expr.args[0] src2 = expr.args[1] if expr.is_op("fmin"): comp = m2_expr.expr_is_float_lower(src1, src2) elif expr.is_op("fmax"): comp = m2_expr.expr_is_float_lower(src2, src1) # x86 documentation (for MIN): # IF ((SRC1 = 0.0) and (SRC2 = 0.0)) THEN DEST <-SRC2; # ELSE IF (SRC1 = SNaN) THEN DEST <-SRC2; FI; # ELSE IF (SRC2 = SNaN) THEN DEST <-SRC2; FI; # ELSE IF (SRC1 < SRC2) THEN DEST <-SRC1; # ELSE DEST<-SRC2; # # But this includes the NaN output of "SRC1 < SRC2" # Associated text is more detailed, and this is the version impl here return m2_expr.ExprCond( m2_expr.expr_is_sNaN(src2), src2, m2_expr.ExprCond( m2_expr.expr_is_NaN(src2) | m2_expr.expr_is_NaN(src1), src2, m2_expr.ExprCond(comp, src1, src2) ) ) # Integer arithmetic # # Additions # # SSE paddb = vec_vertical_instr('+', 8) paddw = vec_vertical_instr('+', 16) paddd = vec_vertical_instr('+', 32) paddq = vec_vertical_instr('+', 64) # Substractions # # SSE psubb = vec_vertical_instr('-', 8) psubw = vec_vertical_instr('-', 16) psubd = vec_vertical_instr('-', 32) psubq = vec_vertical_instr('-', 64) # Multiplications # # SSE pmullb = vec_vertical_instr('*', 8) pmullw = vec_vertical_instr('*', 16) pmulld = vec_vertical_instr('*', 32) pmullq = vec_vertical_instr('*', 64) pmulhub = vec_vertical_instr('*', 8, _keep_mul_high) pmulhuw = vec_vertical_instr('*', 16, _keep_mul_high) pmulhud = vec_vertical_instr('*', 32, _keep_mul_high) pmulhuq = vec_vertical_instr('*', 64, _keep_mul_high) pmulhb = vec_vertical_instr('*', 8, lambda x: _keep_mul_high(x, signed=True)) pmulhw = vec_vertical_instr('*', 16, lambda x: _keep_mul_high(x, signed=True)) pmulhd = vec_vertical_instr('*', 32, lambda x: _keep_mul_high(x, signed=True)) pmulhq = vec_vertical_instr('*', 64, lambda x: _keep_mul_high(x, signed=True)) def pmuludq(ir, instr, dst, src): e = [] if dst.size == 64: e.append(m2_expr.ExprAff( dst, src[:32].zeroExtend(64) * dst[:32].zeroExtend(64) )) elif dst.size == 128: e.append(m2_expr.ExprAff( dst[:64], src[:32].zeroExtend(64) * dst[:32].zeroExtend(64) )) e.append(m2_expr.ExprAff( dst[64:], src[64:96].zeroExtend(64) * dst[64:96].zeroExtend(64) )) else: raise RuntimeError("Unsupported size %d" % dst.size) return e, [] # Mix # # SSE def pmaddwd(ir, instr, dst, src): sizedst = 32 sizesrc = 16 out = [] for start in xrange(0, dst.size, sizedst): base = start mul1 = src[base: base + sizesrc].signExtend(sizedst) * dst[base: base + sizesrc].signExtend(sizedst) base += sizesrc mul2 = src[base: base + sizesrc].signExtend(sizedst) * dst[base: base + sizesrc].signExtend(sizedst) out.append(mul1 + mul2) return [m2_expr.ExprAff(dst, m2_expr.ExprCompose(*out))], [] def _absolute(expr): """Return abs(@expr)""" signed = expr.msb() value_unsigned = (expr ^ expr.mask) + m2_expr.ExprInt(1, expr.size) return m2_expr.ExprCond(signed, value_unsigned, expr) def psadbw(ir, instr, dst, src): sizedst = 16 sizesrc = 8 out_dst = [] for start in xrange(0, dst.size, 64): out = [] for src_start in xrange(0, 64, sizesrc): beg = start + src_start end = beg + sizesrc # Not clear in the doc equations, but in the text, src and dst are: # "8 unsigned byte integers" out.append(_absolute(dst[beg: end].zeroExtend(sizedst) - src[beg: end].zeroExtend(sizedst))) out_dst.append(m2_expr.ExprOp("+", *out)) out_dst.append(m2_expr.ExprInt(0, 64 - sizedst)) return [m2_expr.ExprAff(dst, m2_expr.ExprCompose(*out_dst))], [] def _average(expr): assert expr.is_op("avg") and len(expr.args) == 2 arg1 = expr.args[0].zeroExtend(expr.size * 2) arg2 = expr.args[1].zeroExtend(expr.size * 2) one = m2_expr.ExprInt(1, arg1.size) # avg(unsigned) = (a + b + 1) >> 1, addition beeing at least on one more bit return ((arg1 + arg2 + one) >> one)[:expr.size] pavgb = vec_vertical_instr('avg', 8, _average) pavgw = vec_vertical_instr('avg', 16, _average) # Comparisons # # SSE pminsw = vec_vertical_instr('min', 16, lambda x: _min_max(x, signed=True)) pminub = vec_vertical_instr('min', 8, lambda x: _min_max(x, signed=False)) pminuw = vec_vertical_instr('min', 16, lambda x: _min_max(x, signed=False)) pminud = vec_vertical_instr('min', 32, lambda x: _min_max(x, signed=False)) pmaxub = vec_vertical_instr('max', 8, lambda x: _min_max(x, signed=False)) pmaxuw = vec_vertical_instr('max', 16, lambda x: _min_max(x, signed=False)) pmaxud = vec_vertical_instr('max', 32, lambda x: _min_max(x, signed=False)) pmaxsw = vec_vertical_instr('max', 16, lambda x: _min_max(x, signed=True)) # Floating-point arithmetic # # SSE addss = vec_op_clip('fadd', 32) addsd = vec_op_clip('fadd', 64) addps = vec_vertical_instr('fadd', 32) addpd = vec_vertical_instr('fadd', 64) subss = vec_op_clip('fsub', 32) subsd = vec_op_clip('fsub', 64) subps = vec_vertical_instr('fsub', 32) subpd = vec_vertical_instr('fsub', 64) mulss = vec_op_clip('fmul', 32) mulsd = vec_op_clip('fmul', 64) mulps = vec_vertical_instr('fmul', 32) mulpd = vec_vertical_instr('fmul', 64) divss = vec_op_clip('fdiv', 32) divsd = vec_op_clip('fdiv', 64) divps = vec_vertical_instr('fdiv', 32) divpd = vec_vertical_instr('fdiv', 64) # Comparisons (floating-point) minps = vec_vertical_instr('fmin', 32, _float_min_max) minpd = vec_vertical_instr('fmin', 64, _float_min_max) minss = vec_op_clip('fmin', 32, _float_min_max) minsd = vec_op_clip('fmin', 64, _float_min_max) maxps = vec_vertical_instr('fmax', 32, _float_min_max) maxpd = vec_vertical_instr('fmax', 64, _float_min_max) maxss = vec_op_clip('fmax', 32, _float_min_max) maxsd = vec_op_clip('fmax', 64, _float_min_max) def _float_compare_to_mask(expr): if expr.op == 'unord': to_ext = m2_expr.expr_is_NaN(expr.args[0]) | m2_expr.expr_is_NaN(expr.args[1]) elif expr.op == 'ord': to_ext = ~m2_expr.expr_is_NaN(expr.args[0]) & ~m2_expr.expr_is_NaN(expr.args[1]) else: if expr.op == '==fu': to_ext = m2_expr.expr_is_float_equal(expr.args[0], expr.args[1]) on_NaN = m2_expr.ExprInt(0, 1) elif expr.op == '<fu': to_ext = m2_expr.expr_is_float_lower(expr.args[0], expr.args[1]) on_NaN = m2_expr.ExprInt(0, 1) elif expr.op == '<=fu': to_ext = (m2_expr.expr_is_float_equal(expr.args[0], expr.args[1]) | m2_expr.expr_is_float_lower(expr.args[0], expr.args[1])) on_NaN = m2_expr.ExprInt(0, 1) elif expr.op == '!=fu': to_ext = ~m2_expr.expr_is_float_equal(expr.args[0], expr.args[1]) on_NaN = m2_expr.ExprInt(1, 1) elif expr.op == '!<fu': to_ext = ~m2_expr.expr_is_float_lower(expr.args[0], expr.args[1]) on_NaN = m2_expr.ExprInt(1, 1) elif expr.op == '!<=fu': to_ext = ~(m2_expr.expr_is_float_equal(expr.args[0], expr.args[1]) | m2_expr.expr_is_float_lower(expr.args[0], expr.args[1])) on_NaN = m2_expr.ExprInt(1, 1) to_ext = m2_expr.ExprCond( m2_expr.expr_is_NaN(expr.args[0]) | m2_expr.expr_is_NaN(expr.args[1]), on_NaN, to_ext ) return to_ext.signExtend(expr.size) cmpeqps = vec_vertical_instr('==fu', 32, lambda x: _float_compare_to_mask(x)) cmpeqpd = vec_vertical_instr('==fu', 64, lambda x: _float_compare_to_mask(x)) cmpeqss = vec_op_clip('==fu', 32, lambda x: _float_compare_to_mask(x)) cmpeqsd = vec_op_clip('==fu', 64, lambda x: _float_compare_to_mask(x)) cmpltps = vec_vertical_instr('<fu', 32, lambda x: _float_compare_to_mask(x)) cmpltpd = vec_vertical_instr('<fu', 64, lambda x: _float_compare_to_mask(x)) cmpltss = vec_op_clip('<fu', 32, lambda x: _float_compare_to_mask(x)) cmpltsd = vec_op_clip('<fu', 64, lambda x: _float_compare_to_mask(x)) cmpleps = vec_vertical_instr('<=fu', 32, lambda x: _float_compare_to_mask(x)) cmplepd = vec_vertical_instr('<=fu', 64, lambda x: _float_compare_to_mask(x)) cmpless = vec_op_clip('<=fu', 32, lambda x: _float_compare_to_mask(x)) cmplesd = vec_op_clip('<=fu', 64, lambda x: _float_compare_to_mask(x)) cmpunordps = vec_vertical_instr('unord', 32, lambda x: _float_compare_to_mask(x)) cmpunordpd = vec_vertical_instr('unord', 64, lambda x: _float_compare_to_mask(x)) cmpunordss = vec_op_clip('unord', 32, lambda x: _float_compare_to_mask(x)) cmpunordsd = vec_op_clip('unord', 64, lambda x: _float_compare_to_mask(x)) cmpneqps = vec_vertical_instr('!=fu', 32, lambda x: _float_compare_to_mask(x)) cmpneqpd = vec_vertical_instr('!=fu', 64, lambda x: _float_compare_to_mask(x)) cmpneqss = vec_op_clip('!=fu', 32, lambda x: _float_compare_to_mask(x)) cmpneqsd = vec_op_clip('!=fu', 64, lambda x: _float_compare_to_mask(x)) cmpnltps = vec_vertical_instr('!<fu', 32, lambda x: _float_compare_to_mask(x)) cmpnltpd = vec_vertical_instr('!<fu', 64, lambda x: _float_compare_to_mask(x)) cmpnltss = vec_op_clip('!<fu', 32, lambda x: _float_compare_to_mask(x)) cmpnltsd = vec_op_clip('!<fu', 64, lambda x: _float_compare_to_mask(x)) cmpnleps = vec_vertical_instr('!<=fu', 32, lambda x: _float_compare_to_mask(x)) cmpnlepd = vec_vertical_instr('!<=fu', 64, lambda x: _float_compare_to_mask(x)) cmpnless = vec_op_clip('!<=fu', 32, lambda x: _float_compare_to_mask(x)) cmpnlesd = vec_op_clip('!<=fu', 64, lambda x: _float_compare_to_mask(x)) cmpordps = vec_vertical_instr('ord', 32, lambda x: _float_compare_to_mask(x)) cmpordpd = vec_vertical_instr('ord', 64, lambda x: _float_compare_to_mask(x)) cmpordss = vec_op_clip('ord', 32, lambda x: _float_compare_to_mask(x)) cmpordsd = vec_op_clip('ord', 64, lambda x: _float_compare_to_mask(x)) # Logical (floating-point) # # MMX/SSE/AVX def pand(_, instr, dst, src): e = [] result = dst & src # No flag affected e.append(m2_expr.ExprAff(dst, result)) return e, [] def pandn(_, instr, dst, src): e = [] result = (dst ^ dst.mask) & src # No flag affected e.append(m2_expr.ExprAff(dst, result)) return e, [] def por(_, instr, dst, src): e = [] result = dst | src e.append(m2_expr.ExprAff(dst, result)) return e, [] def cvtdq2pd(_, instr, dst, src): e = [] e.append( m2_expr.ExprAff(dst[:64], m2_expr.ExprOp('sint_to_fp64', src[:32]))) e.append( m2_expr.ExprAff(dst[64:128], m2_expr.ExprOp('sint_to_fp64', src[32:64]))) return e, [] def cvtdq2ps(_, instr, dst, src): e = [] e.append( m2_expr.ExprAff(dst[:32], m2_expr.ExprOp('sint_to_fp32', src[:32]))) e.append( m2_expr.ExprAff(dst[32:64], m2_expr.ExprOp('sint_to_fp32', src[32:64]))) e.append( m2_expr.ExprAff(dst[64:96], m2_expr.ExprOp('sint_to_fp32', src[64:96]))) e.append( m2_expr.ExprAff(dst[96:128], m2_expr.ExprOp('sint_to_fp32', src[96:128]))) return e, [] def cvtpd2dq(_, instr, dst, src): e = [] e.append( m2_expr.ExprAff(dst[:32], m2_expr.ExprOp('fp_to_sint32', src[:64]))) e.append( m2_expr.ExprAff(dst[32:64], m2_expr.ExprOp('fp_to_sint32', src[64:128]))) e.append(m2_expr.ExprAff(dst[64:128], m2_expr.ExprInt(0, 64))) return e, [] def cvtpd2pi(_, instr, dst, src): e = [] e.append( m2_expr.ExprAff(dst[:32], m2_expr.ExprOp('fp_to_sint32', src[:64]))) e.append( m2_expr.ExprAff(dst[32:64], m2_expr.ExprOp('fp_to_sint32', src[64:128]))) return e, [] def cvtpd2ps(_, instr, dst, src): e = [] e.append( m2_expr.ExprAff(dst[:32], m2_expr.ExprOp('fpconvert_fp32', src[:64]))) e.append( m2_expr.ExprAff(dst[32:64], m2_expr.ExprOp('fpconvert_fp32', src[64:128]))) e.append(m2_expr.ExprAff(dst[64:128], m2_expr.ExprInt(0, 64))) return e, [] def cvtpi2pd(_, instr, dst, src): e = [] e.append( m2_expr.ExprAff(dst[:64], m2_expr.ExprOp('sint_to_fp64', src[:32]))) e.append( m2_expr.ExprAff(dst[64:128], m2_expr.ExprOp('sint_to_fp64', src[32:64]))) return e, [] def cvtpi2ps(_, instr, dst, src): e = [] e.append( m2_expr.ExprAff(dst[:32], m2_expr.ExprOp('sint_to_fp32', src[:32]))) e.append( m2_expr.ExprAff(dst[32:64], m2_expr.ExprOp('sint_to_fp32', src[32:64]))) return e, [] def cvtps2dq(_, instr, dst, src): e = [] e.append( m2_expr.ExprAff(dst[:32], m2_expr.ExprOp('fp_to_sint32', src[:32]))) e.append( m2_expr.ExprAff(dst[32:64], m2_expr.ExprOp('fp_to_sint32', src[32:64]))) e.append( m2_expr.ExprAff(dst[64:96], m2_expr.ExprOp('fp_to_sint32', src[64:96]))) e.append( m2_expr.ExprAff(dst[96:128], m2_expr.ExprOp('fp_to_sint32', src[96:128]))) return e, [] def cvtps2pd(_, instr, dst, src): e = [] e.append( m2_expr.ExprAff(dst[:64], m2_expr.ExprOp('fpconvert_fp64', src[:32]))) e.append( m2_expr.ExprAff(dst[64:128], m2_expr.ExprOp('fpconvert_fp64', src[32:64]))) return e, [] def cvtps2pi(_, instr, dst, src): e = [] e.append( m2_expr.ExprAff(dst[:32], m2_expr.ExprOp('fp_to_sint32', src[:32]))) e.append( m2_expr.ExprAff(dst[32:64], m2_expr.ExprOp('fp_to_sint32', src[32:64]))) return e, [] def cvtsd2si(_, instr, dst, src): e = [] e.append( m2_expr.ExprAff(dst[:32], m2_expr.ExprOp('fp_to_sint32', src[:64]))) return e, [] def cvtsd2ss(_, instr, dst, src): e = [] e.append( m2_expr.ExprAff(dst[:32], m2_expr.ExprOp('fpconvert_fp32', src[:64]))) return e, [] def cvtsi2sd(_, instr, dst, src): e = [] e.append( m2_expr.ExprAff(dst[:64], m2_expr.ExprOp('sint_to_fp64', src[:32]))) return e, [] def cvtsi2ss(_, instr, dst, src): e = [] e.append( m2_expr.ExprAff(dst[:32], m2_expr.ExprOp('sint_to_fp32', src[:32]))) return e, [] def cvtss2sd(_, instr, dst, src): e = [] e.append( m2_expr.ExprAff(dst[:64], m2_expr.ExprOp('fpconvert_fp64', src[:32]))) return e, [] def cvtss2si(_, instr, dst, src): e = [] e.append( m2_expr.ExprAff(dst[:32], m2_expr.ExprOp('fp_to_sint32', src[:32]))) return e, [] def _cvtt_tpl(dst, src, numbers, double): e = [] for i in numbers: # For CVTT*D2* (Convert with Truncation ... Double-Precision) to work, # a first conversion fp64 -> fp32 is needed if double: tmp_src = m2_expr.ExprOp('fpconvert_fp32', src[i*64:i*64 + 64]) else: tmp_src = src[i*32:i*32 + 32] e.append(m2_expr.ExprAff( dst[i*32:i*32 + 32], m2_expr.ExprOp('fp_to_sint32', m2_expr.ExprOp( 'fpround_towardszero', tmp_src )))) return e def cvttpd2pi(_, instr, dst, src): return _cvtt_tpl(dst, src, [0, 1], double=True), [] def cvttpd2dq(_, instr, dst, src): e = _cvtt_tpl(dst, src, [0, 1], double=True) e.append(m2_expr.ExprAff(dst[64:128], m2_expr.ExprInt(0, 64))) return e, [] def cvttsd2si(_, instr, dst, src): return _cvtt_tpl(dst, src, [0], double=True), [] def cvttps2dq(_, instr, dst, src): return _cvtt_tpl(dst, src, [0, 1, 2, 3], double=False), [] def cvttps2pi(_, instr, dst, src): return _cvtt_tpl(dst, src, [0, 1], double=False), [] def cvttss2si(_, instr, dst, src): return _cvtt_tpl(dst, src, [0], double=False), [] def movss(_, instr, dst, src): e = [] if not isinstance(dst, m2_expr.ExprMem) and not isinstance(src, m2_expr.ExprMem): # Source and Destination xmm e.append(m2_expr.ExprAff(dst[:32], src[:32])) elif not isinstance(src, m2_expr.ExprMem) and isinstance(dst, m2_expr.ExprMem): # Source XMM Destination Mem e.append(m2_expr.ExprAff(dst, src[:32])) else: # Source Mem Destination XMM e.append(m2_expr.ExprAff( dst, m2_expr.ExprCompose(src, m2_expr.ExprInt(0, 96)))) return e, [] def ucomiss(_, instr, src1, src2): e = [] e.append(m2_expr.ExprAff(zf, m2_expr.ExprOp( 'ucomiss_zf', src1[:32], src2[:32]))) e.append(m2_expr.ExprAff(pf, m2_expr.ExprOp( 'ucomiss_pf', src1[:32], src2[:32]))) e.append(m2_expr.ExprAff(cf, m2_expr.ExprOp( 'ucomiss_cf', src1[:32], src2[:32]))) e.append(m2_expr.ExprAff(of, m2_expr.ExprInt(0, 1))) e.append(m2_expr.ExprAff(af, m2_expr.ExprInt(0, 1))) e.append(m2_expr.ExprAff(nf, m2_expr.ExprInt(0, 1))) return e, [] def ucomisd(_, instr, src1, src2): e = [] e.append(m2_expr.ExprAff(zf, m2_expr.ExprOp( 'ucomisd_zf', src1[:64], src2[:64]))) e.append(m2_expr.ExprAff(pf, m2_expr.ExprOp( 'ucomisd_pf', src1[:64], src2[:64]))) e.append(m2_expr.ExprAff(cf, m2_expr.ExprOp( 'ucomisd_cf', src1[:64], src2[:64]))) e.append(m2_expr.ExprAff(of, m2_expr.ExprInt(0, 1))) e.append(m2_expr.ExprAff(af, m2_expr.ExprInt(0, 1))) e.append(m2_expr.ExprAff(nf, m2_expr.ExprInt(0, 1))) return e, [] def pshufb(_, instr, dst, src): e = [] if dst.size == 64: bit_l = 3 elif dst.size == 128: bit_l = 4 else: raise NotImplementedError("bad size") for i in xrange(0, src.size, 8): index = src[ i:i + bit_l].zeroExtend(dst.size) << m2_expr.ExprInt(3, dst.size) value = (dst >> index)[:8] e.append(m2_expr.ExprAff(dst[i:i + 8], m2_expr.ExprCond(src[i + 7:i + 8], m2_expr.ExprInt(0, 8), value))) return e, [] def pshufd(_, instr, dst, src, imm): control = int(imm) out = [] for i in xrange(4): shift = ((control >> (i * 2)) & 3) * 32 # shift is 2 bits long, expr.size is 128 # => shift + 32 <= src.size out.append(src[shift: shift + 32]) return [m2_expr.ExprAff(dst, m2_expr.ExprCompose(*out))], [] def pshuflw(_, instr, dst, src, imm): control = int(imm) out = [] for i in xrange(4): shift = ((control >> (i * 2)) & 3) * 16 out.append(src[shift: shift + 16]) out.append(src[64:]) return [m2_expr.ExprAff(dst, m2_expr.ExprCompose(*out))], [] def pshufhw(_, instr, dst, src, imm): control = int(imm) out = [src[:64]] for i in xrange(4): shift = ((control >> (i * 2)) & 3) * 16 out.append(src[shift + 64: shift + 16 + 64]) return [m2_expr.ExprAff(dst, m2_expr.ExprCompose(*out))], [] def ps_rl_ll(ir, instr, dst, src, op, size): mask = {16: 0xF, 32: 0x1F, 64: 0x3F}[size] mask = m2_expr.ExprInt(mask, dst.size) # Saturate the counter to 2**size count = src.zeroExtend(dst.size) count = m2_expr.ExprCond(count & expr_simp(~mask), m2_expr.ExprInt(size, dst.size), # saturation count, # count < 2**size ) count = count[:size] if src.is_int(): count = expr_simp(count) out = [] for i in xrange(0, dst.size, size): out.append(m2_expr.ExprOp(op, dst[i:i + size], count)) return [m2_expr.ExprAff(dst, m2_expr.ExprCompose(*out))], [] def psrlw(ir, instr, dst, src): return ps_rl_ll(ir, instr, dst, src, ">>", 16) def psrld(ir, instr, dst, src): return ps_rl_ll(ir, instr, dst, src, ">>", 32) def psrlq(ir, instr, dst, src): return ps_rl_ll(ir, instr, dst, src, ">>", 64) def psllw(ir, instr, dst, src): return ps_rl_ll(ir, instr, dst, src, "<<", 16) def pslld(ir, instr, dst, src): return ps_rl_ll(ir, instr, dst, src, "<<", 32) def psllq(ir, instr, dst, src): return ps_rl_ll(ir, instr, dst, src, "<<", 64) def psraw(ir, instr, dst, src): return ps_rl_ll(ir, instr, dst, src, "a>>", 16) def psrad(ir, instr, dst, src): return ps_rl_ll(ir, instr, dst, src, "a>>", 32) def pslldq(_, instr, dst, src): assert src.is_int() e = [] count = int(src) if count > 15: return [m2_expr.ExprAff(dst, m2_expr.ExprInt(0, dst.size))], [] else: return [m2_expr.ExprAff(dst, dst << m2_expr.ExprInt(8 * count, dst.size))], [] def psrldq(_, instr, dst, src): assert src.is_int() e = [] count = int(src) if count > 15: return [m2_expr.ExprAff(dst, m2_expr.ExprInt(0, dst.size))], [] else: return [m2_expr.ExprAff(dst, dst >> m2_expr.ExprInt(8 * count, dst.size))], [] def iret(ir, instr): """IRET implementation XXX: only support "no-privilege change" """ size = instr.v_opmode() exprs, _ = retf(ir, instr, m2_expr.ExprInt(size / 8, size=size)) tmp = mRSP[instr.mode][:size] + m2_expr.ExprInt((2 * size) / 8, size=size) exprs += _tpl_eflags(tmp) return exprs, [] def pcmpeq(_, instr, dst, src, size): e = [] for i in xrange(0, dst.size, size): test = m2_expr.expr_is_equal(dst[i:i + size], src[i:i + size]) e.append(m2_expr.ExprAff(dst[i:i + size], m2_expr.ExprCond(test, m2_expr.ExprInt(-1, size), m2_expr.ExprInt(0, size)))) return e, [] def pcmpgt(_, instr, dst, src, size): e = [] for i in xrange(0, dst.size, size): test = m2_expr.expr_is_signed_greater(dst[i:i + size], src[i:i + size]) e.append(m2_expr.ExprAff(dst[i:i + size], m2_expr.ExprCond(test, m2_expr.ExprInt(-1, size), m2_expr.ExprInt(0, size)))) return e, [] def pcmpeqb(ir, instr, dst, src): return pcmpeq(ir, instr, dst, src, 8) def pcmpeqw(ir, instr, dst, src): return pcmpeq(ir, instr, dst, src, 16) def pcmpeqd(ir, instr, dst, src): return pcmpeq(ir, instr, dst, src, 32) def pcmpeqq(ir, instr, dst, src): return pcmpeq(ir, instr, dst, src, 64) def pcmpgtb(ir, instr, dst, src): return pcmpgt(ir, instr, dst, src, 8) def pcmpgtw(ir, instr, dst, src): return pcmpgt(ir, instr, dst, src, 16) def pcmpgtd(ir, instr, dst, src): return pcmpgt(ir, instr, dst, src, 32) def pcmpgtq(ir, instr, dst, src): return pcmpgt(ir, instr, dst, src, 64) def punpck(_, instr, dst, src, size, off): e = [] slices = [] for i in xrange(dst.size / (2 * size)): slices.append(dst[size * i + off: size * i + off + size]) slices.append(src[size * i + off: size * i + off + size]) e.append(m2_expr.ExprAff(dst, m2_expr.ExprCompose(*slices))) return e, [] def punpckhbw(ir, instr, dst, src): return punpck(ir, instr, dst, src, 8, dst.size / 2) def punpckhwd(ir, instr, dst, src): return punpck(ir, instr, dst, src, 16, dst.size / 2) def punpckhdq(ir, instr, dst, src): return punpck(ir, instr, dst, src, 32, dst.size / 2) def punpckhqdq(ir, instr, dst, src): return punpck(ir, instr, dst, src, 64, dst.size / 2) def punpcklbw(ir, instr, dst, src): return punpck(ir, instr, dst, src, 8, 0) def punpcklwd(ir, instr, dst, src): return punpck(ir, instr, dst, src, 16, 0) def punpckldq(ir, instr, dst, src): return punpck(ir, instr, dst, src, 32, 0) def punpcklqdq(ir, instr, dst, src): return punpck(ir, instr, dst, src, 64, 0) def pinsr(_, instr, dst, src, imm, size): e = [] mask = {8: 0xF, 16: 0x7, 32: 0x3, 64: 0x1}[size] sel = (int(imm) & mask) * size e.append(m2_expr.ExprAff(dst[sel:sel + size], src[:size])) return e, [] def pinsrb(ir, instr, dst, src, imm): return pinsr(ir, instr, dst, src, imm, 8) def pinsrw(ir, instr, dst, src, imm): return pinsr(ir, instr, dst, src, imm, 16) def pinsrd(ir, instr, dst, src, imm): return pinsr(ir, instr, dst, src, imm, 32) def pinsrq(ir, instr, dst, src, imm): return pinsr(ir, instr, dst, src, imm, 64) def pextr(_, instr, dst, src, imm, size): e = [] mask = {8: 0xF, 16: 0x7, 32: 0x3, 64: 0x1}[size] sel = (int(imm) & mask) * size e.append(m2_expr.ExprAff(dst, src[sel:sel + size].zeroExtend(dst.size))) return e, [] def pextrb(ir, instr, dst, src, imm): return pextr(ir, instr, dst, src, imm, 8) def pextrw(ir, instr, dst, src, imm): return pextr(ir, instr, dst, src, imm, 16) def pextrd(ir, instr, dst, src, imm): return pextr(ir, instr, dst, src, imm, 32) def pextrq(ir, instr, dst, src, imm): return pextr(ir, instr, dst, src, imm, 64) def unpckhps(_, instr, dst, src): e = [] src = m2_expr.ExprCompose(dst[64:96], src[64:96], dst[96:128], src[96:128]) e.append(m2_expr.ExprAff(dst, src)) return e, [] def unpckhpd(_, instr, dst, src): e = [] src = m2_expr.ExprCompose(dst[64:128], src[64:128]) e.append(m2_expr.ExprAff(dst, src)) return e, [] def unpcklps(_, instr, dst, src): e = [] src = m2_expr.ExprCompose(dst[0:32], src[0:32], dst[32:64], src[32:64]) e.append(m2_expr.ExprAff(dst, src)) return e, [] def unpcklpd(_, instr, dst, src): e = [] src = m2_expr.ExprCompose(dst[0:64], src[0:64]) e.append(m2_expr.ExprAff(dst, src)) return e, [] def movlpd(_, instr, dst, src): e = [] e.append(m2_expr.ExprAff(dst[:64], src[:64])) return e, [] def movlps(_, instr, dst, src): e = [] e.append(m2_expr.ExprAff(dst[:64], src[:64])) return e, [] def movhpd(_, instr, dst, src): e = [] if src.size == 64: e.append(m2_expr.ExprAff(dst[64:128], src)) elif dst.size == 64: e.append(m2_expr.ExprAff(dst, src[64:128])) else: raise RuntimeError("bad encoding!") return e, [] def movlhps(_, instr, dst, src): e = [] e.append(m2_expr.ExprAff(dst[64:128], src[:64])) return e, [] def movhlps(_, instr, dst, src): e = [] e.append(m2_expr.ExprAff(dst[:64], src[64:128])) return e, [] def movdq2q(_, instr, dst, src): e = [] e.append(m2_expr.ExprAff(dst, src[:64])) return e, [] def movq2dq(_, instr, dst, src): e = [] e.append(m2_expr.ExprAff(dst, src[:64].zeroExtend(dst.size))) return e, [] def sqrt_gen(_, instr, dst, src, size): e = [] out = [] for i in xrange(src.size / size): out.append(m2_expr.ExprOp('fsqrt', src[i * size: (i + 1) * size])) src = m2_expr.ExprCompose(*out) e.append(m2_expr.ExprAff(dst, src)) return e, [] def sqrtpd(ir, instr, dst, src): return sqrt_gen(ir, instr, dst, src, 64) def sqrtps(ir, instr, dst, src): return sqrt_gen(ir, instr, dst, src, 32) def sqrtsd(_, instr, dst, src): e = [] e.append(m2_expr.ExprAff(dst[:64], m2_expr.ExprOp('fsqrt', src[:64]))) return e, [] def sqrtss(_, instr, dst, src): e = [] e.append(m2_expr.ExprAff(dst[:32], m2_expr.ExprOp('fsqrt', src[:32]))) return e, [] def pmovmskb(_, instr, dst, src): e = [] out = [] for i in xrange(src.size / 8): out.append(src[8 * i + 7:8 * (i + 1)]) src = m2_expr.ExprCompose(*out) e.append(m2_expr.ExprAff(dst, src.zeroExtend(dst.size))) return e, [] def smsw(ir, instr, dst): e = [] LOG_X86_SEM.warning("DEFAULT SMSW %s!!", str(dst)) e.append(m2_expr.ExprAff(dst, m2_expr.ExprInt(0x80050033, 32)[:dst.size])) return e, [] def bndmov(ir, instr, dst, src): # Implemented as a NOP, because BND side effects are not yet supported return [], [] def palignr(ir, instr, dst, src, imm): # dst.src >> imm * 8 [:dst.size] shift = int(imm) * 8 if shift == 0: result = src elif shift == src.size: result = dst elif shift > src.size: result = dst >> m2_expr.ExprInt(shift - src.size, dst.size) else: # shift < src.size result = m2_expr.ExprCompose( src[shift:], dst[:shift], ) return [m2_expr.ExprAff(dst, result)], [] def _signed_saturation(expr, dst_size): """Saturate the expr @expr for @dst_size bit Signed saturation return MAX_INT / MIN_INT or value depending on the value """ assert expr.size > dst_size median = 1 << (dst_size - 1) min_int = m2_expr.ExprInt(- median, dst_size) max_int = m2_expr.ExprInt(median - 1, dst_size) signed = expr.msb() value_unsigned = (expr ^ expr.mask) + m2_expr.ExprInt(1, expr.size) # Re-use the sign bit value = m2_expr.ExprCompose(expr[:dst_size - 1], signed) # Bit hack: to avoid a double signed comparison, use mask # ie., in unsigned, 0xXY > 0x0f iff X is not null # if expr >s 0 # if expr[dst_size - 1:] > 0: # bigger than max_int # -> max_int # else # -> value # else # negative # if expr[dst_size:-1] > 0: # smaller than min_int # -> value # else # -> min_int return m2_expr.ExprCond( signed, m2_expr.ExprCond(value_unsigned[dst_size - 1:], min_int, value), m2_expr.ExprCond(expr[dst_size - 1:], max_int, value), ) def _unsigned_saturation(expr, dst_size): """Saturate the expr @expr for @dst_size bit Unsigned saturation return MAX_INT or value depending on the value """ assert expr.size > dst_size zero = m2_expr.ExprInt(0, dst_size) max_int = m2_expr.ExprInt(-1, dst_size) value = expr[:dst_size] signed = expr.msb() # Bit hack: to avoid a double signed comparison, use mask # ie., in unsigned, 0xXY > 0x0f iff X is not null return m2_expr.ExprCond( signed, zero, m2_expr.ExprCond(expr[dst_size:], max_int, value), ) def packsswb(ir, instr, dst, src): out = [] for source in [dst, src]: for start in xrange(0, dst.size, 16): out.append(_signed_saturation(source[start:start + 16], 8)) return [m2_expr.ExprAff(dst, m2_expr.ExprCompose(*out))], [] def packssdw(ir, instr, dst, src): out = [] for source in [dst, src]: for start in xrange(0, dst.size, 32): out.append(_signed_saturation(source[start:start + 32], 16)) return [m2_expr.ExprAff(dst, m2_expr.ExprCompose(*out))], [] def packuswb(ir, instr, dst, src): out = [] for source in [dst, src]: for start in xrange(0, dst.size, 16): out.append(_unsigned_saturation(source[start:start + 16], 8)) return [m2_expr.ExprAff(dst, m2_expr.ExprCompose(*out))], [] def _saturation_sub_unsigned(expr): assert expr.is_op("+") and len(expr.args) == 2 and expr.args[-1].is_op("-") # Compute the soustraction on one more bit to be able to distinguish cases: # 0x48 - 0xd7 in 8 bit, should saturate arg1 = expr.args[0].zeroExtend(expr.size + 1) arg2 = expr.args[1].args[0].zeroExtend(expr.size + 1) return _unsigned_saturation(arg1 - arg2, expr.size) def _saturation_sub_signed(expr): assert expr.is_op("+") and len(expr.args) == 2 and expr.args[-1].is_op("-") # Compute the substraction on two more bits, see _saturation_sub_unsigned arg1 = expr.args[0].signExtend(expr.size + 2) arg2 = expr.args[1].args[0].signExtend(expr.size + 2) return _signed_saturation(arg1 - arg2, expr.size) def _saturation_add(expr): assert expr.is_op("+") and len(expr.args) == 2 # Compute the addition on one more bit to be able to distinguish cases: # 0x48 + 0xd7 in 8 bit, should saturate arg1 = expr.args[0].zeroExtend(expr.size + 1) arg2 = expr.args[1].zeroExtend(expr.size + 1) # We can also use _unsigned_saturation with two additionnal bits (to # distinguish minus and overflow case) # The resulting expression being more complicated with an impossible case # (signed=True), we rewrite the rule here return m2_expr.ExprCond((arg1 + arg2).msb(), m2_expr.ExprInt(-1, expr.size), expr) def _saturation_add_signed(expr): assert expr.is_op("+") and len(expr.args) == 2 # Compute the substraction on two more bits, see _saturation_add_unsigned arg1 = expr.args[0].signExtend(expr.size + 2) arg2 = expr.args[1].signExtend(expr.size + 2) return _signed_saturation(arg1 + arg2, expr.size) # Saturate SSE operations psubusb = vec_vertical_instr('-', 8, _saturation_sub_unsigned) psubusw = vec_vertical_instr('-', 16, _saturation_sub_unsigned) paddusb = vec_vertical_instr('+', 8, _saturation_add) paddusw = vec_vertical_instr('+', 16, _saturation_add) psubsb = vec_vertical_instr('-', 8, _saturation_sub_signed) psubsw = vec_vertical_instr('-', 16, _saturation_sub_signed) paddsb = vec_vertical_instr('+', 8, _saturation_add_signed) paddsw = vec_vertical_instr('+', 16, _saturation_add_signed) # Others SSE operations def maskmovq(ir, instr, src, mask): loc_next = ir.get_next_loc_key(instr) loc_next_expr = m2_expr.ExprLoc(loc_next, ir.IRDst.size) blks = [] # For each possibility, check if a write is necessary check_labels = [m2_expr.ExprLoc(ir.loc_db.add_location(), ir.IRDst.size) for _ in xrange(0, mask.size, 8)] # If the write has to be done, do it (otherwise, nothing happen) write_labels = [m2_expr.ExprLoc(ir.loc_db.add_location(), ir.IRDst.size) for _ in xrange(0, mask.size, 8)] # Build check blocks for i, start in enumerate(xrange(0, mask.size, 8)): bit = mask[start + 7: start + 8] cur_label = check_labels[i] next_check_label = check_labels[i + 1] if (i + 1) < len(check_labels) else loc_next_expr write_label = write_labels[i] check = m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(bit, write_label, next_check_label)) blks.append(IRBlock(cur_label.loc_key, [AssignBlock([check], instr)])) # Build write blocks dst_addr = mRDI[instr.mode] for i, start in enumerate(xrange(0, mask.size, 8)): bit = mask[start + 7: start + 8] cur_label = write_labels[i] next_check_label = check_labels[i + 1] if (i + 1) < len(check_labels) else loc_next_expr write_addr = dst_addr + m2_expr.ExprInt(i, dst_addr.size) # @8[DI/EDI/RDI + i] = src[byte i] write_mem = m2_expr.ExprAff(m2_expr.ExprMem(write_addr, 8), src[start: start + 8]) jump = m2_expr.ExprAff(ir.IRDst, next_check_label) blks.append(IRBlock(cur_label.loc_key, [AssignBlock([write_mem, jump], instr)])) # If mask is null, bypass all e = [m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(mask, check_labels[0], loc_next_expr))] return e, blks def emms(ir, instr): # Implemented as a NOP return [], [] # Common value without too many option, 0x1fa0 STMXCSR_VALUE = 0x1fa0 def stmxcsr(ir, instr, dst): return [m2_expr.ExprAff(dst, m2_expr.ExprInt(STMXCSR_VALUE, dst.size))], [] def ldmxcsr(ir, instr, dst): # Implemented as a NOP return [], [] def _select4(src, control): # Implementation inspired from Intel Intrisics Guide # @control is already resolved (was an immediate) if control == 0: return src[:32] # 0 elif control == 1: return src[32:64] elif control == 2: return src[64:96] elif control == 3: return src[96:] else: raise ValueError("Control must be on 2 bits") def shufps(ir, instr, dst, src, imm8): out = [] control = int(imm8) for i in xrange(4): if i < 2: source = dst else: source = src out.append(_select4(source, (control >> (i * 2)) & 3)) return [m2_expr.ExprAff(dst, m2_expr.ExprCompose(*out))], [] def shufpd(ir, instr, dst, src, imm8): out = [] control = int(imm8) out.append(dst[64:] if control & 1 else dst[:64]) out.append(src[64:] if control & 2 else src[:64]) return [m2_expr.ExprAff(dst, m2_expr.ExprCompose(*out))], [] def movmskps(ir, instr, dst, src): out = [] for i in xrange(4): out.append(src[(32 * i) + 31:(32 * i) + 32]) return [m2_expr.ExprAff(dst, m2_expr.ExprCompose(*out).zeroExtend(dst.size))], [] def movmskpd(ir, instr, dst, src): out = [] for i in xrange(2): out.append(src[(64 * i) + 63:(64 * i) + 64]) return [m2_expr.ExprAff(dst, m2_expr.ExprCompose(*out).zeroExtend(dst.size))], [] mnemo_func = {'mov': mov, 'xchg': xchg, 'movzx': movzx, 'movsx': movsx, 'movsxd': movsx, 'lea': lea, 'add': add, 'xadd': xadd, 'adc': adc, 'sub': sub, 'sbb': sbb, 'neg': neg, 'not': l_not, 'cmp': l_cmp, 'xor': xor, 'pxor': pxor, 'or': l_or, 'and': l_and, 'test': l_test, 'rol': l_rol, 'ror': l_ror, 'rcl': rcl, 'rcr': rcr, 'sar': sar, 'shr': shr, 'sal': shl, 'shl': shl, 'shld': shld, 'cmc': cmc, 'clc': clc, 'stc': stc, 'cld': cld, 'std': std, 'cli': cli, 'sti': sti, 'bsf': bsf, 'bsr': bsr, 'inc': inc, 'dec': dec, 'push': push, 'pushw': pushw, 'pop': pop, 'popw': popw, 'sete': sete, 'setnz': setnz, 'setl': setl, 'setg': setg, 'setge': setge, 'seta': seta, 'setae': setae, 'setb': setb, 'setbe': setbe, 'setns': setns, 'sets': sets, 'seto': seto, 'setp': setp, 'setpe': setp, 'setnp': setnp, 'setpo': setnp, 'setle': setle, 'setng': setle, 'setna': setna, 'setnbe': setnbe, 'setno': setno, 'setnc': setnb, 'setz': sete, 'setne': setnz, 'setnb': setae, 'setnae': setb, 'setc': setb, 'setnge': setl, 'setnl': setge, 'setnle': setg, 'setalc': setalc, 'bswap': bswap, 'cmpsb': lambda ir, instr: cmps(ir, instr, 8), 'cmpsw': lambda ir, instr: cmps(ir, instr, 16), 'cmpsd': lambda ir, instr: cmps(ir, instr, 32), 'cmpsq': lambda ir, instr: cmps(ir, instr, 64), 'scasb': lambda ir, instr: scas(ir, instr, 8), 'scasw': lambda ir, instr: scas(ir, instr, 16), 'scasd': lambda ir, instr: scas(ir, instr, 32), 'scasq': lambda ir, instr: scas(ir, instr, 64), 'pushfd': pushfd, 'pushfq': pushfq, 'pushfw': pushfw, 'popfd': popfd, 'popfq': popfd, 'popfw': popfw, 'pusha': pusha, 'pushad': pushad, 'popad': popad, 'popa': popa, 'call': call, 'ret': ret, 'retf': retf, 'iret': iret, 'iretd': iret, 'leave': leave, 'enter': enter, 'jmp': jmp, 'jz': jz, 'je': jz, 'jcxz': jcxz, 'jecxz': jecxz, 'jrcxz': jrcxz, 'jnz': jnz, 'jp': jp, 'jpe': jp, 'jnp': jnp, 'ja': ja, 'jae': jae, 'jb': jb, 'jbe': jbe, 'jg': jg, 'jge': jge, 'jl': jl, 'jle': jle, 'js': js, 'jns': jns, 'jo': jo, 'jno': jno, 'jecxz': jecxz, 'loop': loop, 'loopne': loopne, 'loope': loope, 'div': div, 'mul': mul, 'imul': imul, 'idiv': idiv, 'cbw': cbw, 'cwde': cwde, 'cdqe': cdqe, 'cwd': cwd, 'cdq': cdq, 'cqo': cqo, 'daa': daa, 'das': das, 'aam': aam, 'aad': aad, 'aaa': aaa, 'aas': aas, 'shrd': shrd, 'stosb': lambda ir, instr: stos(ir, instr, 8), 'stosw': lambda ir, instr: stos(ir, instr, 16), 'stosd': lambda ir, instr: stos(ir, instr, 32), 'stosq': lambda ir, instr: stos(ir, instr, 64), 'lodsb': lambda ir, instr: lods(ir, instr, 8), 'lodsw': lambda ir, instr: lods(ir, instr, 16), 'lodsd': lambda ir, instr: lods(ir, instr, 32), 'lodsq': lambda ir, instr: lods(ir, instr, 64), 'movsb': lambda ir, instr: movs(ir, instr, 8), 'movsw': lambda ir, instr: movs(ir, instr, 16), 'movsd': movsd_dispatch, 'movsq': lambda ir, instr: movs(ir, instr, 64), 'fcomp': fcomp, 'fcompp': fcompp, 'ficomp': ficomp, 'fucom': fucom, 'fucomp': fucomp, 'fucompp': fucompp, 'comiss': comiss, 'comisd': comisd, 'fcomi': fcomi, 'fcomip': fcomip, 'nop': nop, 'ud2': ud2, 'prefetch0': prefetch0, 'prefetch1': prefetch1, 'prefetch2': prefetch2, 'prefetchw': prefetchw, 'prefetchnta': prefetchnta, 'lfence': lfence, 'mfence': mfence, 'sfence': sfence, 'fnop': nop, # XXX 'hlt': hlt, 'rdtsc': rdtsc, 'fst': fst, 'fstp': fstp, 'fist': fist, 'fistp': fistp, 'fisttp': fisttp, 'fld': fld, 'fldz': fldz, 'fld1': fld1, 'fldl2t': fldl2t, 'fldpi': fldpi, 'fldln2': fldln2, 'fldl2e': fldl2e, 'fldlg2': fldlg2, 'fild': fild, 'fadd': fadd, 'fiadd': fiadd, 'fisub': fisub, 'fisubr': fisubr, 'fpatan': fpatan, 'fprem': fprem, 'fprem1': fprem1, 'fninit': fninit, 'fyl2x': fyl2x, 'faddp': faddp, 'fsub': fsub, 'fsubp': fsubp, 'fsubr': fsubr, 'fsubrp': fsubrp, 'fmul': fmul, 'fimul': fimul, 'fmulp': fmulp, 'fdiv': fdiv, 'fdivr': fdivr, 'fdivrp': fdivrp, 'fidiv': fidiv, 'fidivr': fidivr, 'fdivp': fdivp, 'fxch': fxch, 'fptan': fptan, 'frndint': frndint, 'fsin': fsin, 'fcos': fcos, 'fsincos': fsincos, 'fscale': fscale, 'f2xm1': f2xm1, 'fchs': fchs, 'fsqrt': fsqrt, 'fabs': fabs, 'fnstsw': fnstsw, 'fnstcw': fnstcw, 'fldcw': fldcw, 'fwait': fwait, 'fcmovb': fcmovb, 'fcmove': fcmove, 'fcmovbe': fcmovbe, 'fcmovu': fcmovu, 'fcmovnb': fcmovnb, 'fcmovne': fcmovne, 'fcmovnbe': fcmovnbe, 'fcmovnu': fcmovnu, 'fnstenv': fnstenv, 'fldenv': fldenv, 'sidt': sidt, 'sldt': sldt, 'arpl': arpl, 'cmovz': cmovz, 'cmove': cmovz, 'cmovnz': cmovnz, 'cmovpe': cmovpe, 'cmovnp': cmovnp, 'cmovge': cmovge, 'cmovnl': cmovge, 'cmovg': cmovg, 'cmovl': cmovl, 'cmova': cmova, 'cmovae': cmovae, 'cmovbe': cmovbe, 'cmovb': cmovb, 'cmovnge': cmovl, 'cmovle': cmovle, 'cmovng': cmovle, 'cmovo': cmovo, 'cmovno': cmovno, 'cmovs': cmovs, 'cmovns': cmovns, 'icebp': icebp, 'int': l_int, 'xlat': xlat, 'bt': bt, 'cpuid': cpuid, 'jo': jo, 'fcom': fcom, 'ftst': ftst, 'fxam': fxam, 'ficom': ficom, 'fcomi': fcomi, 'fcomip': fcomip, 'fucomi': fucomi, 'fucomip': fucomip, 'insb': lambda ir, instr: ins(ir, instr, 8), 'insw': lambda ir, instr: ins(ir, instr, 16), 'insd': lambda ir, instr: ins(ir, instr, 32), 'btc': btc, 'bts': bts, 'btr': btr, 'into': into, 'in': l_in, 'outsb': lambda ir, instr: l_outs(ir, instr, 8), 'outsw': lambda ir, instr: l_outs(ir, instr, 16), 'outsd': lambda ir, instr: l_outs(ir, instr, 32), 'out': l_out, "sysenter": l_sysenter, "syscall": l_syscall, "cmpxchg": cmpxchg, "cmpxchg8b": cmpxchg8b, "lds": lds, "les": les, "lss": lss, "lfs": lfs, "lgs": lgs, "lahf": lahf, "sahf": sahf, "lar": lar, "lsl": lsl, "fclex": fclex, "fnclex": fnclex, "str": l_str, "movd": movd, "movdqu": movdqu, "movdqa": movdqu, "movapd": movapd, # XXX TODO alignement check "movupd": movapd, # XXX TODO alignement check "movaps": movapd, # XXX TODO alignement check "movups": movapd, # XXX TODO alignement check "andps": andps, "andpd": andps, "andnps": andnps, "andnpd": andnps, "orps": orps, "orpd": orps, "xorps": xorps, "xorpd": xorps, "movq": movq, "pminsw": pminsw, "cvtdq2pd": cvtdq2pd, "cvtdq2ps": cvtdq2ps, "cvtpd2dq": cvtpd2dq, "cvtpd2pi": cvtpd2pi, "cvtpd2ps": cvtpd2ps, "cvtpi2pd": cvtpi2pd, "cvtpi2ps": cvtpi2ps, "cvtps2dq": cvtps2dq, "cvtps2pd": cvtps2pd, "cvtps2pi": cvtps2pi, "cvtsd2si": cvtsd2si, "cvtsd2ss": cvtsd2ss, "cvtsi2sd": cvtsi2sd, "cvtsi2ss": cvtsi2ss, "cvtss2sd": cvtss2sd, "cvtss2si": cvtss2si, "cvttpd2pi": cvttpd2pi, "cvttpd2dq": cvttpd2dq, "cvttps2dq": cvttps2dq, "cvttps2pi": cvttps2pi, "cvttsd2si": cvttsd2si, "cvttss2si": cvttss2si, "bndmov": bndmov, "movss": movss, "ucomiss": ucomiss, "ucomisd": ucomisd, # # MMX/AVX/SSE operations # Arithmetic (integers) # # Additions # SSE "paddb": paddb, "paddw": paddw, "paddd": paddd, "paddq": paddq, # Substractions # SSE "psubb": psubb, "psubw": psubw, "psubd": psubd, "psubq": psubq, # Multiplications # SSE "pmullb": pmullb, "pmullw": pmullw, "pmulld": pmulld, "pmullq": pmullq, "pmulhub": pmulhub, "pmulhuw": pmulhuw, "pmulhud": pmulhud, "pmulhuq": pmulhuq, "pmulhb": pmulhb, "pmulhw": pmulhw, "pmulhd": pmulhd, "pmulhq": pmulhq, "pmuludq": pmuludq, # Mix # SSE "pmaddwd": pmaddwd, "psadbw": psadbw, "pavgb": pavgb, "pavgw": pavgw, # Arithmetic (floating-point) # # Additions # SSE "addss": addss, "addsd": addsd, "addps": addps, "addpd": addpd, # Substractions # SSE "subss": subss, "subsd": subsd, "subps": subps, "subpd": subpd, # Multiplications # SSE "mulss": mulss, "mulsd": mulsd, "mulps": mulps, "mulpd": mulpd, # Divisions # SSE "divss": divss, "divsd": divsd, "divps": divps, "divpd": divpd, # Comparisons (floating-point) # "minps": minps, "minpd": minpd, "minss": minss, "minsd": minsd, "maxps": maxps, "maxpd": maxpd, "maxss": maxss, "maxsd": maxsd, "cmpeqps": cmpeqps, "cmpeqpd": cmpeqpd, "cmpeqss": cmpeqss, "cmpeqsd": cmpeqsd, "cmpltps": cmpltps, "cmpltpd": cmpltpd, "cmpltss": cmpltss, "cmpltsd": cmpltsd, "cmpleps": cmpleps, "cmplepd": cmplepd, "cmpless": cmpless, "cmplesd": cmplesd, "cmpunordps": cmpunordps, "cmpunordpd": cmpunordpd, "cmpunordss": cmpunordss, "cmpunordsd": cmpunordsd, "cmpneqps": cmpneqps, "cmpneqpd": cmpneqpd, "cmpneqss": cmpneqss, "cmpneqsd": cmpneqsd, "cmpnltps": cmpnltps, "cmpnltpd": cmpnltpd, "cmpnltss": cmpnltss, "cmpnltsd": cmpnltsd, "cmpnleps": cmpnleps, "cmpnlepd": cmpnlepd, "cmpnless": cmpnless, "cmpnlesd": cmpnlesd, "cmpordps": cmpordps, "cmpordpd": cmpordpd, "cmpordss": cmpordss, "cmpordsd": cmpordsd, # Logical (floating-point) # "pand": pand, "pandn": pandn, "por": por, "rdmsr": rdmsr, "wrmsr": wrmsr, "pshufb": pshufb, "pshufd": pshufd, "pshuflw": pshuflw, "pshufhw": pshufhw, "psrlw": psrlw, "psrld": psrld, "psrlq": psrlq, "psllw": psllw, "pslld": pslld, "psllq": psllq, "pslldq": pslldq, "psrldq": psrldq, "psraw": psraw, "psrad": psrad, "palignr": palignr, "pmaxub": pmaxub, "pmaxuw": pmaxuw, "pmaxud": pmaxud, "pmaxsw": pmaxsw, "pminub": pminub, "pminuw": pminuw, "pminud": pminud, "pcmpeqb": pcmpeqb, "pcmpeqw": pcmpeqw, "pcmpeqd": pcmpeqd, "pcmpeqq": pcmpeqq, "pcmpgtb": pcmpgtb, "pcmpgtw": pcmpgtw, "pcmpgtd": pcmpgtd, "pcmpgtq": pcmpgtq, "punpckhbw": punpckhbw, "punpckhwd": punpckhwd, "punpckhdq": punpckhdq, "punpckhqdq": punpckhqdq, "punpcklbw": punpcklbw, "punpcklwd": punpcklwd, "punpckldq": punpckldq, "punpcklqdq": punpcklqdq, "pinsrb": pinsrb, "pinsrw": pinsrw, "pinsrd": pinsrd, "pinsrq": pinsrq, "pextrb": pextrb, "pextrw": pextrw, "pextrd": pextrd, "pextrq": pextrq, "unpckhps": unpckhps, "unpckhpd": unpckhpd, "unpcklps": unpcklps, "unpcklpd": unpcklpd, "movlpd": movlpd, "movlps": movlps, "movhpd": movhpd, "movhps": movhpd, "movlhps": movlhps, "movhlps": movhlps, "movdq2q": movdq2q, "movq2dq": movq2dq, "sqrtpd": sqrtpd, "sqrtps": sqrtps, "sqrtsd": sqrtsd, "sqrtss": sqrtss, "pmovmskb": pmovmskb, "packsswb": packsswb, "packssdw": packssdw, "packuswb": packuswb, "psubusb": psubusb, "psubusw": psubusw, "paddusb": paddusb, "paddusw": paddusw, "psubsb": psubsb, "psubsw": psubsw, "paddsb": paddsb, "paddsw": paddsw, "smsw": smsw, "maskmovq": maskmovq, "maskmovdqu": maskmovq, "emms": emms, "shufps": shufps, "shufpd": shufpd, "movmskps": movmskps, "movmskpd": movmskpd, "stmxcsr": stmxcsr, "ldmxcsr": ldmxcsr, } class ir_x86_16(IntermediateRepresentation): def __init__(self, loc_db=None): IntermediateRepresentation.__init__(self, mn_x86, 16, loc_db) self.do_stk_segm = False self.do_ds_segm = False self.do_str_segm = False self.do_all_segm = False self.pc = IP self.sp = SP self.IRDst = m2_expr.ExprId('IRDst', 16) # Size of memory pointer access in IR # 16 bit mode memory accesses may be greater than 16 bits # 32 bit size may be enought self.addrsize = 32 def mod_pc(self, instr, instr_ir, extra_ir): pass def ExprMem(self, ptr, size): """Generate a memory access to @ptr The ptr is resized to a fixed size self.addrsize @ptr: Expr instance to the memory address @size: size of the memory""" return m2_expr.ExprMem(expraddr(self.addrsize, ptr), size) def gen_segm_expr(self, selector, addr): ptr = m2_expr.ExprOp( 'segm', selector, addr.zeroExtend(self.addrsize) ) return ptr def get_ir(self, instr): args = instr.args[:] args = [arg.replace_expr(float_replace) for arg in args] args = fix_mem_args_size(instr, *args) my_ss = None if self.do_ds_segm: my_ss = DS if self.do_all_segm and instr.additional_info.g2.value: my_ss = {1: CS, 2: SS, 3: DS, 4: ES, 5: FS, 6: GS}[ instr.additional_info.g2.value] if my_ss is not None: for i, a in enumerate(args): if a.is_mem() and not a.is_mem_segm(): args[i] = self.ExprMem(m2_expr.ExprOp('segm', my_ss, a.arg), a.size) if not instr.name.lower() in mnemo_func: raise NotImplementedError( "Mnemonic %s not implemented" % instr.name) instr_ir, extra_ir = mnemo_func[ instr.name.lower()](self, instr, *args) self.mod_pc(instr, instr_ir, extra_ir) instr.additional_info.except_on_instr = False if instr.additional_info.g1.value & 6 == 0 or \ not instr.name in repeat_mn: return instr_ir, extra_ir if instr.name == "MOVSD" and len(instr.args) == 2: return instr_ir, extra_ir instr.additional_info.except_on_instr = True # get instruction size s = {"B": 8, "W": 16, "D": 32, 'Q': 64}[instr.name[-1]] size = instr.v_opmode() admode = instr.v_admode() c_reg = mRCX[instr.mode][:admode] out_ir = [] zf_val = None # set if zf is tested (cmps, scas) for e in instr_ir: # +[updt_c]: if e.dst == zf: zf_val = e.src cond_dec = m2_expr.ExprCond(c_reg - m2_expr.ExprInt(1, c_reg.size), m2_expr.ExprInt(0, 1), m2_expr.ExprInt(1, 1)) # end condition if zf_val is None: c_cond = cond_dec elif instr.additional_info.g1.value & 2: # REPNE c_cond = cond_dec | zf elif instr.additional_info.g1.value & 4: # REP c_cond = cond_dec | (zf ^ m2_expr.ExprInt(1, 1)) # gen while loc_do, loc_do_expr = self.gen_loc_key_and_expr(self.IRDst.size) loc_end, loc_end_expr = self.gen_loc_key_and_expr(self.IRDst.size) loc_skip = self.get_next_loc_key(instr) loc_skip_expr = m2_expr.ExprLoc(loc_skip, self.IRDst.size) loc_next = self.get_next_loc_key(instr) loc_next_expr = m2_expr.ExprLoc(loc_next, self.IRDst.size) fix_next_loc = {loc_next_expr: loc_end_expr} new_extra_ir = [irblock.modify_exprs(mod_src=lambda expr: expr.replace_expr(fix_next_loc)) for irblock in extra_ir] cond_bloc = [] cond_bloc.append(m2_expr.ExprAff(c_reg, c_reg - m2_expr.ExprInt(1, c_reg.size))) cond_bloc.append(m2_expr.ExprAff(self.IRDst, m2_expr.ExprCond(c_cond, loc_skip_expr, loc_do_expr))) cond_bloc = IRBlock(loc_end, [AssignBlock(cond_bloc, instr)]) e_do = instr_ir c = IRBlock(loc_do, [AssignBlock(e_do, instr)]) e_n = [m2_expr.ExprAff(self.IRDst, m2_expr.ExprCond(c_reg, loc_do_expr, loc_skip_expr))] return e_n, [cond_bloc, c] + new_extra_ir def expr_fix_regs_for_mode(self, e, mode=64): return e.replace_expr(replace_regs[mode]) def expraff_fix_regs_for_mode(self, e, mode=64): dst = self.expr_fix_regs_for_mode(e.dst, mode) src = self.expr_fix_regs_for_mode(e.src, mode) return m2_expr.ExprAff(dst, src) def irbloc_fix_regs_for_mode(self, irblock, mode=64): irs = [] for assignblk in irblock: new_assignblk = dict(assignblk) for dst, src in assignblk.iteritems(): del new_assignblk[dst] # Special case for 64 bits: # If destination is a 32 bit reg, zero extend the 64 bit reg if mode == 64: if (isinstance(dst, m2_expr.ExprId) and dst.size == 32 and dst in replace_regs[64]): src = src.zeroExtend(64) dst = replace_regs[64][dst].arg dst = self.expr_fix_regs_for_mode(dst, mode) src = self.expr_fix_regs_for_mode(src, mode) new_assignblk[dst] = src irs.append(AssignBlock(new_assignblk, assignblk.instr)) return IRBlock(irblock.loc_key, irs) class ir_x86_32(ir_x86_16): def __init__(self, loc_db=None): IntermediateRepresentation.__init__(self, mn_x86, 32, loc_db) self.do_stk_segm = False self.do_ds_segm = False self.do_str_segm = False self.do_all_segm = False self.pc = EIP self.sp = ESP self.IRDst = m2_expr.ExprId('IRDst', 32) self.addrsize = 32 class ir_x86_64(ir_x86_16): def __init__(self, loc_db=None): IntermediateRepresentation.__init__(self, mn_x86, 64, loc_db) self.do_stk_segm = False self.do_ds_segm = False self.do_str_segm = False self.do_all_segm = False self.pc = RIP self.sp = RSP self.IRDst = m2_expr.ExprId('IRDst', 64) self.addrsize = 64 def mod_pc(self, instr, instr_ir, extra_ir): # fix RIP for 64 bit pc_fixed = {self.pc: m2_expr.ExprInt(instr.offset + instr.l, 64)} for i, expr in enumerate(instr_ir): dst, src = expr.dst, expr.src if dst != self.pc: dst = dst.replace_expr(pc_fixed) src = src.replace_expr(pc_fixed) instr_ir[i] = m2_expr.ExprAff(dst, src) for idx, irblock in enumerate(extra_ir): extra_ir[idx] = irblock.modify_exprs(lambda expr: expr.replace_expr(pc_fixed) \ if expr != self.pc else expr, lambda expr: expr.replace_expr(pc_fixed))
Module variables
var CONSOLE_HANDLER
var EXCEPT_DIV_BY_ZERO
var EXCEPT_ILLEGAL_INSN
var EXCEPT_INT_XX
var EXCEPT_PRIV_INSN
var EXCEPT_SOFT_BP
var LOG_X86_SEM
var STMXCSR_VALUE
var all_regs_ids
var all_regs_ids_byname
var all_regs_ids_init
var all_regs_ids_no_alias
var attrib_to_regs
var crregs32_expr
var crregs32_str
var ctx
var drregs32_expr
var drregs32_str
var float_list
var float_replace
var fltregs32_expr
var fltregs32_str
var i
var mRAX
var mRBP
var mRBX
var mRCX
var mRDI
var mRDX
var mRIP
var mRSI
var mRSP
var mnemo_func
var pa_regs
var reg_ac
var reg_af
var reg_cf
var reg_cr0
var reg_cr1
var reg_cr2
var reg_cr3
var reg_cr4
var reg_cr5
var reg_cr6
var reg_cr7
var reg_cs
var reg_df
var reg_dr0
var reg_dr1
var reg_dr2
var reg_dr3
var reg_dr4
var reg_dr5
var reg_dr6
var reg_dr7
var reg_ds
var reg_es
var reg_float_address
var reg_float_c0
var reg_float_c1
var reg_float_c2
var reg_float_c3
var reg_float_control
var reg_float_cs
var reg_float_ds
var reg_float_eip
var reg_float_stack_ptr
var reg_fs
var reg_gs
var reg_id
var reg_if
var reg_iopl
var reg_mm0
var reg_mm1
var reg_mm2
var reg_mm3
var reg_mm4
var reg_mm5
var reg_mm6
var reg_mm7
var reg_nf
var reg_nt
var reg_of
var reg_pf
var reg_rf
var reg_ss
var reg_tf
var reg_tsc1
var reg_tsc2
var reg_vif
var reg_vip
var reg_vm
var reg_zf
var regs08_64_expr
var regs08_64_str
var regs08_expr
var regs08_str
var regs16_expr
var regs16_str
var regs32_expr
var regs32_str
var regs64_expr
var regs64_str
var regs_bnd_expr
var regs_bnd_str
var regs_flt_expr
var regs_init
var regs_mm_expr
var regs_mm_str
var regs_xmm_expr
var regs_xmm_str
var repeat_mn
var replace_regs
var sbuild
http://www.emulators.com/docs/nx11_flags.htm
CF(A+B) = (((A XOR B) XOR D) < 0) XOR (((A XOR D) AND NOT (A XOR B)) < 0) CF(A-B) = (((A XOR B) XOR D) < 0) XOR (((A XOR D) AND (A XOR B)) < 0)
OF(A+B) = ((A XOR D) AND NOT (A XOR B)) < 0 OF(A-B) = ((A XOR D) AND (A XOR B)) < 0
var selectr_expr
var selectr_str
Functions
def aaa(
ir, instr)
def aaa(ir, instr): return _tpl_aaa(ir, instr, "+")
def aad(
_, instr, src)
def aad(_, instr, src): e = [] tempAL = mRAX[instr.mode][0:8] tempAH = mRAX[instr.mode][8:16] newEAX = m2_expr.ExprCompose((tempAL + (tempAH * src)) & m2_expr.ExprInt(0xFF, 8), m2_expr.ExprInt(0, 8), mRAX[instr.mode][16:]) e += [m2_expr.ExprAff(mRAX[instr.mode], newEAX)] e += update_flag_arith(newEAX) e.append(m2_expr.ExprAff(af, m2_expr.ExprInt(0, 1))) return e, []
def aam(
_, instr, src)
def aam(_, instr, src): e = [] tempAL = mRAX[instr.mode][0:8] newEAX = m2_expr.ExprCompose(m2_expr.ExprOp("umod", tempAL, src), m2_expr.ExprOp("udiv", tempAL, src), mRAX[instr.mode][16:]) e += [m2_expr.ExprAff(mRAX[instr.mode], newEAX)] e += update_flag_arith(newEAX) e.append(m2_expr.ExprAff(af, m2_expr.ExprInt(0, 1))) return e, []
def aas(
ir, instr)
def aas(ir, instr): return _tpl_aaa(ir, instr, "-")
def adc(
_, instr, dst, src)
def adc(_, instr, dst, src): e = [] arg1 = dst arg2 = src result = arg1 + (arg2 + cf.zeroExtend(src.size)) e += update_flag_arith_addwc_znp(arg1, arg2, cf) e += update_flag_arith_addwc_co(arg1, arg2, cf) e += update_flag_af(arg1, arg2, result) e.append(m2_expr.ExprAff(dst, result)) return e, []
def add(
_, instr, dst, src)
def add(_, instr, dst, src): e = [] result = dst + src e += update_flag_arith_add_znp(dst, src) e += update_flag_arith_add_co(dst, src, result) e += update_flag_af(dst, src, result) e.append(m2_expr.ExprAff(dst, result)) return e, []
def addpd(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def addps(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def addsd(
ir, instr, dst, src)
def vec_op_clip_instr(ir, instr, dst, src): if op == '-': result = dst[:size] - src[:size] else: result = m2_expr.ExprOp(op, dst[:size], src[:size]) if callback is not None: result = callback(result) return [m2_expr.ExprAff(dst[:size], result)], []
def addss(
ir, instr, dst, src)
def vec_op_clip_instr(ir, instr, dst, src): if op == '-': result = dst[:size] - src[:size] else: result = m2_expr.ExprOp(op, dst[:size], src[:size]) if callback is not None: result = callback(result) return [m2_expr.ExprAff(dst[:size], result)], []
def andnps(
_, instr, dst, src)
def andnps(_, instr, dst, src): e = [] e.append(m2_expr.ExprAff(dst, m2_expr.ExprOp('&', dst ^ dst.mask, src))) return e, []
def andps(
_, instr, dst, src)
def andps(_, instr, dst, src): e = [] e.append(m2_expr.ExprAff(dst, m2_expr.ExprOp('&', dst, src))) return e, []
def arith_flag(
a, b, c)
def arith_flag(a, b, c): a_s, b_s, c_s = a.size, b.size, c.size check_ops_msb(a_s, b_s, c_s) a_s, b_s, c_s = a.msb(), b.msb(), c.msb() return a_s, b_s, c_s
def arpl(
_, instr, dst, src)
def arpl(_, instr, dst, src): e = [] e.append(m2_expr.ExprAff(exception_flags, m2_expr.ExprInt(1 << 7, 32))) return e, []
def bittest_get(
ir, instr, src, index)
def bittest_get(ir, instr, src, index): index = index.zeroExtend(src.size) if isinstance(src, m2_expr.ExprMem): b_mask = {16: 4, 32: 5, 64: 6} b_decal = {16: 1, 32: 3, 64: 7} ptr = src.arg segm = src.is_mem_segm() if segm: ptr = ptr.args[1] off_bit = index.zeroExtend( src.size) & m2_expr.ExprInt((1 << b_mask[src.size]) - 1, src.size) off_byte = ((index.zeroExtend(ptr.size) >> m2_expr.ExprInt(3, ptr.size)) & m2_expr.ExprInt(((1 << src.size) - 1) ^ b_decal[src.size], ptr.size)) addr = ptr + off_byte if segm: addr = ir.gen_segm_expr(src.arg.args[0], addr) d = ir.ExprMem(addr, src.size) else: off_bit = m2_expr.ExprOp( '&', index, m2_expr.ExprInt(src.size - 1, src.size)) d = src return d, off_bit
def bndmov(
ir, instr, dst, src)
def bndmov(ir, instr, dst, src): # Implemented as a NOP, because BND side effects are not yet supported return [], []
def bsf(
ir, instr, dst, src)
def bsf(ir, instr, dst, src): return bsr_bsf(ir, instr, dst, src, lambda src: m2_expr.ExprOp("cnttrailzeros", src))
def bsr(
ir, instr, dst, src)
def bsr(ir, instr, dst, src): return bsr_bsf( ir, instr, dst, src, lambda src: m2_expr.ExprInt(src.size - 1, src.size) - m2_expr.ExprOp("cntleadzeros", src) )
def bsr_bsf(
ir, instr, dst, src, op_func)
IF SRC == 0 ZF = 1 DEST is left unchanged ELSE ZF = 0 DEST = @op_func(SRC)
def bsr_bsf(ir, instr, dst, src, op_func): """ IF SRC == 0 ZF = 1 DEST is left unchanged ELSE ZF = 0 DEST = @op_func(SRC) """ loc_src_null, loc_src_null_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) loc_src_not_null, loc_src_not_null_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) loc_next = ir.get_next_loc_key(instr) loc_next_expr = m2_expr.ExprLoc(loc_next, ir.IRDst.size) aff_dst = m2_expr.ExprAff(ir.IRDst, loc_next_expr) e = [m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(src, loc_src_not_null_expr, loc_src_null_expr))] e_src_null = [] e_src_null.append(m2_expr.ExprAff(zf, m2_expr.ExprInt(1, zf.size))) # XXX destination is undefined e_src_null.append(aff_dst) e_src_not_null = [] e_src_not_null.append(m2_expr.ExprAff(zf, m2_expr.ExprInt(0, zf.size))) e_src_not_null.append(m2_expr.ExprAff(dst, op_func(src))) e_src_not_null.append(aff_dst) return e, [IRBlock(loc_src_null, [AssignBlock(e_src_null, instr)]), IRBlock(loc_src_not_null, [AssignBlock(e_src_not_null, instr)])]
def bswap(
_, instr, dst)
def bswap(_, instr, dst): e = [] if dst.size == 16: result = m2_expr.ExprCompose(dst[8:16], dst[:8]) elif dst.size == 32: result = m2_expr.ExprCompose( dst[24:32], dst[16:24], dst[8:16], dst[:8]) elif dst.size == 64: result = m2_expr.ExprCompose(dst[56:64], dst[48:56], dst[40:48], dst[32:40], dst[24:32], dst[16:24], dst[8:16], dst[:8]) else: raise ValueError('the size DOES matter') e.append(m2_expr.ExprAff(dst, result)) return e, []
def bt(
ir, instr, src, index)
def bt(ir, instr, src, index): e = [] index = index.zeroExtend(src.size) d, off_bit = bittest_get(ir, instr, src, index) d = d >> off_bit e.append(m2_expr.ExprAff(cf, d[:1])) return e, []
def btc(
ir, instr, src, index)
def btc(ir, instr, src, index): e = [] d, off_bit = bittest_get(ir, instr, src, index) e.append(m2_expr.ExprAff(cf, (d >> off_bit)[:1])) m = m2_expr.ExprInt(1, src.size) << off_bit e.append(m2_expr.ExprAff(d, d ^ m)) return e, []
def btr(
ir, instr, src, index)
def btr(ir, instr, src, index): e = [] d, off_bit = bittest_get(ir, instr, src, index) e.append(m2_expr.ExprAff(cf, (d >> off_bit)[:1])) m = ~(m2_expr.ExprInt(1, src.size) << off_bit) e.append(m2_expr.ExprAff(d, d & m)) return e, []
def bts(
ir, instr, src, index)
def bts(ir, instr, src, index): e = [] d, off_bit = bittest_get(ir, instr, src, index) e.append(m2_expr.ExprAff(cf, (d >> off_bit)[:1])) m = m2_expr.ExprInt(1, src.size) << off_bit e.append(m2_expr.ExprAff(d, d | m)) return e, []
def call(
ir, instr, dst)
def call(ir, instr, dst): e = [] # opmode, admode = instr.opmode, instr.admode s = dst.size meip = mRIP[ir.IRDst.size] opmode, admode = s, instr.v_admode() myesp = mRSP[instr.mode][:opmode] n = m2_expr.ExprLoc(ir.get_next_loc_key(instr), ir.IRDst.size) if isinstance(dst, m2_expr.ExprOp): if dst.op == "segm": # Far call segm:addr if instr.mode not in [16, 32]: raise RuntimeError('not supported') segm = dst.args[0] base = dst.args[1] m1 = segm.zeroExtend(CS.size) m2 = base.zeroExtend(meip.size) elif dst.op == "far": # Far call far [eax] addr = dst.args[0].arg m1 = ir.ExprMem(addr, CS.size) m2 = ir.ExprMem(addr + m2_expr.ExprInt(2, addr.size), meip.size) else: raise RuntimeError("bad call operator") e.append(m2_expr.ExprAff(CS, m1)) e.append(m2_expr.ExprAff(meip, m2)) e.append(m2_expr.ExprAff(ir.IRDst, m2)) c = myesp + m2_expr.ExprInt(-s / 8, s) e.append(m2_expr.ExprAff(ir.ExprMem(c, size=s).zeroExtend(s), CS.zeroExtend(s))) c = myesp + m2_expr.ExprInt(-2 * s / 8, s) e.append(m2_expr.ExprAff(ir.ExprMem(c, size=s).zeroExtend(s), meip.zeroExtend(s))) c = myesp + m2_expr.ExprInt((-2 * s) / 8, s) e.append(m2_expr.ExprAff(myesp, c)) return e, [] c = myesp + m2_expr.ExprInt((-s / 8), s) e.append(m2_expr.ExprAff(myesp, c)) if ir.do_stk_segm: c = ir.gen_segm_expr(SS, c) e.append(m2_expr.ExprAff(ir.ExprMem(c, size=s), n)) e.append(m2_expr.ExprAff(meip, dst.zeroExtend(ir.IRDst.size))) e.append(m2_expr.ExprAff(ir.IRDst, dst.zeroExtend(ir.IRDst.size))) return e, []
def cbw(
_, instr)
def cbw(_, instr): # Only in 16 bit e = [] tempAL = mRAX[instr.v_opmode()][:8] tempAX = mRAX[instr.v_opmode()][:16] e.append(m2_expr.ExprAff(tempAX, tempAL.signExtend(16))) return e, []
def cdq(
_, instr)
def cdq(_, instr): # Only in 32/64 bit e = [] tempEAX = mRAX[instr.v_opmode()] tempEDX = mRDX[instr.v_opmode()] result = tempEAX.signExtend(64) e.append(m2_expr.ExprAff(tempEDX, result[32:64])) return e, []
def cdqe(
_, instr)
def cdqe(_, instr): # Only in 64 bit e = [] tempEAX = mRAX[instr.mode][:32] tempRAX = mRAX[instr.mode][:64] e.append(m2_expr.ExprAff(tempRAX, tempEAX.signExtend(64))) return e, []
def check_ops_msb(
a, b, c)
def check_ops_msb(a, b, c): if not a or not b or not c or a != b or a != c: raise ValueError('bad ops size %s %s %s' % (a, b, c))
def clc(
_, instr)
def clc(_, instr): e = [m2_expr.ExprAff(cf, m2_expr.ExprInt(0, cf.size))] return e, []
def cld(
_, instr)
def cld(_, instr): e = [m2_expr.ExprAff(df, m2_expr.ExprInt(0, df.size))] return e, []
def cli(
_, instr)
def cli(_, instr): e = [m2_expr.ExprAff(i_f, m2_expr.ExprInt(0, i_f.size))] return e, []
def cmc(
_, instr)
def cmc(_, instr): e = [m2_expr.ExprAff(cf, m2_expr.ExprCond(cf, m2_expr.ExprInt(0, cf.size), m2_expr.ExprInt(1, cf.size)))] return e, []
def cmova(
ir, instr, dst, src)
def cmova(ir, instr, dst, src): #return gen_cmov(ir, instr, cf | zf, dst, src, False) return gen_cmov(ir, instr, m2_expr.ExprOp("CC_U>", cf, zf), dst, src, True)
def cmovae(
ir, instr, dst, src)
def cmovae(ir, instr, dst, src): #return gen_cmov(ir, instr, cf, dst, src, False) return gen_cmov(ir, instr, m2_expr.ExprOp("CC_U>=", cf), dst, src, True)
def cmovb(
ir, instr, dst, src)
def cmovb(ir, instr, dst, src): #return gen_cmov(ir, instr, cf, dst, src, True) return gen_cmov(ir, instr, m2_expr.ExprOp("CC_U<", cf), dst, src, True)
def cmovbe(
ir, instr, dst, src)
def cmovbe(ir, instr, dst, src): #return gen_cmov(ir, instr, cf | zf, dst, src, True) return gen_cmov(ir, instr, m2_expr.ExprOp("CC_U<=", cf, zf), dst, src, True)
def cmovg(
ir, instr, dst, src)
def cmovg(ir, instr, dst, src): #return gen_cmov(ir, instr, zf | (nf ^ of), dst, src, False) return gen_cmov(ir, instr, m2_expr.ExprOp("CC_S>", nf, of, zf), dst, src, True)
def cmovge(
ir, instr, dst, src)
def cmovge(ir, instr, dst, src): #return gen_cmov(ir, instr, nf ^ of, dst, src, False) return gen_cmov(ir, instr, m2_expr.ExprOp("CC_S>=", nf, of), dst, src, True)
def cmovl(
ir, instr, dst, src)
def cmovl(ir, instr, dst, src): #return gen_cmov(ir, instr, nf ^ of, dst, src, True) return gen_cmov(ir, instr, m2_expr.ExprOp("CC_S<", nf, of), dst, src, True)
def cmovle(
ir, instr, dst, src)
def cmovle(ir, instr, dst, src): #return gen_cmov(ir, instr, zf | (nf ^ of), dst, src, True) return gen_cmov(ir, instr, m2_expr.ExprOp("CC_S<=", nf, of, zf), dst, src, True)
def cmovno(
ir, instr, dst, src)
def cmovno(ir, instr, dst, src): return gen_cmov(ir, instr, of, dst, src, False)
def cmovnp(
ir, instr, dst, src)
def cmovnp(ir, instr, dst, src): return gen_cmov(ir, instr, pf, dst, src, False)
def cmovns(
ir, instr, dst, src)
def cmovns(ir, instr, dst, src): #return gen_cmov(ir, instr, nf, dst, src, False) return gen_cmov(ir, instr, m2_expr.ExprOp("CC_NEG", nf), dst, src, False)
def cmovnz(
ir, instr, dst, src)
def cmovnz(ir, instr, dst, src): #return gen_cmov(ir, instr, zf, dst, src, False) return gen_cmov(ir, instr, m2_expr.ExprOp("CC_EQ", zf), dst, src, False)
def cmovo(
ir, instr, dst, src)
def cmovo(ir, instr, dst, src): return gen_cmov(ir, instr, of, dst, src, True)
def cmovpe(
ir, instr, dst, src)
def cmovpe(ir, instr, dst, src): return gen_cmov(ir, instr, pf, dst, src, True)
def cmovs(
ir, instr, dst, src)
def cmovs(ir, instr, dst, src): #return gen_cmov(ir, instr, nf, dst, src, True) return gen_cmov(ir, instr, m2_expr.ExprOp("CC_NEG", nf), dst, src, True)
def cmovz(
ir, instr, dst, src)
def cmovz(ir, instr, dst, src): #return gen_cmov(ir, instr, zf, dst, src, True) return gen_cmov(ir, instr, m2_expr.ExprOp("CC_EQ", zf), dst, src, True)
def cmpeqpd(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def cmpeqps(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def cmpeqsd(
ir, instr, dst, src)
def vec_op_clip_instr(ir, instr, dst, src): if op == '-': result = dst[:size] - src[:size] else: result = m2_expr.ExprOp(op, dst[:size], src[:size]) if callback is not None: result = callback(result) return [m2_expr.ExprAff(dst[:size], result)], []
def cmpeqss(
ir, instr, dst, src)
def vec_op_clip_instr(ir, instr, dst, src): if op == '-': result = dst[:size] - src[:size] else: result = m2_expr.ExprOp(op, dst[:size], src[:size]) if callback is not None: result = callback(result) return [m2_expr.ExprAff(dst[:size], result)], []
def cmplepd(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def cmpleps(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def cmplesd(
ir, instr, dst, src)
def vec_op_clip_instr(ir, instr, dst, src): if op == '-': result = dst[:size] - src[:size] else: result = m2_expr.ExprOp(op, dst[:size], src[:size]) if callback is not None: result = callback(result) return [m2_expr.ExprAff(dst[:size], result)], []
def cmpless(
ir, instr, dst, src)
def vec_op_clip_instr(ir, instr, dst, src): if op == '-': result = dst[:size] - src[:size] else: result = m2_expr.ExprOp(op, dst[:size], src[:size]) if callback is not None: result = callback(result) return [m2_expr.ExprAff(dst[:size], result)], []
def cmpltpd(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def cmpltps(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def cmpltsd(
ir, instr, dst, src)
def vec_op_clip_instr(ir, instr, dst, src): if op == '-': result = dst[:size] - src[:size] else: result = m2_expr.ExprOp(op, dst[:size], src[:size]) if callback is not None: result = callback(result) return [m2_expr.ExprAff(dst[:size], result)], []
def cmpltss(
ir, instr, dst, src)
def vec_op_clip_instr(ir, instr, dst, src): if op == '-': result = dst[:size] - src[:size] else: result = m2_expr.ExprOp(op, dst[:size], src[:size]) if callback is not None: result = callback(result) return [m2_expr.ExprAff(dst[:size], result)], []
def cmpneqpd(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def cmpneqps(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def cmpneqsd(
ir, instr, dst, src)
def vec_op_clip_instr(ir, instr, dst, src): if op == '-': result = dst[:size] - src[:size] else: result = m2_expr.ExprOp(op, dst[:size], src[:size]) if callback is not None: result = callback(result) return [m2_expr.ExprAff(dst[:size], result)], []
def cmpneqss(
ir, instr, dst, src)
def vec_op_clip_instr(ir, instr, dst, src): if op == '-': result = dst[:size] - src[:size] else: result = m2_expr.ExprOp(op, dst[:size], src[:size]) if callback is not None: result = callback(result) return [m2_expr.ExprAff(dst[:size], result)], []
def cmpnlepd(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def cmpnleps(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def cmpnlesd(
ir, instr, dst, src)
def vec_op_clip_instr(ir, instr, dst, src): if op == '-': result = dst[:size] - src[:size] else: result = m2_expr.ExprOp(op, dst[:size], src[:size]) if callback is not None: result = callback(result) return [m2_expr.ExprAff(dst[:size], result)], []
def cmpnless(
ir, instr, dst, src)
def vec_op_clip_instr(ir, instr, dst, src): if op == '-': result = dst[:size] - src[:size] else: result = m2_expr.ExprOp(op, dst[:size], src[:size]) if callback is not None: result = callback(result) return [m2_expr.ExprAff(dst[:size], result)], []
def cmpnltpd(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def cmpnltps(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def cmpnltsd(
ir, instr, dst, src)
def vec_op_clip_instr(ir, instr, dst, src): if op == '-': result = dst[:size] - src[:size] else: result = m2_expr.ExprOp(op, dst[:size], src[:size]) if callback is not None: result = callback(result) return [m2_expr.ExprAff(dst[:size], result)], []
def cmpnltss(
ir, instr, dst, src)
def vec_op_clip_instr(ir, instr, dst, src): if op == '-': result = dst[:size] - src[:size] else: result = m2_expr.ExprOp(op, dst[:size], src[:size]) if callback is not None: result = callback(result) return [m2_expr.ExprAff(dst[:size], result)], []
def cmpordpd(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def cmpordps(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def cmpordsd(
ir, instr, dst, src)
def vec_op_clip_instr(ir, instr, dst, src): if op == '-': result = dst[:size] - src[:size] else: result = m2_expr.ExprOp(op, dst[:size], src[:size]) if callback is not None: result = callback(result) return [m2_expr.ExprAff(dst[:size], result)], []
def cmpordss(
ir, instr, dst, src)
def vec_op_clip_instr(ir, instr, dst, src): if op == '-': result = dst[:size] - src[:size] else: result = m2_expr.ExprOp(op, dst[:size], src[:size]) if callback is not None: result = callback(result) return [m2_expr.ExprAff(dst[:size], result)], []
def cmps(
ir, instr, size)
def cmps(ir, instr, size): loc_df_0, loc_df_0_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) loc_df_1, loc_df_1_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) loc_next_expr = m2_expr.ExprLoc(ir.get_next_loc_key(instr), ir.IRDst.size) src1 = mRSI[instr.mode][:instr.v_admode()] src2 = mRDI[instr.mode][:instr.v_admode()] if ir.do_str_segm: if instr.additional_info.g2.value: raise NotImplementedError("add segm support") src1_sgm = ir.gen_segm_expr(DS, src1) src2_sgm = ir.gen_segm_expr(ES, src2) else: src1_sgm = src1 src2_sgm = src2 offset = m2_expr.ExprInt(size / 8, src1.size) e, _ = l_cmp(ir, instr, ir.ExprMem(src1_sgm, size), ir.ExprMem(src2_sgm, size)) e0 = [] e0.append(m2_expr.ExprAff(src1, src1 + offset)) e0.append(m2_expr.ExprAff(src2, src2 + offset)) e0.append(m2_expr.ExprAff(ir.IRDst, loc_next_expr)) e0 = IRBlock(loc_df_0, [AssignBlock(e0, instr)]) e1 = [] e1.append(m2_expr.ExprAff(src1, src1 - offset)) e1.append(m2_expr.ExprAff(src2, src2 - offset)) e1.append(m2_expr.ExprAff(ir.IRDst, loc_next_expr)) e1 = IRBlock(loc_df_1, [AssignBlock(e1, instr)]) e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(df, loc_df_1_expr, loc_df_0_expr))) return e, [e0, e1]
def cmpunordpd(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def cmpunordps(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def cmpunordsd(
ir, instr, dst, src)
def vec_op_clip_instr(ir, instr, dst, src): if op == '-': result = dst[:size] - src[:size] else: result = m2_expr.ExprOp(op, dst[:size], src[:size]) if callback is not None: result = callback(result) return [m2_expr.ExprAff(dst[:size], result)], []
def cmpunordss(
ir, instr, dst, src)
def vec_op_clip_instr(ir, instr, dst, src): if op == '-': result = dst[:size] - src[:size] else: result = m2_expr.ExprOp(op, dst[:size], src[:size]) if callback is not None: result = callback(result) return [m2_expr.ExprAff(dst[:size], result)], []
def comisd(
_, instr, dst, src)
def comisd(_, instr, dst, src): # TODO unordered float e = [] dst = m2_expr.ExprOp('sint_to_fp64', dst[:64]) src = m2_expr.ExprOp('sint_to_fp64', src[:64]) e.append(m2_expr.ExprAff(cf, m2_expr.ExprOp('fcom_c0', dst, src))) e.append(m2_expr.ExprAff(pf, m2_expr.ExprOp('fcom_c2', dst, src))) e.append(m2_expr.ExprAff(zf, m2_expr.ExprOp('fcom_c3', dst, src))) e.append(m2_expr.ExprAff(of, m2_expr.ExprInt(0, 1))) e.append(m2_expr.ExprAff(nf, m2_expr.ExprInt(0, 1))) e.append(m2_expr.ExprAff(af, m2_expr.ExprInt(0, 1))) e += set_float_cs_eip(instr) return e, []
def comiss(
_, instr, dst, src)
def comiss(_, instr, dst, src): # TODO unordered float e = [] dst = m2_expr.ExprOp('sint_to_fp32', dst[:32]) src = m2_expr.ExprOp('sint_to_fp32', src[:32]) e.append(m2_expr.ExprAff(cf, m2_expr.ExprOp('fcom_c0', dst, src))) e.append(m2_expr.ExprAff(pf, m2_expr.ExprOp('fcom_c2', dst, src))) e.append(m2_expr.ExprAff(zf, m2_expr.ExprOp('fcom_c3', dst, src))) e.append(m2_expr.ExprAff(of, m2_expr.ExprInt(0, 1))) e.append(m2_expr.ExprAff(nf, m2_expr.ExprInt(0, 1))) e.append(m2_expr.ExprAff(af, m2_expr.ExprInt(0, 1))) e += set_float_cs_eip(instr) return e, []
def compose_eflag(
s=32)
def compose_eflag(s=32): args = [] args = [cf, m2_expr.ExprInt(1, 1), pf, m2_expr.ExprInt(0, 1), af, m2_expr.ExprInt(0, 1), zf, nf, tf, i_f, df, of, iopl] if s == 32: args += [nt, m2_expr.ExprInt(0, 1), rf, vm, ac, vif, vip, i_d] elif s == 16: args += [nt, m2_expr.ExprInt(0, 1)] else: raise ValueError('unk size') if s == 32: args.append(m2_expr.ExprInt(0, 10)) return m2_expr.ExprCompose(*args)
def cpuid(
_, instr)
def cpuid(_, instr): e = [] e.append( m2_expr.ExprAff(mRAX[instr.mode], m2_expr.ExprOp('x86_cpuid', mRAX[instr.mode], m2_expr.ExprInt(0, instr.mode)))) e.append( m2_expr.ExprAff(mRBX[instr.mode], m2_expr.ExprOp('x86_cpuid', mRAX[instr.mode], m2_expr.ExprInt(1, instr.mode)))) e.append( m2_expr.ExprAff(mRCX[instr.mode], m2_expr.ExprOp('x86_cpuid', mRAX[instr.mode], m2_expr.ExprInt(2, instr.mode)))) e.append( m2_expr.ExprAff(mRDX[instr.mode], m2_expr.ExprOp('x86_cpuid', mRAX[instr.mode], m2_expr.ExprInt(3, instr.mode)))) return e, []
def cqo(
_, instr)
def cqo(_, instr): # Only in 64 bit e = [] tempRAX = mRAX[instr.mode][:64] tempRDX = mRDX[instr.mode][:64] result = tempRAX.signExtend(128) e.append(m2_expr.ExprAff(tempRAX, result[:64])) e.append(m2_expr.ExprAff(tempRDX, result[64:128])) return e, []
def cvtdq2pd(
_, instr, dst, src)
def cvtdq2pd(_, instr, dst, src): e = [] e.append( m2_expr.ExprAff(dst[:64], m2_expr.ExprOp('sint_to_fp64', src[:32]))) e.append( m2_expr.ExprAff(dst[64:128], m2_expr.ExprOp('sint_to_fp64', src[32:64]))) return e, []
def cvtdq2ps(
_, instr, dst, src)
def cvtdq2ps(_, instr, dst, src): e = [] e.append( m2_expr.ExprAff(dst[:32], m2_expr.ExprOp('sint_to_fp32', src[:32]))) e.append( m2_expr.ExprAff(dst[32:64], m2_expr.ExprOp('sint_to_fp32', src[32:64]))) e.append( m2_expr.ExprAff(dst[64:96], m2_expr.ExprOp('sint_to_fp32', src[64:96]))) e.append( m2_expr.ExprAff(dst[96:128], m2_expr.ExprOp('sint_to_fp32', src[96:128]))) return e, []
def cvtpd2dq(
_, instr, dst, src)
def cvtpd2dq(_, instr, dst, src): e = [] e.append( m2_expr.ExprAff(dst[:32], m2_expr.ExprOp('fp_to_sint32', src[:64]))) e.append( m2_expr.ExprAff(dst[32:64], m2_expr.ExprOp('fp_to_sint32', src[64:128]))) e.append(m2_expr.ExprAff(dst[64:128], m2_expr.ExprInt(0, 64))) return e, []
def cvtpd2pi(
_, instr, dst, src)
def cvtpd2pi(_, instr, dst, src): e = [] e.append( m2_expr.ExprAff(dst[:32], m2_expr.ExprOp('fp_to_sint32', src[:64]))) e.append( m2_expr.ExprAff(dst[32:64], m2_expr.ExprOp('fp_to_sint32', src[64:128]))) return e, []
def cvtpd2ps(
_, instr, dst, src)
def cvtpd2ps(_, instr, dst, src): e = [] e.append( m2_expr.ExprAff(dst[:32], m2_expr.ExprOp('fpconvert_fp32', src[:64]))) e.append( m2_expr.ExprAff(dst[32:64], m2_expr.ExprOp('fpconvert_fp32', src[64:128]))) e.append(m2_expr.ExprAff(dst[64:128], m2_expr.ExprInt(0, 64))) return e, []
def cvtpi2pd(
_, instr, dst, src)
def cvtpi2pd(_, instr, dst, src): e = [] e.append( m2_expr.ExprAff(dst[:64], m2_expr.ExprOp('sint_to_fp64', src[:32]))) e.append( m2_expr.ExprAff(dst[64:128], m2_expr.ExprOp('sint_to_fp64', src[32:64]))) return e, []
def cvtpi2ps(
_, instr, dst, src)
def cvtpi2ps(_, instr, dst, src): e = [] e.append( m2_expr.ExprAff(dst[:32], m2_expr.ExprOp('sint_to_fp32', src[:32]))) e.append( m2_expr.ExprAff(dst[32:64], m2_expr.ExprOp('sint_to_fp32', src[32:64]))) return e, []
def cvtps2dq(
_, instr, dst, src)
def cvtps2dq(_, instr, dst, src): e = [] e.append( m2_expr.ExprAff(dst[:32], m2_expr.ExprOp('fp_to_sint32', src[:32]))) e.append( m2_expr.ExprAff(dst[32:64], m2_expr.ExprOp('fp_to_sint32', src[32:64]))) e.append( m2_expr.ExprAff(dst[64:96], m2_expr.ExprOp('fp_to_sint32', src[64:96]))) e.append( m2_expr.ExprAff(dst[96:128], m2_expr.ExprOp('fp_to_sint32', src[96:128]))) return e, []
def cvtps2pd(
_, instr, dst, src)
def cvtps2pd(_, instr, dst, src): e = [] e.append( m2_expr.ExprAff(dst[:64], m2_expr.ExprOp('fpconvert_fp64', src[:32]))) e.append( m2_expr.ExprAff(dst[64:128], m2_expr.ExprOp('fpconvert_fp64', src[32:64]))) return e, []
def cvtps2pi(
_, instr, dst, src)
def cvtps2pi(_, instr, dst, src): e = [] e.append( m2_expr.ExprAff(dst[:32], m2_expr.ExprOp('fp_to_sint32', src[:32]))) e.append( m2_expr.ExprAff(dst[32:64], m2_expr.ExprOp('fp_to_sint32', src[32:64]))) return e, []
def cvtsd2si(
_, instr, dst, src)
def cvtsd2si(_, instr, dst, src): e = [] e.append( m2_expr.ExprAff(dst[:32], m2_expr.ExprOp('fp_to_sint32', src[:64]))) return e, []
def cvtsd2ss(
_, instr, dst, src)
def cvtsd2ss(_, instr, dst, src): e = [] e.append( m2_expr.ExprAff(dst[:32], m2_expr.ExprOp('fpconvert_fp32', src[:64]))) return e, []
def cvtsi2sd(
_, instr, dst, src)
def cvtsi2sd(_, instr, dst, src): e = [] e.append( m2_expr.ExprAff(dst[:64], m2_expr.ExprOp('sint_to_fp64', src[:32]))) return e, []
def cvtsi2ss(
_, instr, dst, src)
def cvtsi2ss(_, instr, dst, src): e = [] e.append( m2_expr.ExprAff(dst[:32], m2_expr.ExprOp('sint_to_fp32', src[:32]))) return e, []
def cvtss2sd(
_, instr, dst, src)
def cvtss2sd(_, instr, dst, src): e = [] e.append( m2_expr.ExprAff(dst[:64], m2_expr.ExprOp('fpconvert_fp64', src[:32]))) return e, []
def cvtss2si(
_, instr, dst, src)
def cvtss2si(_, instr, dst, src): e = [] e.append( m2_expr.ExprAff(dst[:32], m2_expr.ExprOp('fp_to_sint32', src[:32]))) return e, []
def cvttpd2dq(
_, instr, dst, src)
def cvttpd2dq(_, instr, dst, src): e = _cvtt_tpl(dst, src, [0, 1], double=True) e.append(m2_expr.ExprAff(dst[64:128], m2_expr.ExprInt(0, 64))) return e, []
def cvttpd2pi(
_, instr, dst, src)
def cvttpd2pi(_, instr, dst, src): return _cvtt_tpl(dst, src, [0, 1], double=True), []
def cvttps2dq(
_, instr, dst, src)
def cvttps2dq(_, instr, dst, src): return _cvtt_tpl(dst, src, [0, 1, 2, 3], double=False), []
def cvttps2pi(
_, instr, dst, src)
def cvttps2pi(_, instr, dst, src): return _cvtt_tpl(dst, src, [0, 1], double=False), []
def cvttsd2si(
_, instr, dst, src)
def cvttsd2si(_, instr, dst, src): return _cvtt_tpl(dst, src, [0], double=True), []
def cvttss2si(
_, instr, dst, src)
def cvttss2si(_, instr, dst, src): return _cvtt_tpl(dst, src, [0], double=False), []
def cwd(
_, instr)
def cwd(_, instr): # Only in 16 bit e = [] tempAX = mRAX[instr.mode][:16] tempDX = mRDX[instr.mode][:16] result = tempAX.signExtend(32) e.append(m2_expr.ExprAff(tempAX, result[:16])) e.append(m2_expr.ExprAff(tempDX, result[16:32])) return e, []
def cwde(
_, instr)
def cwde(_, instr): # Only in 32/64 bit e = [] tempAX = mRAX[instr.v_opmode()][:16] tempEAX = mRAX[instr.v_opmode()][:32] e.append(m2_expr.ExprAff(tempEAX, tempAX.signExtend(32))) return e, []
def daa(
_, instr)
def daa(_, instr): e = [] r_al = mRAX[instr.mode][:8] cond1 = m2_expr.expr_is_unsigned_greater(r_al[:4], m2_expr.ExprInt(0x9, 4)) | af e.append(m2_expr.ExprAff(af, cond1)) cond2 = m2_expr.expr_is_unsigned_greater(m2_expr.ExprInt(6, 8), r_al) cond3 = m2_expr.expr_is_unsigned_greater(r_al, m2_expr.ExprInt(0x99, 8)) | cf cf_c1 = m2_expr.ExprCond(cond1, cf | (cond2), m2_expr.ExprInt(0, 1)) new_cf = m2_expr.ExprCond(cond3, m2_expr.ExprInt(1, 1), m2_expr.ExprInt(0, 1)) e.append(m2_expr.ExprAff(cf, new_cf)) al_c1 = m2_expr.ExprCond(cond1, r_al + m2_expr.ExprInt(6, 8), r_al) new_al = m2_expr.ExprCond(cond3, al_c1 + m2_expr.ExprInt(0x60, 8), al_c1) e.append(m2_expr.ExprAff(r_al, new_al)) e += update_flag_znp(new_al) return e, []
def das(
_, instr)
def das(_, instr): e = [] r_al = mRAX[instr.mode][:8] cond1 = m2_expr.expr_is_unsigned_greater(r_al[:4], m2_expr.ExprInt(0x9, 4)) | af e.append(m2_expr.ExprAff(af, cond1)) cond2 = m2_expr.expr_is_unsigned_greater(m2_expr.ExprInt(6, 8), r_al) cond3 = m2_expr.expr_is_unsigned_greater(r_al, m2_expr.ExprInt(0x99, 8)) | cf cf_c1 = m2_expr.ExprCond(cond1, cf | (cond2), m2_expr.ExprInt(0, 1)) new_cf = m2_expr.ExprCond(cond3, m2_expr.ExprInt(1, 1), cf_c1) e.append(m2_expr.ExprAff(cf, new_cf)) al_c1 = m2_expr.ExprCond(cond1, r_al - m2_expr.ExprInt(6, 8), r_al) new_al = m2_expr.ExprCond(cond3, al_c1 - m2_expr.ExprInt(0x60, 8), al_c1) e.append(m2_expr.ExprAff(r_al, new_al)) e += update_flag_znp(new_al) return e, []
def dec(
_, instr, dst)
def dec(_, instr, dst): e = [] src = m2_expr.ExprInt(1, dst.size) arg1, arg2 = dst, src result = dst - src e += update_flag_arith_sub_znp(arg1, arg2) e += update_flag_af(arg1, arg2, result) e += update_flag_sub_of(arg1, arg2, result) e.append(m2_expr.ExprAff(dst, result)) return e, []
def div(
ir, instr, src1)
def div(ir, instr, src1): e = [] size = src1.size if size == 8: src2 = mRAX[instr.mode][:16] elif size in [16, 32, 64]: s1, s2 = mRDX[size], mRAX[size] src2 = m2_expr.ExprCompose(s2, s1) else: raise ValueError('div arg not impl', src1) c_d = m2_expr.ExprOp('udiv', src2, src1.zeroExtend(src2.size)) c_r = m2_expr.ExprOp('umod', src2, src1.zeroExtend(src2.size)) # if 8 bit div, only ax is affected if size == 8: e.append(m2_expr.ExprAff(src2, m2_expr.ExprCompose(c_d[:8], c_r[:8]))) else: e.append(m2_expr.ExprAff(s1, c_r[:size])) e.append(m2_expr.ExprAff(s2, c_d[:size])) loc_div, loc_div_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) loc_except, loc_except_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) loc_next = ir.get_next_loc_key(instr) loc_next_expr = m2_expr.ExprLoc(loc_next, ir.IRDst.size) do_div = [] do_div += e do_div.append(m2_expr.ExprAff(ir.IRDst, loc_next_expr)) blk_div = IRBlock(loc_div, [AssignBlock(do_div, instr)]) do_except = [] do_except.append(m2_expr.ExprAff(exception_flags, m2_expr.ExprInt( EXCEPT_DIV_BY_ZERO, exception_flags.size))) do_except.append(m2_expr.ExprAff(ir.IRDst, loc_next_expr)) blk_except = IRBlock(loc_except, [AssignBlock(do_except, instr)]) e = [] e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(src1, loc_div_expr, loc_except_expr))) return e, [blk_div, blk_except]
def divpd(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def divps(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def divsd(
ir, instr, dst, src)
def vec_op_clip_instr(ir, instr, dst, src): if op == '-': result = dst[:size] - src[:size] else: result = m2_expr.ExprOp(op, dst[:size], src[:size]) if callback is not None: result = callback(result) return [m2_expr.ExprAff(dst[:size], result)], []
def divss(
ir, instr, dst, src)
def vec_op_clip_instr(ir, instr, dst, src): if op == '-': result = dst[:size] - src[:size] else: result = m2_expr.ExprOp(op, dst[:size], src[:size]) if callback is not None: result = callback(result) return [m2_expr.ExprAff(dst[:size], result)], []
def emms(
ir, instr)
def emms(ir, instr): # Implemented as a NOP return [], []
def enter(
ir, instr, src1, src2)
def enter(ir, instr, src1, src2): size, admode = instr.v_opmode(), instr.v_admode() myesp = mRSP[instr.mode][:size] myebp = mRBP[instr.mode][:size] src1 = src1.zeroExtend(size) e = [] esp_tmp = myesp - m2_expr.ExprInt(size / 8, size) e.append(m2_expr.ExprAff(ir.ExprMem(esp_tmp, size=size), myebp)) e.append(m2_expr.ExprAff(myebp, esp_tmp)) e.append(m2_expr.ExprAff(myesp, myesp - (src1 + m2_expr.ExprInt(size / 8, size)))) return e, []
def expraddr(
mode, ptr)
Returns memory address pointer with size according to current @mode
def expraddr(mode, ptr): """Returns memory address pointer with size according to current @mode""" return ptr.zeroExtend(mode2addrsize(mode))
def f2xm1(
_, instr)
def f2xm1(_, instr): e = [] e.append(m2_expr.ExprAff(float_st0, m2_expr.ExprOp('f2xm1', float_st0))) e += set_float_cs_eip(instr) return e, []
def fabs(
_, instr)
def fabs(_, instr): e = [] e.append(m2_expr.ExprAff(float_st0, m2_expr.ExprOp('fabs', float_st0))) e += set_float_cs_eip(instr) return e, []
def fadd(
_, instr, dst, src=None)
def fadd(_, instr, dst, src=None): dst, src = float_implicit_st0(dst, src) e = [] src = mem2double(instr, src) e.append(m2_expr.ExprAff(dst, m2_expr.ExprOp('fadd', dst, src))) e += set_float_cs_eip(instr) return e, []
def faddp(
_, instr, dst, src=None)
def faddp(_, instr, dst, src=None): dst, src = float_implicit_st0(dst, src) e = [] src = mem2double(instr, src) e.append(m2_expr.ExprAff(float_prev(dst), m2_expr.ExprOp('fadd', dst, src))) e += set_float_cs_eip(instr) e += float_pop(dst) return e, []
def fchs(
_, instr)
def fchs(_, instr): e = [] e.append(m2_expr.ExprAff(float_st0, m2_expr.ExprOp('fchs', float_st0))) e += set_float_cs_eip(instr) return e, []
def fclex(
_, instr)
def fclex(_, instr): # XXX TODO return [], []
def fcmovb(
ir, instr, arg1, arg2)
def fcmovb(ir, instr, arg1, arg2): return gen_fcmov(ir, instr, cf, arg1, arg2, True)
def fcmovbe(
ir, instr, arg1, arg2)
def fcmovbe(ir, instr, arg1, arg2): return gen_fcmov(ir, instr, cf | zf, arg1, arg2, True)
def fcmove(
ir, instr, arg1, arg2)
def fcmove(ir, instr, arg1, arg2): return gen_fcmov(ir, instr, zf, arg1, arg2, True)
def fcmovnb(
ir, instr, arg1, arg2)
def fcmovnb(ir, instr, arg1, arg2): return gen_fcmov(ir, instr, cf, arg1, arg2, False)
def fcmovnbe(
ir, instr, arg1, arg2)
def fcmovnbe(ir, instr, arg1, arg2): return gen_fcmov(ir, instr, cf | zf, arg1, arg2, False)
def fcmovne(
ir, instr, arg1, arg2)
def fcmovne(ir, instr, arg1, arg2): return gen_fcmov(ir, instr, zf, arg1, arg2, False)
def fcmovnu(
ir, instr, arg1, arg2)
def fcmovnu(ir, instr, arg1, arg2): return gen_fcmov(ir, instr, pf, arg1, arg2, False)
def fcmovu(
ir, instr, arg1, arg2)
def fcmovu(ir, instr, arg1, arg2): return gen_fcmov(ir, instr, pf, arg1, arg2, True)
def fcom(
_, instr, dst=None, src=None)
def fcom(_, instr, dst=None, src=None): if dst is None and src is None: dst, src = float_st0, float_st1 elif src is None: src = mem2double(instr, dst) dst = float_st0 e = [] e.append(m2_expr.ExprAff(float_c0, m2_expr.ExprOp('fcom_c0', dst, src))) e.append(m2_expr.ExprAff(float_c1, m2_expr.ExprOp('fcom_c1', dst, src))) e.append(m2_expr.ExprAff(float_c2, m2_expr.ExprOp('fcom_c2', dst, src))) e.append(m2_expr.ExprAff(float_c3, m2_expr.ExprOp('fcom_c3', dst, src))) e += set_float_cs_eip(instr) return e, []
def fcomi(
_, instr, dst=None, src=None)
def fcomi(_, instr, dst=None, src=None): # TODO unordered float if dst is None and src is None: dst, src = float_st0, float_st1 elif src is None: src = dst dst = float_st0 e = [] e.append(m2_expr.ExprAff(cf, m2_expr.ExprOp('fcom_c0', dst, src))) e.append(m2_expr.ExprAff(pf, m2_expr.ExprOp('fcom_c2', dst, src))) e.append(m2_expr.ExprAff(zf, m2_expr.ExprOp('fcom_c3', dst, src))) e.append(m2_expr.ExprAff(of, m2_expr.ExprInt(0, 1))) e.append(m2_expr.ExprAff(nf, m2_expr.ExprInt(0, 1))) e.append(m2_expr.ExprAff(af, m2_expr.ExprInt(0, 1))) e += set_float_cs_eip(instr) return e, []
def fcomip(
ir, instr, dst=None, src=None)
def fcomip(ir, instr, dst=None, src=None): e, extra = fcomi(ir, instr, dst, src) e += float_pop() e += set_float_cs_eip(instr) return e, extra
def fcomp(
ir, instr, dst=None, src=None)
def fcomp(ir, instr, dst=None, src=None): e, extra = fcom(ir, instr, dst, src) e += float_pop() e += set_float_cs_eip(instr) return e, extra
def fcompp(
ir, instr, dst=None, src=None)
def fcompp(ir, instr, dst=None, src=None): e, extra = fcom(ir, instr, dst, src) e += float_pop(popcount=2) e += set_float_cs_eip(instr) return e, extra
def fcos(
_, instr)
def fcos(_, instr): e = [] e.append(m2_expr.ExprAff(float_st0, m2_expr.ExprOp('fcos', float_st0))) e += set_float_cs_eip(instr) return e, []
def fdiv(
_, instr, dst, src=None)
def fdiv(_, instr, dst, src=None): dst, src = float_implicit_st0(dst, src) e = [] src = mem2double(instr, src) e.append(m2_expr.ExprAff(dst, m2_expr.ExprOp('fdiv', dst, src))) e += set_float_cs_eip(instr) return e, []
def fdivp(
_, instr, dst, src=None)
def fdivp(_, instr, dst, src=None): # Invalid emulation dst, src = float_implicit_st0(dst, src) e = [] src = mem2double(instr, src) e.append(m2_expr.ExprAff(float_prev(dst), m2_expr.ExprOp('fdiv', dst, src))) e += set_float_cs_eip(instr) e += float_pop(dst) return e, []
def fdivr(
_, instr, dst, src=None)
def fdivr(_, instr, dst, src=None): dst, src = float_implicit_st0(dst, src) e = [] src = mem2double(instr, src) e.append(m2_expr.ExprAff(dst, m2_expr.ExprOp('fdiv', src, dst))) e += set_float_cs_eip(instr) return e, []
def fdivrp(
_, instr, dst, src=None)
def fdivrp(_, instr, dst, src=None): dst, src = float_implicit_st0(dst, src) e = [] src = mem2double(instr, src) e.append(m2_expr.ExprAff(float_prev(dst), m2_expr.ExprOp('fdiv', src, dst))) e += set_float_cs_eip(instr) e += float_pop(dst) return e, []
def fiadd(
_, instr, dst, src=None)
def fiadd(_, instr, dst, src=None): dst, src = float_implicit_st0(dst, src) e = [] src = mem2double(instr, src) e.append(m2_expr.ExprAff(dst, m2_expr.ExprOp('fiadd', dst, src))) e += set_float_cs_eip(instr) return e, []
def ficom(
_, instr, dst, src=None)
def ficom(_, instr, dst, src=None): dst, src = float_implicit_st0(dst, src) e = [] e.append(m2_expr.ExprAff(float_c0, m2_expr.ExprOp('fcom_c0', dst, src.zeroExtend(dst.size)))) e.append(m2_expr.ExprAff(float_c1, m2_expr.ExprOp('fcom_c1', dst, src.zeroExtend(dst.size)))) e.append(m2_expr.ExprAff(float_c2, m2_expr.ExprOp('fcom_c2', dst, src.zeroExtend(dst.size)))) e.append(m2_expr.ExprAff(float_c3, m2_expr.ExprOp('fcom_c3', dst, src.zeroExtend(dst.size)))) e += set_float_cs_eip(instr) return e, []
def ficomp(
ir, instr, dst, src=None)
def ficomp(ir, instr, dst, src=None): e, extra = ficom(ir, instr, dst, src) e += float_pop() e += set_float_cs_eip(instr) return e, extra
def fidiv(
_, instr, dst, src=None)
def fidiv(_, instr, dst, src=None): dst, src = float_implicit_st0(dst, src) e = [] src = mem2double(instr, src) e.append(m2_expr.ExprAff(dst, m2_expr.ExprOp('fidiv', dst, src))) e += set_float_cs_eip(instr) return e, []
def fidivr(
_, instr, dst, src=None)
def fidivr(_, instr, dst, src=None): dst, src = float_implicit_st0(dst, src) e = [] src = mem2double(instr, src) e.append(m2_expr.ExprAff(dst, m2_expr.ExprOp('fidiv', src, dst))) e += set_float_cs_eip(instr) return e, []
def fild(
ir, instr, src)
def fild(ir, instr, src): # XXXXX src = m2_expr.ExprOp('sint_to_fp64', src) e = [] e += set_float_cs_eip(instr) e_fld, extra = fld(ir, instr, src) e += e_fld return e, extra
def fimul(
_, instr, dst, src=None)
def fimul(_, instr, dst, src=None): dst, src = float_implicit_st0(dst, src) e = [] src = mem2double(instr, src) e.append(m2_expr.ExprAff(dst, m2_expr.ExprOp('fimul', dst, src))) e += set_float_cs_eip(instr) return e, []
def fist(
_, instr, dst)
def fist(_, instr, dst): e = [] e.append(m2_expr.ExprAff(dst, m2_expr.ExprOp('fp_to_sint%d' % dst.size, float_st0))) e += set_float_cs_eip(instr) return e, []
def fistp(
ir, instr, dst)
def fistp(ir, instr, dst): e, extra = fist(ir, instr, dst) e += float_pop(dst) return e, extra
def fisttp(
_, instr, dst)
def fisttp(_, instr, dst): e = [] e.append(m2_expr.ExprAff( dst, m2_expr.ExprOp('fp_to_sint%d' % dst.size, m2_expr.ExprOp('fpround_towardszero', float_st0) ))) e += set_float_cs_eip(instr) e += float_pop(dst) return e, []
def fisub(
_, instr, dst, src=None)
def fisub(_, instr, dst, src=None): dst, src = float_implicit_st0(dst, src) e = [] src = mem2double(instr, src) e.append(m2_expr.ExprAff(dst, m2_expr.ExprOp('fisub', dst, src))) e += set_float_cs_eip(instr) return e, []
def fisubr(
_, instr, dst, src=None)
def fisubr(_, instr, dst, src=None): dst, src = float_implicit_st0(dst, src) e = [] src = mem2double(instr, src) e.append(m2_expr.ExprAff(dst, m2_expr.ExprOp('fisub', src, dst))) e += set_float_cs_eip(instr) return e, []
def fix_mem_args_size(
instr, *args)
def fix_mem_args_size(instr, *args): out = [] for arg in args: if not arg.is_mem(): out.append(arg) continue ptr = arg.arg size = arg.size if ptr.is_op('segm'): ptr = m2_expr.ExprOp( 'segm', ptr.args[0], expraddr(instr.mode, ptr.args[1])) else: ptr = expraddr(instr.mode, ptr) out.append(m2_expr.ExprMem(ptr, size)) return out
def fld(
_, instr, src)
def fld(_, instr, src): if src.size == 32: src = m2_expr.ExprOp("fpconvert_fp64", src) e = [] e.append(m2_expr.ExprAff(float_st7, float_st6)) e.append(m2_expr.ExprAff(float_st6, float_st5)) e.append(m2_expr.ExprAff(float_st5, float_st4)) e.append(m2_expr.ExprAff(float_st4, float_st3)) e.append(m2_expr.ExprAff(float_st3, float_st2)) e.append(m2_expr.ExprAff(float_st2, float_st1)) e.append(m2_expr.ExprAff(float_st1, float_st0)) e.append(m2_expr.ExprAff(float_st0, src)) e.append( m2_expr.ExprAff(float_stack_ptr, float_stack_ptr + m2_expr.ExprInt(1, 3))) e += set_float_cs_eip(instr) return e, []
def fld1(
ir, instr)
def fld1(ir, instr): return fld(ir, instr, m2_expr.ExprOp('sint_to_fp64', m2_expr.ExprInt(1, 32)))
def fldcw(
_, instr, src)
def fldcw(_, instr, src): e = [] e.append(m2_expr.ExprAff(float_control, src)) return e, []
def fldenv(
ir, instr, src)
def fldenv(ir, instr, src): e = [] # Inspired from fnstenv (same TODOs / issues) s = instr.mode # The behaviour in 64bit is identical to 32 bit # This will truncate addresses size = min(32, s) # Float control ad = ir.ExprMem(src.arg, size=16) e.append(m2_expr.ExprAff(float_control, ad)) # Status word ad = ir.ExprMem(src.arg + m2_expr.ExprInt(size / 8 * 1, size=src.arg.size), size=16) e += [m2_expr.ExprAff(x, y) for x, y in ((float_c0, ad[8:9]), (float_c1, ad[9:10]), (float_c2, ad[10:11]), (float_stack_ptr, ad[11:14]), (float_c3, ad[14:15])) ] # EIP, CS, Address, DS for offset, target in ((3, float_eip[:size]), (4, float_cs), (5, float_address[:size]), (6, float_ds)): ad = ir.ExprMem(src.arg + m2_expr.ExprInt(size / 8 * offset, size=src.arg.size), size=target.size) e.append(m2_expr.ExprAff(target, ad)) return e, []
def fldl2e(
ir, instr)
def fldl2e(ir, instr): x = struct.pack('d', 1 / math.log(2)) x = struct.unpack('Q', x)[0] return fld(ir, instr, m2_expr.ExprOp('mem_64_to_double', m2_expr.ExprInt(x, 64)))
def fldl2t(
ir, instr)
def fldl2t(ir, instr): value_f = math.log(10) / math.log(2) value = struct.unpack('I', struct.pack('f', value_f))[0] return fld(ir, instr, m2_expr.ExprOp('sint_to_fp64', m2_expr.ExprInt(value, 32)))
def fldlg2(
ir, instr)
def fldlg2(ir, instr): x = struct.pack('d', math.log10(2)) x = struct.unpack('Q', x)[0] return fld(ir, instr, m2_expr.ExprOp('mem_64_to_double', m2_expr.ExprInt(x, 64)))
def fldln2(
ir, instr)
def fldln2(ir, instr): value_f = math.log(2) value = struct.unpack('Q', struct.pack('d', value_f))[0] return fld(ir, instr, m2_expr.ExprOp('mem_64_to_double', m2_expr.ExprInt(value, 64)))
def fldpi(
ir, instr)
def fldpi(ir, instr): value_f = math.pi value = struct.unpack('I', struct.pack('f', value_f))[0] return fld(ir, instr, m2_expr.ExprOp('sint_to_fp64', m2_expr.ExprInt(value, 32)))
def fldz(
ir, instr)
def fldz(ir, instr): return fld(ir, instr, m2_expr.ExprOp('sint_to_fp64', m2_expr.ExprInt(0, 32)))
def float_implicit_st0(
arg1, arg2)
Generate full float operators if one argument is implicit (float_st0)
def float_implicit_st0(arg1, arg2): """ Generate full float operators if one argument is implicit (float_st0) """ if arg2 is None: arg2 = arg1 arg1 = float_st0 return arg1, arg2
def float_pop(
avoid_flt=None, popcount=1)
Generate floatpop semantic (@popcount times), avoiding the avoid_flt@ float @avoid_flt: float avoided in the generated semantic @popcount: pop count
def float_pop(avoid_flt=None, popcount=1): """ Generate floatpop semantic (@popcount times), avoiding the avoid_flt@ float @avoid_flt: float avoided in the generated semantic @popcount: pop count """ avoid_flt = float_prev(avoid_flt, popcount) e = [] for i in xrange(8 - popcount): if avoid_flt != float_list[i]: e.append(m2_expr.ExprAff(float_list[i], float_list[i + popcount])) fill_value = m2_expr.ExprOp("sint_to_fp64", m2_expr.ExprInt(0, float_list[i].size)) for i in xrange(8 - popcount, 8): e.append(m2_expr.ExprAff(float_list[i], fill_value)) e.append( m2_expr.ExprAff(float_stack_ptr, float_stack_ptr - m2_expr.ExprInt(popcount, 3))) return e
def float_prev(
flt, popcount=1)
def float_prev(flt, popcount=1): if not flt in float_list: return None i = float_list.index(flt) if i < popcount: # Drop value (ex: FSTP ST(0)) return None flt = float_list[i - popcount] return flt
def fmul(
_, instr, dst, src=None)
def fmul(_, instr, dst, src=None): dst, src = float_implicit_st0(dst, src) e = [] src = mem2double(instr, src) e.append(m2_expr.ExprAff(dst, m2_expr.ExprOp('fmul', dst, src))) e += set_float_cs_eip(instr) return e, []
def fmulp(
_, instr, dst, src=None)
def fmulp(_, instr, dst, src=None): # Invalid emulation dst, src = float_implicit_st0(dst, src) e = [] src = mem2double(instr, src) e.append(m2_expr.ExprAff(float_prev(dst), m2_expr.ExprOp('fmul', dst, src))) e += set_float_cs_eip(instr) e += float_pop(dst) return e, []
def fnclex(
_, instr)
def fnclex(_, instr): # XXX TODO return [], []
def fninit(
_, instr)
def fninit(_, instr): e = [] e += set_float_cs_eip(instr) return e, []
def fnstcw(
_, instr, dst)
def fnstcw(_, instr, dst): e = [] e.append(m2_expr.ExprAff(dst, float_control)) return e, []
def fnstenv(
ir, instr, dst)
def fnstenv(ir, instr, dst): e = [] # XXX TODO tag word, ... status_word = m2_expr.ExprCompose(m2_expr.ExprInt(0, 8), float_c0, float_c1, float_c2, float_stack_ptr, float_c3, m2_expr.ExprInt(0, 1)) s = instr.mode # The behaviour in 64bit is identical to 32 bit # This will truncate addresses size = min(32, s) ad = ir.ExprMem(dst.arg, size=16) e.append(m2_expr.ExprAff(ad, float_control)) ad = ir.ExprMem(dst.arg + m2_expr.ExprInt(size / 8 * 1, dst.arg.size), size=16) e.append(m2_expr.ExprAff(ad, status_word)) ad = ir.ExprMem(dst.arg + m2_expr.ExprInt(size / 8 * 3, dst.arg.size), size=size) e.append(m2_expr.ExprAff(ad, float_eip[:size])) ad = ir.ExprMem(dst.arg + m2_expr.ExprInt(size / 8 * 4, dst.arg.size), size=16) e.append(m2_expr.ExprAff(ad, float_cs)) ad = ir.ExprMem(dst.arg + m2_expr.ExprInt(size / 8 * 5, dst.arg.size), size=size) e.append(m2_expr.ExprAff(ad, float_address[:size])) ad = ir.ExprMem(dst.arg + m2_expr.ExprInt(size / 8 * 6, dst.arg.size), size=16) e.append(m2_expr.ExprAff(ad, float_ds)) return e, []
def fnstsw(
_, instr, dst)
def fnstsw(_, instr, dst): args = [ # Exceptions -> 0 m2_expr.ExprInt(0, 8), float_c0, float_c1, float_c2, float_stack_ptr, float_c3, # B: FPU is not busy -> 0 m2_expr.ExprInt(0, 1)] e = [m2_expr.ExprAff(dst, m2_expr.ExprCompose(*args))] return e, []
def fpatan(
_, instr)
def fpatan(_, instr): e = [] a = float_st1 e.append(m2_expr.ExprAff(float_prev(a), m2_expr.ExprOp('fpatan', float_st0, float_st1))) e += set_float_cs_eip(instr) e += float_pop(a) return e, []
def fprem(
_, instr)
def fprem(_, instr): e = [] e.append( m2_expr.ExprAff(float_st0, m2_expr.ExprOp('fprem', float_st0, float_st1))) # Remaining bits (ex: used in argument reduction in tan) remain = m2_expr.ExprOp('fprem_lsb', float_st0, float_st1) e += [m2_expr.ExprAff(float_c0, remain[2:3]), m2_expr.ExprAff(float_c3, remain[1:2]), m2_expr.ExprAff(float_c1, remain[0:1]), # Consider the reduction is always completed m2_expr.ExprAff(float_c2, m2_expr.ExprInt(0, 1)), ] e += set_float_cs_eip(instr) return e, []
def fprem1(
_, instr)
def fprem1(_, instr): e = [] e.append( m2_expr.ExprAff(float_st0, m2_expr.ExprOp('fprem1', float_st0, float_st1))) e += set_float_cs_eip(instr) return e, []
def fptan(
_, instr)
def fptan(_, instr): e = [] e.append(m2_expr.ExprAff(float_st7, float_st6)) e.append(m2_expr.ExprAff(float_st6, float_st5)) e.append(m2_expr.ExprAff(float_st5, float_st4)) e.append(m2_expr.ExprAff(float_st4, float_st3)) e.append(m2_expr.ExprAff(float_st3, float_st2)) e.append(m2_expr.ExprAff(float_st2, float_st1)) e.append(m2_expr.ExprAff(float_st1, m2_expr.ExprOp('ftan', float_st0))) e.append(m2_expr.ExprAff(float_st0, m2_expr.ExprOp('sint_to_fp64', m2_expr.ExprInt(1, 32)))) e.append( m2_expr.ExprAff(float_stack_ptr, float_stack_ptr + m2_expr.ExprInt(1, 3))) return e, []
def frndint(
_, instr)
def frndint(_, instr): e = [] e.append(m2_expr.ExprAff(float_st0, m2_expr.ExprOp('frndint', float_st0))) e += set_float_cs_eip(instr) return e, []
def fscale(
_, instr)
def fscale(_, instr): e = [] e.append(m2_expr.ExprAff(float_st0, m2_expr.ExprOp('fscale', float_st0, float_st1))) e += set_float_cs_eip(instr) return e, []
def fsin(
_, instr)
def fsin(_, instr): e = [] e.append(m2_expr.ExprAff(float_st0, m2_expr.ExprOp('fsin', float_st0))) e += set_float_cs_eip(instr) return e, []
def fsincos(
_, instr)
def fsincos(_, instr): e = [] e.append(m2_expr.ExprAff(float_st7, float_st6)) e.append(m2_expr.ExprAff(float_st6, float_st5)) e.append(m2_expr.ExprAff(float_st5, float_st4)) e.append(m2_expr.ExprAff(float_st4, float_st3)) e.append(m2_expr.ExprAff(float_st3, float_st2)) e.append(m2_expr.ExprAff(float_st2, float_st1)) e.append(m2_expr.ExprAff(float_st1, m2_expr.ExprOp('fsin', float_st0))) e.append(m2_expr.ExprAff(float_st0, m2_expr.ExprOp('fcos', float_st0))) e.append( m2_expr.ExprAff(float_stack_ptr, float_stack_ptr + m2_expr.ExprInt(1, 3))) return e, []
def fsqrt(
_, instr)
def fsqrt(_, instr): e = [] e.append(m2_expr.ExprAff(float_st0, m2_expr.ExprOp('fsqrt', float_st0))) e += set_float_cs_eip(instr) return e, []
def fst(
_, instr, dst)
def fst(_, instr, dst): e = [] if isinstance(dst, m2_expr.ExprMem) and dst.size > 64: raise NotImplementedError('convert to 80bits') src = float_st0 if dst.size == 32: src = m2_expr.ExprOp("fpconvert_fp32", src) e.append(m2_expr.ExprAff(dst, src)) e += set_float_cs_eip(instr) return e, []
def fstp(
ir, instr, dst)
def fstp(ir, instr, dst): e = [] if isinstance(dst, m2_expr.ExprMem) and dst.size > 64: raise NotImplementedError('convert to 80bits') if isinstance(dst, m2_expr.ExprMem): src = float_st0 if dst.size == 32: src = m2_expr.ExprOp("fpconvert_fp32", src) e.append(m2_expr.ExprAff(dst, src)) else: src = float_st0 if float_list.index(dst) > 1: # a = st0 -> st0 is dropped # a = st1 -> st0 = st0, useless e.append(m2_expr.ExprAff(float_prev(dst), src)) e += set_float_cs_eip(instr) e += float_pop(dst) return e, []
def fsub(
_, instr, dst, src=None)
def fsub(_, instr, dst, src=None): dst, src = float_implicit_st0(dst, src) e = [] src = mem2double(instr, src) e.append(m2_expr.ExprAff(dst, m2_expr.ExprOp('fsub', dst, src))) e += set_float_cs_eip(instr) return e, []
def fsubp(
_, instr, dst, src=None)
def fsubp(_, instr, dst, src=None): dst, src = float_implicit_st0(dst, src) e = [] src = mem2double(instr, src) e.append(m2_expr.ExprAff(float_prev(dst), m2_expr.ExprOp('fsub', dst, src))) e += set_float_cs_eip(instr) e += float_pop(dst) return e, []
def fsubr(
_, instr, dst, src=None)
def fsubr(_, instr, dst, src=None): dst, src = float_implicit_st0(dst, src) e = [] src = mem2double(instr, src) e.append(m2_expr.ExprAff(dst, m2_expr.ExprOp('fsub', src, dst))) e += set_float_cs_eip(instr) return e, []
def fsubrp(
_, instr, dst, src=None)
def fsubrp(_, instr, dst, src=None): dst, src = float_implicit_st0(dst, src) e = [] src = mem2double(instr, src) e.append(m2_expr.ExprAff(float_prev(dst), m2_expr.ExprOp('fsub', src, dst))) e += set_float_cs_eip(instr) e += float_pop(dst) return e, []
def ftan(
_, instr, src)
def ftan(_, instr, src): e = [] src = mem2double(instr, src) e.append(m2_expr.ExprAff(float_st0, m2_expr.ExprOp('ftan', src))) e += set_float_cs_eip(instr) return e, []
def ftst(
_, instr)
def ftst(_, instr): dst = float_st0 e = [] src = m2_expr.ExprOp('sint_to_fp64', m2_expr.ExprInt(0, 32)) e.append(m2_expr.ExprAff(float_c0, m2_expr.ExprOp('fcom_c0', dst, src))) e.append(m2_expr.ExprAff(float_c1, m2_expr.ExprOp('fcom_c1', dst, src))) e.append(m2_expr.ExprAff(float_c2, m2_expr.ExprOp('fcom_c2', dst, src))) e.append(m2_expr.ExprAff(float_c3, m2_expr.ExprOp('fcom_c3', dst, src))) e += set_float_cs_eip(instr) return e, []
def fucom(
ir, instr, dst=None, src=None)
def fucom(ir, instr, dst=None, src=None): # TODO unordered float return fcom(ir, instr, dst, src)
def fucomi(
ir, instr, dst=None, src=None)
def fucomi(ir, instr, dst=None, src=None): # TODO unordered float return fcomi(ir, instr, dst, src)
def fucomip(
ir, instr, dst=None, src=None)
def fucomip(ir, instr, dst=None, src=None): # TODO unordered float return fcomip(ir, instr, dst, src)
def fucomp(
ir, instr, dst=None, src=None)
def fucomp(ir, instr, dst=None, src=None): # TODO unordered float return fcomp(ir, instr, dst, src)
def fucompp(
ir, instr, dst=None, src=None)
def fucompp(ir, instr, dst=None, src=None): # TODO unordered float return fcompp(ir, instr, dst, src)
def fwait(
_, instr)
def fwait(_, instr): return [], []
def fxam(
_, instr)
def fxam(_, instr): dst = float_st0 e = [] e.append(m2_expr.ExprAff(float_c0, m2_expr.ExprOp('fxam_c0', dst))) e.append(m2_expr.ExprAff(float_c1, m2_expr.ExprOp('fxam_c1', dst))) e.append(m2_expr.ExprAff(float_c2, m2_expr.ExprOp('fxam_c2', dst))) e.append(m2_expr.ExprAff(float_c3, m2_expr.ExprOp('fxam_c3', dst))) e += set_float_cs_eip(instr) return e, []
def fxch(
_, instr, src)
def fxch(_, instr, src): e = [] src = mem2double(instr, src) e.append(m2_expr.ExprAff(float_st0, src)) e.append(m2_expr.ExprAff(src, float_st0)) e += set_float_cs_eip(instr) return e, []
def fyl2x(
_, instr)
def fyl2x(_, instr): e = [] a = float_st1 e.append( m2_expr.ExprAff(float_prev(a), m2_expr.ExprOp('fyl2x', float_st0, float_st1))) e += set_float_cs_eip(instr) e += float_pop(a) return e, []
def gen_cmov(
ir, instr, cond, dst, src, mov_if)
Generate cmov @ir: ir instance @instr: instruction instance @cond: condition @mov_if: invert condition if False
def gen_cmov(ir, instr, cond, dst, src, mov_if): """Generate cmov @ir: ir instance @instr: instruction instance @cond: condition @mov_if: invert condition if False""" loc_do, loc_do_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) loc_skip = ir.get_next_loc_key(instr) loc_skip_expr = m2_expr.ExprLoc(loc_skip, ir.IRDst.size) if mov_if: dstA, dstB = loc_do_expr, loc_skip_expr else: dstA, dstB = loc_skip_expr, loc_do_expr e = [] e_do, extra_irs = mov(ir, instr, dst, src) e_do.append(m2_expr.ExprAff(ir.IRDst, loc_skip_expr)) e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(cond, dstA, dstB))) return e, [IRBlock(loc_do, [AssignBlock(e_do, instr)])]
def gen_fcmov(
ir, instr, cond, arg1, arg2, mov_if)
Generate fcmov @ir: ir instance @instr: instruction instance @cond: condition @mov_if: invert condition if False
def gen_fcmov(ir, instr, cond, arg1, arg2, mov_if): """Generate fcmov @ir: ir instance @instr: instruction instance @cond: condition @mov_if: invert condition if False""" loc_do, loc_do_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) loc_skip = ir.get_next_loc_key(instr) loc_skip_expr = m2_expr.ExprLoc(loc_skip, ir.IRDst.size) if mov_if: dstA, dstB = loc_do_expr, loc_skip_expr else: dstA, dstB = loc_skip_expr, loc_do_expr e = [] e_do, extra_irs = [m2_expr.ExprAff(arg1, arg2)], [] e_do.append(m2_expr.ExprAff(ir.IRDst, loc_skip_expr)) e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(cond, dstA, dstB))) return e, [IRBlock(loc_do, [AssignBlock(e_do, instr)])]
def gen_jcc(
ir, instr, cond, dst, jmp_if)
Macro to generate jcc semantic @ir: ir instance @instr: instruction @cond: condtion of the jcc @dst: the dstination if jcc is taken @jmp_if: jump if/notif cond
def gen_jcc(ir, instr, cond, dst, jmp_if): """ Macro to generate jcc semantic @ir: ir instance @instr: instruction @cond: condtion of the jcc @dst: the dstination if jcc is taken @jmp_if: jump if/notif cond """ e = [] meip = mRIP[ir.IRDst.size] loc_next = ir.get_next_loc_key(instr) loc_next_expr = m2_expr.ExprLoc(loc_next, dst.size) if jmp_if: dstA, dstB = dst, loc_next_expr else: dstA, dstB = loc_next_expr, dst mn_dst = m2_expr.ExprCond(cond, dstA.zeroExtend(ir.IRDst.size), dstB.zeroExtend(ir.IRDst.size)) e.append(m2_expr.ExprAff(meip, mn_dst)) e.append(m2_expr.ExprAff(ir.IRDst, mn_dst)) return e, []
def get_shift(
dst, src)
def get_shift(dst, src): if isinstance(src, m2_expr.ExprInt): src = m2_expr.ExprInt(int(src), dst.size) else: src = src.zeroExtend(dst.size) if dst.size == 64: shift = src & m2_expr.ExprInt(63, src.size) else: shift = src & m2_expr.ExprInt(31, src.size) shift = expr_simp(shift) return shift
def hlt(
_, instr)
def hlt(_, instr): e = [] except_int = EXCEPT_PRIV_INSN e.append(m2_expr.ExprAff(exception_flags, m2_expr.ExprInt(except_int, 32))) return e, []
def icebp(
_, instr)
def icebp(_, instr): e = [] e.append(m2_expr.ExprAff(exception_flags, m2_expr.ExprInt(EXCEPT_SOFT_BP, 32))) return e, []
def idiv(
ir, instr, src1)
def idiv(ir, instr, src1): e = [] size = src1.size if size == 8: src2 = mRAX[instr.mode][:16] elif size in [16, 32, 64]: s1, s2 = mRDX[size], mRAX[size] src2 = m2_expr.ExprCompose(s2, s1) else: raise ValueError('div arg not impl', src1) c_d = m2_expr.ExprOp('idiv', src2, src1.signExtend(src2.size)) c_r = m2_expr.ExprOp('imod', src2, src1.signExtend(src2.size)) # if 8 bit div, only ax is affected if size == 8: e.append(m2_expr.ExprAff(src2, m2_expr.ExprCompose(c_d[:8], c_r[:8]))) else: e.append(m2_expr.ExprAff(s1, c_r[:size])) e.append(m2_expr.ExprAff(s2, c_d[:size])) loc_div, loc_div_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) loc_except, loc_except_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) loc_next = ir.get_next_loc_key(instr) loc_next_expr = m2_expr.ExprLoc(loc_next, ir.IRDst.size) do_div = [] do_div += e do_div.append(m2_expr.ExprAff(ir.IRDst, loc_next_expr)) blk_div = IRBlock(loc_div, [AssignBlock(do_div, instr)]) do_except = [] do_except.append(m2_expr.ExprAff(exception_flags, m2_expr.ExprInt( EXCEPT_DIV_BY_ZERO, exception_flags.size))) do_except.append(m2_expr.ExprAff(ir.IRDst, loc_next_expr)) blk_except = IRBlock(loc_except, [AssignBlock(do_except, instr)]) e = [] e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(src1, loc_div_expr, loc_except_expr))) return e, [blk_div, blk_except]
def imul(
_, instr, src1, src2=None, src3=None)
def imul(_, instr, src1, src2=None, src3=None): e = [] size = src1.size if src2 is None: if size in [16, 32, 64]: result = m2_expr.ExprOp('*', mRAX[size].signExtend(size * 2), src1.signExtend(size * 2)) e.append(m2_expr.ExprAff(mRAX[size], result[:size])) e.append(m2_expr.ExprAff(mRDX[size], result[size:size * 2])) elif size == 8: dst = mRAX[instr.mode][:16] result = m2_expr.ExprOp('*', mRAX[instr.mode][:8].signExtend(16), src1.signExtend(16)) e.append(m2_expr.ExprAff(dst, result)) value = m2_expr.ExprCond(result - result[:size].signExtend(size * 2), m2_expr.ExprInt(1, 1), m2_expr.ExprInt(0, 1)) e.append(m2_expr.ExprAff(cf, value)) value = m2_expr.ExprCond(result - result[:size].signExtend(size * 2), m2_expr.ExprInt(1, 1), m2_expr.ExprInt(0, 1)) e.append(m2_expr.ExprAff(of, value)) else: if src3 is None: src3 = src2 src2 = src1 result = m2_expr.ExprOp('*', src2.signExtend(size * 2), src3.signExtend(size * 2)) e.append(m2_expr.ExprAff(src1, result[:size])) value = m2_expr.ExprCond(result - result[:size].signExtend(size * 2), m2_expr.ExprInt(1, 1), m2_expr.ExprInt(0, 1)) e.append(m2_expr.ExprAff(cf, value)) value = m2_expr.ExprCond(result - result[:size].signExtend(size * 2), m2_expr.ExprInt(1, 1), m2_expr.ExprInt(0, 1)) e.append(m2_expr.ExprAff(of, value)) return e, []
def inc(
_, instr, dst)
def inc(_, instr, dst): e = [] src = m2_expr.ExprInt(1, dst.size) arg1, arg2 = dst, src result = dst + src e += update_flag_arith_add_znp(arg1, arg2) e += update_flag_af(arg1, arg2, result) e += update_flag_add_of(arg1, arg2, result) e.append(m2_expr.ExprAff(dst, result)) return e, []
def ins(
_, instr, size)
def ins(_, instr, size): e = [] e.append(m2_expr.ExprAff(exception_flags, m2_expr.ExprInt(1 << 7, 32))) return e, []
def instr2addrsize(
instr)
Returns the address size for a given @instr
def instr2addrsize(instr): """Returns the address size for a given @instr""" return mode2addrsize(instr.mode)
def into(
_, instr)
def into(_, instr): return [], []
def iret(
ir, instr)
IRET implementation XXX: only support "no-privilege change"
def iret(ir, instr): """IRET implementation XXX: only support "no-privilege change" """ size = instr.v_opmode() exprs, _ = retf(ir, instr, m2_expr.ExprInt(size / 8, size=size)) tmp = mRSP[instr.mode][:size] + m2_expr.ExprInt((2 * size) / 8, size=size) exprs += _tpl_eflags(tmp) return exprs, []
def ja(
ir, instr, dst)
def ja(ir, instr, dst): #return gen_jcc(ir, instr, cf | zf, dst, False) return gen_jcc(ir, instr, m2_expr.ExprOp("CC_U>", cf, zf), dst, True)
def jae(
ir, instr, dst)
def jae(ir, instr, dst): #return gen_jcc(ir, instr, cf, dst, False) return gen_jcc(ir, instr, m2_expr.ExprOp("CC_U>=", cf), dst, True)
def jb(
ir, instr, dst)
def jb(ir, instr, dst): #return gen_jcc(ir, instr, cf, dst, True) return gen_jcc(ir, instr, m2_expr.ExprOp("CC_U<", cf), dst, True)
def jbe(
ir, instr, dst)
def jbe(ir, instr, dst): #return gen_jcc(ir, instr, cf | zf, dst, True) return gen_jcc(ir, instr, m2_expr.ExprOp("CC_U<=", cf, zf), dst, True)
def jcxz(
ir, instr, dst)
def jcxz(ir, instr, dst): return gen_jcc(ir, instr, mRCX[instr.mode][:16], dst, False)
def jecxz(
ir, instr, dst)
def jecxz(ir, instr, dst): return gen_jcc(ir, instr, mRCX[instr.mode][:32], dst, False)
def jg(
ir, instr, dst)
def jg(ir, instr, dst): #return gen_jcc(ir, instr, zf | (nf - of), dst, False) return gen_jcc(ir, instr, m2_expr.ExprOp("CC_S>", nf, of, zf), dst, True)
def jge(
ir, instr, dst)
def jge(ir, instr, dst): #return gen_jcc(ir, instr, nf - of, dst, False) return gen_jcc(ir, instr, m2_expr.ExprOp("CC_S>=", nf, of), dst, True)
def jl(
ir, instr, dst)
def jl(ir, instr, dst): #return gen_jcc(ir, instr, nf - of, dst, True) return gen_jcc(ir, instr, m2_expr.ExprOp("CC_S<", nf, of), dst, True)
def jle(
ir, instr, dst)
def jle(ir, instr, dst): #return gen_jcc(ir, instr, zf | (nf - of), dst, True) return gen_jcc(ir, instr, m2_expr.ExprOp("CC_S<=", nf, of, zf), dst, True)
def jmp(
ir, instr, dst)
def jmp(ir, instr, dst): e = [] meip = mRIP[ir.IRDst.size] if isinstance(dst, m2_expr.ExprOp): if dst.op == "segm": # Far jmp segm:addr segm = dst.args[0] base = dst.args[1] m1 = segm.zeroExtend(CS.size) m2 = base.zeroExtend(meip.size) elif dst.op == "far": # Far jmp far [eax] addr = dst.args[0].arg m1 = ir.ExprMem(addr, CS.size) m2 = ir.ExprMem(addr + m2_expr.ExprInt(2, addr.size), meip.size) else: raise RuntimeError("bad jmp operator") e.append(m2_expr.ExprAff(CS, m1)) e.append(m2_expr.ExprAff(meip, m2)) e.append(m2_expr.ExprAff(ir.IRDst, m2)) else: # Classic jmp e.append(m2_expr.ExprAff(meip, dst)) e.append(m2_expr.ExprAff(ir.IRDst, dst)) if isinstance(dst, m2_expr.ExprMem): dst = meip return e, []
def jno(
ir, instr, dst)
def jno(ir, instr, dst): return gen_jcc(ir, instr, of, dst, False)
def jnp(
ir, instr, dst)
def jnp(ir, instr, dst): return gen_jcc(ir, instr, pf, dst, False)
def jns(
ir, instr, dst)
def jns(ir, instr, dst): #return gen_jcc(ir, instr, nf, dst, False) return gen_jcc(ir, instr, m2_expr.ExprOp("CC_NEG", nf), dst, False)
def jnz(
ir, instr, dst)
def jnz(ir, instr, dst): #return gen_jcc(ir, instr, zf, dst, False) return gen_jcc(ir, instr, m2_expr.ExprOp("CC_EQ", zf), dst, False)
def jo(
ir, instr, dst)
def jo(ir, instr, dst): return gen_jcc(ir, instr, of, dst, True)
def jp(
ir, instr, dst)
def jp(ir, instr, dst): return gen_jcc(ir, instr, pf, dst, True)
def jrcxz(
ir, instr, dst)
def jrcxz(ir, instr, dst): return gen_jcc(ir, instr, mRCX[instr.mode], dst, False)
def js(
ir, instr, dst)
def js(ir, instr, dst): #return gen_jcc(ir, instr, nf, dst, True) return gen_jcc(ir, instr, m2_expr.ExprOp("CC_NEG", nf), dst, True)
def jz(
ir, instr, dst)
def jz(ir, instr, dst): #return gen_jcc(ir, instr, zf, dst, True) return gen_jcc(ir, instr, m2_expr.ExprOp("CC_EQ", zf), dst, True)
def l_and(
_, instr, dst, src)
def l_and(_, instr, dst, src): e = [] result = dst & src e += [m2_expr.ExprAff(zf, m2_expr.ExprOp('FLAG_EQ_AND', dst, src))] e += update_flag_np(result) e += null_flag_co() e.append(m2_expr.ExprAff(dst, result)) return (e, [])
def l_cmp(
_, instr, dst, src)
def l_cmp(_, instr, dst, src): e = [] arg1, arg2 = dst, src result = dst - src e += update_flag_arith_sub_znp(arg1, arg2) e += update_flag_arith_sub_co(arg1, arg2, result) e += update_flag_af(dst, src, result) return (e, [])
def l_in(
_, instr, src1, src2)
def l_in(_, instr, src1, src2): e = [] e.append(m2_expr.ExprAff(exception_flags, m2_expr.ExprInt(EXCEPT_PRIV_INSN, 32))) return e, []
def l_int(
_, instr, src)
def l_int(_, instr, src): e = [] # XXX if src.arg in [1, 3]: except_int = EXCEPT_SOFT_BP else: except_int = EXCEPT_INT_XX e.append(m2_expr.ExprAff(exception_flags, m2_expr.ExprInt(except_int, 32))) e.append(m2_expr.ExprAff(interrupt_num, src)) return e, []
def l_not(
_, instr, dst)
def l_not(_, instr, dst): e = [] result = (~dst) e.append(m2_expr.ExprAff(dst, result)) return (e, [])
def l_or(
_, instr, dst, src)
def l_or(_, instr, dst, src): e = [] result = dst | src e += [m2_expr.ExprAff(zf, m2_expr.ExprOp('FLAG_EQ', dst | src))] e += update_flag_np(result) e += null_flag_co() e.append(m2_expr.ExprAff(dst, result)) return (e, [])
def l_out(
_, instr, src1, src2)
def l_out(_, instr, src1, src2): e = [] e.append(m2_expr.ExprAff(exception_flags, m2_expr.ExprInt(EXCEPT_PRIV_INSN, 32))) return e, []
def l_outs(
_, instr, size)
def l_outs(_, instr, size): e = [] e.append(m2_expr.ExprAff(exception_flags, m2_expr.ExprInt(EXCEPT_PRIV_INSN, 32))) return e, []
def l_rol(
ir, instr, dst, src)
def l_rol(ir, instr, dst, src): return _rotate_tpl(ir, instr, dst, src, '<<<', left=True)
def l_ror(
ir, instr, dst, src)
def l_ror(ir, instr, dst, src): return _rotate_tpl(ir, instr, dst, src, '>>>')
def l_str(
_, instr, dst)
def l_str(_, instr, dst): e = [] e.append(m2_expr.ExprAff(dst, m2_expr.ExprOp('load_tr_segment_selector', m2_expr.ExprInt(0, 32)))) return e, []
def l_syscall(
_, instr)
def l_syscall(_, instr): e = [] e.append(m2_expr.ExprAff(exception_flags, m2_expr.ExprInt(EXCEPT_PRIV_INSN, 32))) return e, []
def l_sysenter(
_, instr)
def l_sysenter(_, instr): e = [] e.append(m2_expr.ExprAff(exception_flags, m2_expr.ExprInt(EXCEPT_PRIV_INSN, 32))) return e, []
def l_test(
_, instr, dst, src)
def l_test(_, instr, dst, src): e = [] result = dst & src e += [m2_expr.ExprAff(zf, m2_expr.ExprOp('FLAG_EQ_CMP', result, m2_expr.ExprInt(0, result.size)))] e += [m2_expr.ExprAff(nf, m2_expr.ExprOp("FLAG_SIGN_SUB", result, m2_expr.ExprInt(0, result.size)))] e += update_flag_pf(result) e += null_flag_co() return (e, [])
def lahf(
_, instr)
def lahf(_, instr): e = [] args = [cf, m2_expr.ExprInt(1, 1), pf, m2_expr.ExprInt(0, 1), af, m2_expr.ExprInt(0, 1), zf, nf] e.append( m2_expr.ExprAff(mRAX[instr.mode][8:16], m2_expr.ExprCompose(*args))) return e, []
def lar(
_, instr, dst, src)
def lar(_, instr, dst, src): e = [] e.append(m2_expr.ExprAff(dst, m2_expr.ExprOp('access_segment', src))) e.append(m2_expr.ExprAff(zf, m2_expr.ExprOp('access_segment_ok', src))) return e, []
def ldmxcsr(
ir, instr, dst)
def ldmxcsr(ir, instr, dst): # Implemented as a NOP return [], []
def lds(
ir, instr, dst, src)
def lds(ir, instr, dst, src): e = [] e.append(m2_expr.ExprAff(dst, ir.ExprMem(src.arg, size=dst.size))) DS_value = ir.ExprMem(src.arg + m2_expr.ExprInt(dst.size / 8, src.arg.size), size=16) e.append(m2_expr.ExprAff(DS, DS_value)) return e, []
def lea(
_, instr, dst, src)
def lea(_, instr, dst, src): ptr = src.arg if src.is_mem_segm(): # Do not use segmentation here ptr = ptr.args[1] if ptr.size > dst.size: ptr = ptr[:dst.size] e = [m2_expr.ExprAff(dst, ptr.zeroExtend(dst.size))] return e, []
def leave(
ir, instr)
def leave(ir, instr): opmode, admode = instr.v_opmode(), instr.v_admode() size = instr.mode myesp = mRSP[size] e = [] e.append(m2_expr.ExprAff(mRBP[size], ir.ExprMem(mRBP[size], size=size))) e.append(m2_expr.ExprAff(myesp, m2_expr.ExprInt(size / 8, size) + mRBP[size])) return e, []
def les(
ir, instr, dst, src)
def les(ir, instr, dst, src): e = [] e.append(m2_expr.ExprAff(dst, ir.ExprMem(src.arg, size=dst.size))) ES_value = ir.ExprMem(src.arg + m2_expr.ExprInt(dst.size / 8, src.arg.size), size=16) e.append(m2_expr.ExprAff(ES, ES_value)) return e, []
def lfence(
_, instr, src=None)
def lfence(_, instr, src=None): # see 3-485 on this documentation # https://www-ssl.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf return [], []
def lfs(
ir, instr, dst, src)
def lfs(ir, instr, dst, src): e = [] e.append(m2_expr.ExprAff(dst, ir.ExprMem(src.arg, size=dst.size))) FS_value = ir.ExprMem(src.arg + m2_expr.ExprInt(dst.size / 8, src.arg.size), size=16) e.append(m2_expr.ExprAff(FS, FS_value)) return e, []
def lgs(
ir, instr, dst, src)
def lgs(ir, instr, dst, src): e = [] e.append(m2_expr.ExprAff(dst, ir.ExprMem(src.arg, size=dst.size))) GS_value = ir.ExprMem(src.arg + m2_expr.ExprInt(dst.size / 8, src.arg.size), size=16) e.append(m2_expr.ExprAff(GS, GS_value)) return e, []
def lods(
ir, instr, size)
def lods(ir, instr, size): loc_df_0, loc_df_0_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) loc_df_1, loc_df_1_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) loc_next_expr = m2_expr.ExprLoc(ir.get_next_loc_key(instr), ir.IRDst.size) e = [] addr_o = mRSI[instr.mode][:instr.v_admode()] addr = addr_o addr_p = addr + m2_expr.ExprInt(size / 8, addr.size) addr_m = addr - m2_expr.ExprInt(size / 8, addr.size) if ir.do_str_segm: mss = DS if instr.additional_info.g2.value: raise NotImplementedError("add segm support") addr = ir.gen_segm_expr(mss, addr) b = mRAX[instr.mode][:size] e0 = [] e0.append(m2_expr.ExprAff(addr_o, addr_p)) e0.append(m2_expr.ExprAff(ir.IRDst, loc_next_expr)) e0 = IRBlock(loc_df_0, [AssignBlock(e0, instr)]) e1 = [] e1.append(m2_expr.ExprAff(addr_o, addr_m)) e1.append(m2_expr.ExprAff(ir.IRDst, loc_next_expr)) e1 = IRBlock(loc_df_1, [AssignBlock(e1, instr)]) e = [] if instr.mode == 64 and b.size == 32: e.append(m2_expr.ExprAff(mRAX[instr.mode], ir.ExprMem(addr, size).zeroExtend(64))) else: e.append(m2_expr.ExprAff(b, ir.ExprMem(addr, size))) e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(df, loc_df_1_expr, loc_df_0_expr))) return e, [e0, e1]
def loop(
ir, instr, dst)
def loop(ir, instr, dst): e = [] meip = mRIP[ir.IRDst.size] admode = instr.v_admode() myecx = mRCX[instr.mode][:admode] n = m2_expr.ExprLoc(ir.get_next_loc_key(instr), ir.IRDst.size) c = myecx - m2_expr.ExprInt(1, myecx.size) dst_o = m2_expr.ExprCond(c, dst.zeroExtend(ir.IRDst.size), n.zeroExtend(ir.IRDst.size)) e.append(m2_expr.ExprAff(myecx, c)) e.append(m2_expr.ExprAff(meip, dst_o)) e.append(m2_expr.ExprAff(ir.IRDst, dst_o)) return e, []
def loope(
ir, instr, dst)
def loope(ir, instr, dst): e = [] meip = mRIP[ir.IRDst.size] admode = instr.v_admode() myecx = mRCX[instr.mode][:admode] n = m2_expr.ExprLoc(ir.get_next_loc_key(instr), ir.IRDst.size) c = m2_expr.ExprCond(myecx - m2_expr.ExprInt(1, size=myecx.size), m2_expr.ExprInt(1, 1), m2_expr.ExprInt(0, 1)) c &= zf e.append(m2_expr.ExprAff(myecx, myecx - m2_expr.ExprInt(1, myecx.size))) dst_o = m2_expr.ExprCond(c, dst.zeroExtend(ir.IRDst.size), n.zeroExtend(ir.IRDst.size)) e.append(m2_expr.ExprAff(meip, dst_o)) e.append(m2_expr.ExprAff(ir.IRDst, dst_o)) return e, []
def loopne(
ir, instr, dst)
def loopne(ir, instr, dst): e = [] meip = mRIP[ir.IRDst.size] admode = instr.v_admode() myecx = mRCX[instr.mode][:admode] n = m2_expr.ExprLoc(ir.get_next_loc_key(instr), ir.IRDst.size) c = m2_expr.ExprCond(myecx - m2_expr.ExprInt(1, size=myecx.size), m2_expr.ExprInt(1, 1), m2_expr.ExprInt(0, 1)) c &= zf ^ m2_expr.ExprInt(1, 1) e.append(m2_expr.ExprAff(myecx, myecx - m2_expr.ExprInt(1, myecx.size))) dst_o = m2_expr.ExprCond(c, dst.zeroExtend(ir.IRDst.size), n.zeroExtend(ir.IRDst.size)) e.append(m2_expr.ExprAff(meip, dst_o)) e.append(m2_expr.ExprAff(ir.IRDst, dst_o)) return e, []
def lsl(
_, instr, dst, src)
def lsl(_, instr, dst, src): e = [] e.append(m2_expr.ExprAff(dst, m2_expr.ExprOp('load_segment_limit', src))) e.append(m2_expr.ExprAff(zf, m2_expr.ExprOp('load_segment_limit_ok', src))) return e, []
def lss(
ir, instr, dst, src)
def lss(ir, instr, dst, src): e = [] e.append(m2_expr.ExprAff(dst, ir.ExprMem(src.arg, size=dst.size))) SS_value = ir.ExprMem(src.arg + m2_expr.ExprInt(dst.size / 8, src.arg.size), size=16) e.append(m2_expr.ExprAff(SS, SS_value)) return e, []
def maskmovq(
ir, instr, src, mask)
def maskmovq(ir, instr, src, mask): loc_next = ir.get_next_loc_key(instr) loc_next_expr = m2_expr.ExprLoc(loc_next, ir.IRDst.size) blks = [] # For each possibility, check if a write is necessary check_labels = [m2_expr.ExprLoc(ir.loc_db.add_location(), ir.IRDst.size) for _ in xrange(0, mask.size, 8)] # If the write has to be done, do it (otherwise, nothing happen) write_labels = [m2_expr.ExprLoc(ir.loc_db.add_location(), ir.IRDst.size) for _ in xrange(0, mask.size, 8)] # Build check blocks for i, start in enumerate(xrange(0, mask.size, 8)): bit = mask[start + 7: start + 8] cur_label = check_labels[i] next_check_label = check_labels[i + 1] if (i + 1) < len(check_labels) else loc_next_expr write_label = write_labels[i] check = m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(bit, write_label, next_check_label)) blks.append(IRBlock(cur_label.loc_key, [AssignBlock([check], instr)])) # Build write blocks dst_addr = mRDI[instr.mode] for i, start in enumerate(xrange(0, mask.size, 8)): bit = mask[start + 7: start + 8] cur_label = write_labels[i] next_check_label = check_labels[i + 1] if (i + 1) < len(check_labels) else loc_next_expr write_addr = dst_addr + m2_expr.ExprInt(i, dst_addr.size) # @8[DI/EDI/RDI + i] = src[byte i] write_mem = m2_expr.ExprAff(m2_expr.ExprMem(write_addr, 8), src[start: start + 8]) jump = m2_expr.ExprAff(ir.IRDst, next_check_label) blks.append(IRBlock(cur_label.loc_key, [AssignBlock([write_mem, jump], instr)])) # If mask is null, bypass all e = [m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(mask, check_labels[0], loc_next_expr))] return e, blks
def maxpd(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def maxps(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def maxsd(
ir, instr, dst, src)
def vec_op_clip_instr(ir, instr, dst, src): if op == '-': result = dst[:size] - src[:size] else: result = m2_expr.ExprOp(op, dst[:size], src[:size]) if callback is not None: result = callback(result) return [m2_expr.ExprAff(dst[:size], result)], []
def maxss(
ir, instr, dst, src)
def vec_op_clip_instr(ir, instr, dst, src): if op == '-': result = dst[:size] - src[:size] else: result = m2_expr.ExprOp(op, dst[:size], src[:size]) if callback is not None: result = callback(result) return [m2_expr.ExprAff(dst[:size], result)], []
def mem2double(
instr, arg)
Add float convertion if argument is an ExprMem @arg: argument to tranform
def mem2double(instr, arg): """ Add float convertion if argument is an ExprMem @arg: argument to tranform """ if isinstance(arg, m2_expr.ExprMem): if arg.size > 64: # TODO: move to 80 bits arg = m2_expr.ExprMem(expraddr(instr.mode, arg.arg), size=64) return m2_expr.ExprOp('mem_%.2d_to_double' % arg.size, arg) else: return arg
def mfence(
_, instr, src=None)
def mfence(_, instr, src=None): # see 3-516 on this documentation # https://www-ssl.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf return [], []
def minpd(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def minps(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def minsd(
ir, instr, dst, src)
def vec_op_clip_instr(ir, instr, dst, src): if op == '-': result = dst[:size] - src[:size] else: result = m2_expr.ExprOp(op, dst[:size], src[:size]) if callback is not None: result = callback(result) return [m2_expr.ExprAff(dst[:size], result)], []
def minss(
ir, instr, dst, src)
def vec_op_clip_instr(ir, instr, dst, src): if op == '-': result = dst[:size] - src[:size] else: result = m2_expr.ExprOp(op, dst[:size], src[:size]) if callback is not None: result = callback(result) return [m2_expr.ExprAff(dst[:size], result)], []
def mode2addrsize(
mode)
Returns the address size for a given @mode
def mode2addrsize(mode): """Returns the address size for a given @mode""" mode2size = {16:32, 32:32, 64:64} if mode not in mode2size: raise RuntimeError("Unknown size %s", mode) return mode2size[mode]
def mov(
_, instr, dst, src)
def mov(_, instr, dst, src): if dst in [ES, CS, SS, DS, FS, GS]: src = src[:dst.size] if src in [ES, CS, SS, DS, FS, GS]: src = src.zeroExtend(dst.size) e = [m2_expr.ExprAff(dst, src)] return e, []
def movapd(
_, instr, dst, src)
def movapd(_, instr, dst, src): # XXX TODO alignement check return [m2_expr.ExprAff(dst, src)], []
def movd(
_, instr, dst, src)
def movd(_, instr, dst, src): e = [] if dst in regs_mm_expr: e.append(m2_expr.ExprAff( dst, m2_expr.ExprCompose(src, m2_expr.ExprInt(0, 32)))) elif dst in regs_xmm_expr: e.append(m2_expr.ExprAff( dst, m2_expr.ExprCompose(src, m2_expr.ExprInt(0, 96)))) else: e.append(m2_expr.ExprAff(dst, src[:32])) return e, []
def movdq2q(
_, instr, dst, src)
def movdq2q(_, instr, dst, src): e = [] e.append(m2_expr.ExprAff(dst, src[:64])) return e, []
def movdqu(
_, instr, dst, src)
def movdqu(_, instr, dst, src): # XXX TODO alignement check return [m2_expr.ExprAff(dst, src)], []
def movhlps(
_, instr, dst, src)
def movhlps(_, instr, dst, src): e = [] e.append(m2_expr.ExprAff(dst[:64], src[64:128])) return e, []
def movhpd(
_, instr, dst, src)
def movhpd(_, instr, dst, src): e = [] if src.size == 64: e.append(m2_expr.ExprAff(dst[64:128], src)) elif dst.size == 64: e.append(m2_expr.ExprAff(dst, src[64:128])) else: raise RuntimeError("bad encoding!") return e, []
def movlhps(
_, instr, dst, src)
def movlhps(_, instr, dst, src): e = [] e.append(m2_expr.ExprAff(dst[64:128], src[:64])) return e, []
def movlpd(
_, instr, dst, src)
def movlpd(_, instr, dst, src): e = [] e.append(m2_expr.ExprAff(dst[:64], src[:64])) return e, []
def movlps(
_, instr, dst, src)
def movlps(_, instr, dst, src): e = [] e.append(m2_expr.ExprAff(dst[:64], src[:64])) return e, []
def movmskpd(
ir, instr, dst, src)
def movmskpd(ir, instr, dst, src): out = [] for i in xrange(2): out.append(src[(64 * i) + 63:(64 * i) + 64]) return [m2_expr.ExprAff(dst, m2_expr.ExprCompose(*out).zeroExtend(dst.size))], []
def movmskps(
ir, instr, dst, src)
def movmskps(ir, instr, dst, src): out = [] for i in xrange(4): out.append(src[(32 * i) + 31:(32 * i) + 32]) return [m2_expr.ExprAff(dst, m2_expr.ExprCompose(*out).zeroExtend(dst.size))], []
def movq(
_, instr, dst, src)
def movq(_, instr, dst, src): src_final = (src.zeroExtend(dst.size) if dst.size >= src.size else src[:dst.size]) return [m2_expr.ExprAff(dst, src_final)], []
def movq2dq(
_, instr, dst, src)
def movq2dq(_, instr, dst, src): e = [] e.append(m2_expr.ExprAff(dst, src[:64].zeroExtend(dst.size))) return e, []
def movs(
ir, instr, size)
def movs(ir, instr, size): loc_df_0, loc_df_0_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) loc_df_1, loc_df_1_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) loc_next_expr = m2_expr.ExprLoc(ir.get_next_loc_key(instr), ir.IRDst.size) dst = mRDI[instr.mode][:instr.v_admode()] src = mRSI[instr.mode][:instr.v_admode()] e = [] if ir.do_str_segm: if instr.additional_info.g2.value: raise NotImplementedError("add segm support") src_sgm = ir.gen_segm_expr(DS, src) dst_sgm = ir.gen_segm_expr(ES, dst) else: src_sgm = src dst_sgm = dst offset = m2_expr.ExprInt(size / 8, src.size) e.append(m2_expr.ExprAff(ir.ExprMem(dst_sgm, size), ir.ExprMem(src_sgm, size))) e0 = [] e0.append(m2_expr.ExprAff(src, src + offset)) e0.append(m2_expr.ExprAff(dst, dst + offset)) e0.append(m2_expr.ExprAff(ir.IRDst, loc_next_expr)) e0 = IRBlock(loc_df_0, [AssignBlock(e0, instr)]) e1 = [] e1.append(m2_expr.ExprAff(src, src - offset)) e1.append(m2_expr.ExprAff(dst, dst - offset)) e1.append(m2_expr.ExprAff(ir.IRDst, loc_next_expr)) e1 = IRBlock(loc_df_1, [AssignBlock(e1, instr)]) e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(df, loc_df_1_expr, loc_df_0_expr))) return e, [e0, e1]
def movsd(
_, instr, dst, src)
def movsd(_, instr, dst, src): # 64 bits access if dst.is_id() and src.is_id(): src = src[:64] dst = dst[:64] elif dst.is_mem() and src.is_id(): dst = m2_expr.ExprMem(dst.arg, 64) src = src[:64] else: src = m2_expr.ExprMem(src.arg, 64) # Erase dst high bits src = src.zeroExtend(dst.size) return [m2_expr.ExprAff(dst, src)], []
def movsd_dispatch(
ir, instr, dst=None, src=None)
def movsd_dispatch(ir, instr, dst=None, src=None): if dst is None and src is None: return movs(ir, instr, 32) else: return movsd(ir, instr, dst, src)
def movss(
_, instr, dst, src)
def movss(_, instr, dst, src): e = [] if not isinstance(dst, m2_expr.ExprMem) and not isinstance(src, m2_expr.ExprMem): # Source and Destination xmm e.append(m2_expr.ExprAff(dst[:32], src[:32])) elif not isinstance(src, m2_expr.ExprMem) and isinstance(dst, m2_expr.ExprMem): # Source XMM Destination Mem e.append(m2_expr.ExprAff(dst, src[:32])) else: # Source Mem Destination XMM e.append(m2_expr.ExprAff( dst, m2_expr.ExprCompose(src, m2_expr.ExprInt(0, 96)))) return e, []
def movsx(
_, instr, dst, src)
def movsx(_, instr, dst, src): e = [m2_expr.ExprAff(dst, src.signExtend(dst.size))] return e, []
def movzx(
_, instr, dst, src)
def movzx(_, instr, dst, src): e = [m2_expr.ExprAff(dst, src.zeroExtend(dst.size))] return e, []
def mul(
_, instr, src1)
def mul(_, instr, src1): e = [] size = src1.size if src1.size in [16, 32, 64]: result = m2_expr.ExprOp('*', mRAX[size].zeroExtend(size * 2), src1.zeroExtend(size * 2)) e.append(m2_expr.ExprAff(mRAX[size], result[:size])) e.append(m2_expr.ExprAff(mRDX[size], result[size:size * 2])) elif src1.size == 8: result = m2_expr.ExprOp('*', mRAX[instr.mode][:8].zeroExtend(16), src1.zeroExtend(16)) e.append(m2_expr.ExprAff(mRAX[instr.mode][:16], result)) else: raise ValueError('unknow size') e.append(m2_expr.ExprAff(of, m2_expr.ExprCond(result[size:size * 2], m2_expr.ExprInt(1, 1), m2_expr.ExprInt(0, 1)))) e.append(m2_expr.ExprAff(cf, m2_expr.ExprCond(result[size:size * 2], m2_expr.ExprInt(1, 1), m2_expr.ExprInt(0, 1)))) return e, []
def mulpd(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def mulps(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def mulsd(
ir, instr, dst, src)
def vec_op_clip_instr(ir, instr, dst, src): if op == '-': result = dst[:size] - src[:size] else: result = m2_expr.ExprOp(op, dst[:size], src[:size]) if callback is not None: result = callback(result) return [m2_expr.ExprAff(dst[:size], result)], []
def mulss(
ir, instr, dst, src)
def vec_op_clip_instr(ir, instr, dst, src): if op == '-': result = dst[:size] - src[:size] else: result = m2_expr.ExprOp(op, dst[:size], src[:size]) if callback is not None: result = callback(result) return [m2_expr.ExprAff(dst[:size], result)], []
def neg(
_, instr, src)
def neg(_, instr, src): e = [] dst = m2_expr.ExprInt(0, src.size) arg1, arg2 = dst, src result = arg1 - arg2 e += update_flag_arith_sub_znp(arg1, arg2) e += update_flag_arith_sub_co(arg1, arg2, result) e += update_flag_af(arg1, arg2, result) e.append(m2_expr.ExprAff(src, result)) return (e, [])
def nop(
_, instr, a=None)
def nop(_, instr, a=None): return [], []
def null_flag_co(
)
def null_flag_co(): e = [] e.append(m2_expr.ExprAff(of, m2_expr.ExprInt(0, of.size))) e.append(m2_expr.ExprAff(cf, m2_expr.ExprInt(0, cf.size))) return e
def orps(
_, instr, dst, src)
def orps(_, instr, dst, src): e = [] e.append(m2_expr.ExprAff(dst, m2_expr.ExprOp('|', dst, src))) return e, []
def packssdw(
ir, instr, dst, src)
def packssdw(ir, instr, dst, src): out = [] for source in [dst, src]: for start in xrange(0, dst.size, 32): out.append(_signed_saturation(source[start:start + 32], 16)) return [m2_expr.ExprAff(dst, m2_expr.ExprCompose(*out))], []
def packsswb(
ir, instr, dst, src)
def packsswb(ir, instr, dst, src): out = [] for source in [dst, src]: for start in xrange(0, dst.size, 16): out.append(_signed_saturation(source[start:start + 16], 8)) return [m2_expr.ExprAff(dst, m2_expr.ExprCompose(*out))], []
def packuswb(
ir, instr, dst, src)
def packuswb(ir, instr, dst, src): out = [] for source in [dst, src]: for start in xrange(0, dst.size, 16): out.append(_unsigned_saturation(source[start:start + 16], 8)) return [m2_expr.ExprAff(dst, m2_expr.ExprCompose(*out))], []
def paddb(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def paddd(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def paddq(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def paddsb(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def paddsw(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def paddusb(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def paddusw(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def paddw(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def palignr(
ir, instr, dst, src, imm)
def palignr(ir, instr, dst, src, imm): # dst.src >> imm * 8 [:dst.size] shift = int(imm) * 8 if shift == 0: result = src elif shift == src.size: result = dst elif shift > src.size: result = dst >> m2_expr.ExprInt(shift - src.size, dst.size) else: # shift < src.size result = m2_expr.ExprCompose( src[shift:], dst[:shift], ) return [m2_expr.ExprAff(dst, result)], []
def pand(
_, instr, dst, src)
def pand(_, instr, dst, src): e = [] result = dst & src # No flag affected e.append(m2_expr.ExprAff(dst, result)) return e, []
def pandn(
_, instr, dst, src)
def pandn(_, instr, dst, src): e = [] result = (dst ^ dst.mask) & src # No flag affected e.append(m2_expr.ExprAff(dst, result)) return e, []
def pavgb(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def pavgw(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def pcmpeq(
_, instr, dst, src, size)
def pcmpeq(_, instr, dst, src, size): e = [] for i in xrange(0, dst.size, size): test = m2_expr.expr_is_equal(dst[i:i + size], src[i:i + size]) e.append(m2_expr.ExprAff(dst[i:i + size], m2_expr.ExprCond(test, m2_expr.ExprInt(-1, size), m2_expr.ExprInt(0, size)))) return e, []
def pcmpeqb(
ir, instr, dst, src)
def pcmpeqb(ir, instr, dst, src): return pcmpeq(ir, instr, dst, src, 8)
def pcmpeqd(
ir, instr, dst, src)
def pcmpeqd(ir, instr, dst, src): return pcmpeq(ir, instr, dst, src, 32)
def pcmpeqq(
ir, instr, dst, src)
def pcmpeqq(ir, instr, dst, src): return pcmpeq(ir, instr, dst, src, 64)
def pcmpeqw(
ir, instr, dst, src)
def pcmpeqw(ir, instr, dst, src): return pcmpeq(ir, instr, dst, src, 16)
def pcmpgt(
_, instr, dst, src, size)
def pcmpgt(_, instr, dst, src, size): e = [] for i in xrange(0, dst.size, size): test = m2_expr.expr_is_signed_greater(dst[i:i + size], src[i:i + size]) e.append(m2_expr.ExprAff(dst[i:i + size], m2_expr.ExprCond(test, m2_expr.ExprInt(-1, size), m2_expr.ExprInt(0, size)))) return e, []
def pcmpgtb(
ir, instr, dst, src)
def pcmpgtb(ir, instr, dst, src): return pcmpgt(ir, instr, dst, src, 8)
def pcmpgtd(
ir, instr, dst, src)
def pcmpgtd(ir, instr, dst, src): return pcmpgt(ir, instr, dst, src, 32)
def pcmpgtq(
ir, instr, dst, src)
def pcmpgtq(ir, instr, dst, src): return pcmpgt(ir, instr, dst, src, 64)
def pcmpgtw(
ir, instr, dst, src)
def pcmpgtw(ir, instr, dst, src): return pcmpgt(ir, instr, dst, src, 16)
def pextr(
_, instr, dst, src, imm, size)
def pextr(_, instr, dst, src, imm, size): e = [] mask = {8: 0xF, 16: 0x7, 32: 0x3, 64: 0x1}[size] sel = (int(imm) & mask) * size e.append(m2_expr.ExprAff(dst, src[sel:sel + size].zeroExtend(dst.size))) return e, []
def pextrb(
ir, instr, dst, src, imm)
def pextrb(ir, instr, dst, src, imm): return pextr(ir, instr, dst, src, imm, 8)
def pextrd(
ir, instr, dst, src, imm)
def pextrd(ir, instr, dst, src, imm): return pextr(ir, instr, dst, src, imm, 32)
def pextrq(
ir, instr, dst, src, imm)
def pextrq(ir, instr, dst, src, imm): return pextr(ir, instr, dst, src, imm, 64)
def pextrw(
ir, instr, dst, src, imm)
def pextrw(ir, instr, dst, src, imm): return pextr(ir, instr, dst, src, imm, 16)
def pinsr(
_, instr, dst, src, imm, size)
def pinsr(_, instr, dst, src, imm, size): e = [] mask = {8: 0xF, 16: 0x7, 32: 0x3, 64: 0x1}[size] sel = (int(imm) & mask) * size e.append(m2_expr.ExprAff(dst[sel:sel + size], src[:size])) return e, []
def pinsrb(
ir, instr, dst, src, imm)
def pinsrb(ir, instr, dst, src, imm): return pinsr(ir, instr, dst, src, imm, 8)
def pinsrd(
ir, instr, dst, src, imm)
def pinsrd(ir, instr, dst, src, imm): return pinsr(ir, instr, dst, src, imm, 32)
def pinsrq(
ir, instr, dst, src, imm)
def pinsrq(ir, instr, dst, src, imm): return pinsr(ir, instr, dst, src, imm, 64)
def pinsrw(
ir, instr, dst, src, imm)
def pinsrw(ir, instr, dst, src, imm): return pinsr(ir, instr, dst, src, imm, 16)
def pmaddwd(
ir, instr, dst, src)
def pmaddwd(ir, instr, dst, src): sizedst = 32 sizesrc = 16 out = [] for start in xrange(0, dst.size, sizedst): base = start mul1 = src[base: base + sizesrc].signExtend(sizedst) * dst[base: base + sizesrc].signExtend(sizedst) base += sizesrc mul2 = src[base: base + sizesrc].signExtend(sizedst) * dst[base: base + sizesrc].signExtend(sizedst) out.append(mul1 + mul2) return [m2_expr.ExprAff(dst, m2_expr.ExprCompose(*out))], []
def pmaxsw(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def pmaxub(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def pmaxud(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def pmaxuw(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def pminsw(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def pminub(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def pminud(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def pminuw(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def pmovmskb(
_, instr, dst, src)
def pmovmskb(_, instr, dst, src): e = [] out = [] for i in xrange(src.size / 8): out.append(src[8 * i + 7:8 * (i + 1)]) src = m2_expr.ExprCompose(*out) e.append(m2_expr.ExprAff(dst, src.zeroExtend(dst.size))) return e, []
def pmulhb(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def pmulhd(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def pmulhq(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def pmulhub(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def pmulhud(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def pmulhuq(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def pmulhuw(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def pmulhw(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def pmullb(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def pmulld(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def pmullq(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def pmullw(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def pmuludq(
ir, instr, dst, src)
def pmuludq(ir, instr, dst, src): e = [] if dst.size == 64: e.append(m2_expr.ExprAff( dst, src[:32].zeroExtend(64) * dst[:32].zeroExtend(64) )) elif dst.size == 128: e.append(m2_expr.ExprAff( dst[:64], src[:32].zeroExtend(64) * dst[:32].zeroExtend(64) )) e.append(m2_expr.ExprAff( dst[64:], src[64:96].zeroExtend(64) * dst[64:96].zeroExtend(64) )) else: raise RuntimeError("Unsupported size %d" % dst.size) return e, []
def pop(
ir, instr, src)
def pop(ir, instr, src): return pop_gen(ir, instr, src, instr.mode)
def pop_gen(
ir, instr, src, size)
def pop_gen(ir, instr, src, size): e = [] if not size in [16, 32, 64]: raise ValueError('bad size stacker!') sp = mRSP[instr.mode] new_sp = sp + m2_expr.ExprInt(src.size / 8, sp.size) # don't generate ESP incrementation on POP ESP if src != ir.sp: e.append(m2_expr.ExprAff(sp, new_sp)) # XXX FIX XXX for pop [esp] if isinstance(src, m2_expr.ExprMem): src = expr_simp(src.replace_expr({sp: new_sp})) result = sp if ir.do_stk_segm: result = ir.gen_segm_expr(SS, result) e.append(m2_expr.ExprAff(src, ir.ExprMem(result, src.size))) return e, []
def popa(
ir, instr)
def popa(ir, instr): return popa_gen(ir, instr, 16)
def popa_gen(
ir, instr, size)
def popa_gen(ir, instr, size): e = [] cur_sp = mRSP[instr.mode] for i, reg in enumerate(reversed(pa_regs)): if reg == mRSP: continue stk_ptr = cur_sp + m2_expr.ExprInt((size / 8) * i, instr.mode) e.append(m2_expr.ExprAff(reg[size], ir.ExprMem(stk_ptr, size))) stk_ptr = cur_sp + m2_expr.ExprInt((size / 8) * (i + 1), instr.mode) e.append(m2_expr.ExprAff(cur_sp, stk_ptr)) return e, []
def popad(
ir, instr)
def popad(ir, instr): return popa_gen(ir, instr, 32)
def popfd(
ir, instr)
def popfd(ir, instr): tmp = ir.ExprMem(mRSP[instr.mode], 32) e = [] e.append(m2_expr.ExprAff(cf, m2_expr.ExprSlice(tmp, 0, 1))) e.append(m2_expr.ExprAff(pf, m2_expr.ExprSlice(tmp, 2, 3))) e.append(m2_expr.ExprAff(af, m2_expr.ExprSlice(tmp, 4, 5))) e.append(m2_expr.ExprAff(zf, m2_expr.ExprSlice(tmp, 6, 7))) e.append(m2_expr.ExprAff(nf, m2_expr.ExprSlice(tmp, 7, 8))) e.append(m2_expr.ExprAff(tf, m2_expr.ExprSlice(tmp, 8, 9))) e.append(m2_expr.ExprAff(i_f, m2_expr.ExprSlice(tmp, 9, 10))) e.append(m2_expr.ExprAff(df, m2_expr.ExprSlice(tmp, 10, 11))) e.append(m2_expr.ExprAff(of, m2_expr.ExprSlice(tmp, 11, 12))) e.append(m2_expr.ExprAff(iopl, m2_expr.ExprSlice(tmp, 12, 14))) e.append(m2_expr.ExprAff(nt, m2_expr.ExprSlice(tmp, 14, 15))) e.append(m2_expr.ExprAff(rf, m2_expr.ExprSlice(tmp, 16, 17))) e.append(m2_expr.ExprAff(vm, m2_expr.ExprSlice(tmp, 17, 18))) e.append(m2_expr.ExprAff(ac, m2_expr.ExprSlice(tmp, 18, 19))) e.append(m2_expr.ExprAff(vif, m2_expr.ExprSlice(tmp, 19, 20))) e.append(m2_expr.ExprAff(vip, m2_expr.ExprSlice(tmp, 20, 21))) e.append(m2_expr.ExprAff(i_d, m2_expr.ExprSlice(tmp, 21, 22))) e.append(m2_expr.ExprAff(mRSP[instr.mode], mRSP[instr.mode] + m2_expr.ExprInt(instr.mode / 8, mRSP[instr.mode].size))) e.append(m2_expr.ExprAff(exception_flags, m2_expr.ExprCond(m2_expr.ExprSlice(tmp, 8, 9), m2_expr.ExprInt( EXCEPT_SOFT_BP, 32), exception_flags ) ) ) return e, []
def popfw(
ir, instr)
def popfw(ir, instr): tmp = ir.ExprMem(mRSP[instr.mode], 32) e = _tpl_eflags(tmp) e.append( m2_expr.ExprAff(mRSP[instr.mode], mRSP[instr.mode] + m2_expr.ExprInt(2, mRSP[instr.mode].size))) return e, []
def popw(
ir, instr, src)
def popw(ir, instr, src): return pop_gen(ir, instr, src, 16)
def por(
_, instr, dst, src)
def por(_, instr, dst, src): e = [] result = dst | src e.append(m2_expr.ExprAff(dst, result)) return e, []
def prefetch0(
_, instr, src=None)
def prefetch0(_, instr, src=None): # see 4-198 on this documentation # https://www-ssl.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf return [], []
def prefetch1(
_, instr, src=None)
def prefetch1(_, instr, src=None): # see 4-198 on this documentation # https://www-ssl.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf return [], []
def prefetch2(
_, instr, src=None)
def prefetch2(_, instr, src=None): # see 4-198 on this documentation # https://www-ssl.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf return [], []
def prefetchnta(
_, instr, src=None)
def prefetchnta(_, instr, src=None): # see 4-201 on this documentation # https://www-ssl.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf return [], []
def prefetchw(
_, instr, src=None)
def prefetchw(_, instr, src=None): # see 4-201 on this documentation # https://www-ssl.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf return [], []
def ps_rl_ll(
ir, instr, dst, src, op, size)
def ps_rl_ll(ir, instr, dst, src, op, size): mask = {16: 0xF, 32: 0x1F, 64: 0x3F}[size] mask = m2_expr.ExprInt(mask, dst.size) # Saturate the counter to 2**size count = src.zeroExtend(dst.size) count = m2_expr.ExprCond(count & expr_simp(~mask), m2_expr.ExprInt(size, dst.size), # saturation count, # count < 2**size ) count = count[:size] if src.is_int(): count = expr_simp(count) out = [] for i in xrange(0, dst.size, size): out.append(m2_expr.ExprOp(op, dst[i:i + size], count)) return [m2_expr.ExprAff(dst, m2_expr.ExprCompose(*out))], []
def psadbw(
ir, instr, dst, src)
def psadbw(ir, instr, dst, src): sizedst = 16 sizesrc = 8 out_dst = [] for start in xrange(0, dst.size, 64): out = [] for src_start in xrange(0, 64, sizesrc): beg = start + src_start end = beg + sizesrc # Not clear in the doc equations, but in the text, src and dst are: # "8 unsigned byte integers" out.append(_absolute(dst[beg: end].zeroExtend(sizedst) - src[beg: end].zeroExtend(sizedst))) out_dst.append(m2_expr.ExprOp("+", *out)) out_dst.append(m2_expr.ExprInt(0, 64 - sizedst)) return [m2_expr.ExprAff(dst, m2_expr.ExprCompose(*out_dst))], []
def pshufb(
_, instr, dst, src)
def pshufb(_, instr, dst, src): e = [] if dst.size == 64: bit_l = 3 elif dst.size == 128: bit_l = 4 else: raise NotImplementedError("bad size") for i in xrange(0, src.size, 8): index = src[ i:i + bit_l].zeroExtend(dst.size) << m2_expr.ExprInt(3, dst.size) value = (dst >> index)[:8] e.append(m2_expr.ExprAff(dst[i:i + 8], m2_expr.ExprCond(src[i + 7:i + 8], m2_expr.ExprInt(0, 8), value))) return e, []
def pshufd(
_, instr, dst, src, imm)
def pshufd(_, instr, dst, src, imm): control = int(imm) out = [] for i in xrange(4): shift = ((control >> (i * 2)) & 3) * 32 # shift is 2 bits long, expr.size is 128 # => shift + 32 <= src.size out.append(src[shift: shift + 32]) return [m2_expr.ExprAff(dst, m2_expr.ExprCompose(*out))], []
def pshufhw(
_, instr, dst, src, imm)
def pshufhw(_, instr, dst, src, imm): control = int(imm) out = [src[:64]] for i in xrange(4): shift = ((control >> (i * 2)) & 3) * 16 out.append(src[shift + 64: shift + 16 + 64]) return [m2_expr.ExprAff(dst, m2_expr.ExprCompose(*out))], []
def pshuflw(
_, instr, dst, src, imm)
def pshuflw(_, instr, dst, src, imm): control = int(imm) out = [] for i in xrange(4): shift = ((control >> (i * 2)) & 3) * 16 out.append(src[shift: shift + 16]) out.append(src[64:]) return [m2_expr.ExprAff(dst, m2_expr.ExprCompose(*out))], []
def pslld(
ir, instr, dst, src)
def pslld(ir, instr, dst, src): return ps_rl_ll(ir, instr, dst, src, "<<", 32)
def pslldq(
_, instr, dst, src)
def pslldq(_, instr, dst, src): assert src.is_int() e = [] count = int(src) if count > 15: return [m2_expr.ExprAff(dst, m2_expr.ExprInt(0, dst.size))], [] else: return [m2_expr.ExprAff(dst, dst << m2_expr.ExprInt(8 * count, dst.size))], []
def psllq(
ir, instr, dst, src)
def psllq(ir, instr, dst, src): return ps_rl_ll(ir, instr, dst, src, "<<", 64)
def psllw(
ir, instr, dst, src)
def psllw(ir, instr, dst, src): return ps_rl_ll(ir, instr, dst, src, "<<", 16)
def psrad(
ir, instr, dst, src)
def psrad(ir, instr, dst, src): return ps_rl_ll(ir, instr, dst, src, "a>>", 32)
def psraw(
ir, instr, dst, src)
def psraw(ir, instr, dst, src): return ps_rl_ll(ir, instr, dst, src, "a>>", 16)
def psrld(
ir, instr, dst, src)
def psrld(ir, instr, dst, src): return ps_rl_ll(ir, instr, dst, src, ">>", 32)
def psrldq(
_, instr, dst, src)
def psrldq(_, instr, dst, src): assert src.is_int() e = [] count = int(src) if count > 15: return [m2_expr.ExprAff(dst, m2_expr.ExprInt(0, dst.size))], [] else: return [m2_expr.ExprAff(dst, dst >> m2_expr.ExprInt(8 * count, dst.size))], []
def psrlq(
ir, instr, dst, src)
def psrlq(ir, instr, dst, src): return ps_rl_ll(ir, instr, dst, src, ">>", 64)
def psrlw(
ir, instr, dst, src)
def psrlw(ir, instr, dst, src): return ps_rl_ll(ir, instr, dst, src, ">>", 16)
def psubb(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def psubd(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def psubq(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def psubsb(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def psubsw(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def psubusb(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def psubusw(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def psubw(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def punpck(
_, instr, dst, src, size, off)
def punpck(_, instr, dst, src, size, off): e = [] slices = [] for i in xrange(dst.size / (2 * size)): slices.append(dst[size * i + off: size * i + off + size]) slices.append(src[size * i + off: size * i + off + size]) e.append(m2_expr.ExprAff(dst, m2_expr.ExprCompose(*slices))) return e, []
def punpckhbw(
ir, instr, dst, src)
def punpckhbw(ir, instr, dst, src): return punpck(ir, instr, dst, src, 8, dst.size / 2)
def punpckhdq(
ir, instr, dst, src)
def punpckhdq(ir, instr, dst, src): return punpck(ir, instr, dst, src, 32, dst.size / 2)
def punpckhqdq(
ir, instr, dst, src)
def punpckhqdq(ir, instr, dst, src): return punpck(ir, instr, dst, src, 64, dst.size / 2)
def punpckhwd(
ir, instr, dst, src)
def punpckhwd(ir, instr, dst, src): return punpck(ir, instr, dst, src, 16, dst.size / 2)
def punpcklbw(
ir, instr, dst, src)
def punpcklbw(ir, instr, dst, src): return punpck(ir, instr, dst, src, 8, 0)
def punpckldq(
ir, instr, dst, src)
def punpckldq(ir, instr, dst, src): return punpck(ir, instr, dst, src, 32, 0)
def punpcklqdq(
ir, instr, dst, src)
def punpcklqdq(ir, instr, dst, src): return punpck(ir, instr, dst, src, 64, 0)
def punpcklwd(
ir, instr, dst, src)
def punpcklwd(ir, instr, dst, src): return punpck(ir, instr, dst, src, 16, 0)
def push(
ir, instr, src)
def push(ir, instr, src): return push_gen(ir, instr, src, instr.mode)
def push_gen(
ir, instr, src, size)
def push_gen(ir, instr, src, size): e = [] if not size in [16, 32, 64]: raise ValueError('bad size stacker!') if src.size < size: src = src.zeroExtend(size) off_size = src.size sp = mRSP[instr.mode] new_sp = sp - m2_expr.ExprInt(off_size / 8, sp.size) e.append(m2_expr.ExprAff(sp, new_sp)) if ir.do_stk_segm: new_sp = ir.gen_segm_expr(SS, new_sp) e.append(m2_expr.ExprAff(ir.ExprMem(new_sp, off_size), src)) return e, []
def pusha(
ir, instr)
def pusha(ir, instr): return pusha_gen(ir, instr, 16)
def pusha_gen(
ir, instr, size)
def pusha_gen(ir, instr, size): e = [] cur_sp = mRSP[instr.mode] for i, reg in enumerate(pa_regs): stk_ptr = cur_sp + m2_expr.ExprInt(-(size / 8) * (i + 1), instr.mode) e.append(m2_expr.ExprAff(ir.ExprMem(stk_ptr, size), reg[size])) e.append(m2_expr.ExprAff(cur_sp, stk_ptr)) return e, []
def pushad(
ir, instr)
def pushad(ir, instr): return pusha_gen(ir, instr, 32)
def pushfd(
ir, instr)
def pushfd(ir, instr): return push(ir, instr, compose_eflag())
def pushfq(
ir, instr)
def pushfq(ir, instr): return push(ir, instr, compose_eflag().zeroExtend(64))
def pushfw(
ir, instr)
def pushfw(ir, instr): return pushw(ir, instr, compose_eflag(16))
def pushw(
ir, instr, src)
def pushw(ir, instr, src): return push_gen(ir, instr, src, 16)
def pxor(
_, instr, dst, src)
def pxor(_, instr, dst, src): e = [] result = dst ^ src e.append(m2_expr.ExprAff(dst, result)) return (e, [])
def rcl(
ir, instr, dst, src)
def rcl(ir, instr, dst, src): return rotate_with_carry_tpl(ir, instr, '<<<', dst, src)
def rcr(
ir, instr, dst, src)
def rcr(ir, instr, dst, src): return rotate_with_carry_tpl(ir, instr, '>>>', dst, src)
def rdmsr(
ir, instr)
def rdmsr(ir, instr): msr_addr = m2_expr.ExprId('MSR', 64) + m2_expr.ExprInt(8, 64) * mRCX[32].zeroExtend(64) e = [] e.append(m2_expr.ExprAff(mRAX[32], ir.ExprMem(msr_addr, 32))) e.append(m2_expr.ExprAff(mRDX[32], ir.ExprMem(msr_addr + m2_expr.ExprInt(4, 64), 32))) return e, []
def rdtsc(
_, instr)
def rdtsc(_, instr): e = [] e.append(m2_expr.ExprAff(tsc1, tsc1 + m2_expr.ExprInt(1, 32))) e.append(m2_expr.ExprAff(tsc2, tsc2 + m2_expr.ExprCond(tsc1 - tsc1.mask, m2_expr.ExprInt(0, 32), m2_expr.ExprInt(1, 32)))) e.append(m2_expr.ExprAff(mRAX[32], tsc1)) e.append(m2_expr.ExprAff(mRDX[32], tsc2)) return e, []
def ret(
ir, instr, src=None)
def ret(ir, instr, src=None): e = [] meip = mRIP[ir.IRDst.size] size, admode = instr.v_opmode(), instr.v_admode() myesp = mRSP[instr.mode][:size] if src is None: src = m2_expr.ExprInt(0, size) value = (myesp + (m2_expr.ExprInt((size / 8), size))) else: src = m2_expr.ExprInt(int(src), size) value = (myesp + (m2_expr.ExprInt((size / 8), size) + src)) e.append(m2_expr.ExprAff(myesp, value)) result = myesp if ir.do_stk_segm: result = ir.gen_segm_expr(SS, result) e.append(m2_expr.ExprAff(meip, ir.ExprMem( result, size=size).zeroExtend(size))) e.append(m2_expr.ExprAff(ir.IRDst, ir.ExprMem(result, size=size).zeroExtend(size))) return e, []
def retf(
ir, instr, src=None)
def retf(ir, instr, src=None): e = [] meip = mRIP[ir.IRDst.size] size, admode = instr.v_opmode(), instr.v_admode() if src is None: src = m2_expr.ExprInt(0, instr.mode) myesp = mRSP[instr.mode][:size] src = src.zeroExtend(size) result = myesp if ir.do_stk_segm: result = ir.gen_segm_expr(SS, result) e.append(m2_expr.ExprAff(meip, ir.ExprMem( result, size=size).zeroExtend(size))) e.append(m2_expr.ExprAff(ir.IRDst, ir.ExprMem(result, size=size).zeroExtend(size))) # e.append(m2_expr.ExprAff(meip, ir.ExprMem(c, size = s))) result = myesp + m2_expr.ExprInt(size / 8, size) if ir.do_stk_segm: result = ir.gen_segm_expr(SS, result) e.append(m2_expr.ExprAff(CS, ir.ExprMem(result, size=16))) value = myesp + (m2_expr.ExprInt((2 * size) / 8, size) + src) e.append(m2_expr.ExprAff(myesp, value)) return e, []
def rotate_with_carry_tpl(
ir, instr, op, dst, src)
def rotate_with_carry_tpl(ir, instr, op, dst, src): # Compute results shifter = get_shift(dst, src).zeroExtend(dst.size + 1) result = m2_expr.ExprOp(op, m2_expr.ExprCompose(dst, cf), shifter) new_cf = result[dst.size:dst.size +1] new_dst = result[:dst.size] result_trunc = result[:dst.size] if op == '<<<': of_value = result_trunc.msb() ^ new_cf else: of_value = (dst ^ result_trunc).msb() # OF is defined only for @b == 1 new_of = m2_expr.ExprCond(src - m2_expr.ExprInt(1, size=src.size), m2_expr.ExprInt(0, size=of.size), of_value) # Build basic blocks e_do = [m2_expr.ExprAff(cf, new_cf), m2_expr.ExprAff(of, new_of), m2_expr.ExprAff(dst, new_dst) ] # Don't generate conditional shifter on constant if isinstance(shifter, m2_expr.ExprInt): if int(shifter) != 0: return (e_do, []) else: return ([], []) e = [] loc_do, loc_do_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) loc_skip = ir.get_next_loc_key(instr) loc_skip_expr = m2_expr.ExprLoc(loc_skip, ir.IRDst.size) e_do.append(m2_expr.ExprAff(ir.IRDst, loc_skip_expr)) e.append(m2_expr.ExprAff( ir.IRDst, m2_expr.ExprCond(shifter, loc_do_expr, loc_skip_expr))) return (e, [IRBlock(loc_do, [AssignBlock(e_do, instr)])])
def sahf(
_, instr)
def sahf(_, instr): tmp = mRAX[instr.mode][8:16] e = [] e.append(m2_expr.ExprAff(cf, tmp[0:1])) e.append(m2_expr.ExprAff(pf, tmp[2:3])) e.append(m2_expr.ExprAff(af, tmp[4:5])) e.append(m2_expr.ExprAff(zf, tmp[6:7])) e.append(m2_expr.ExprAff(nf, tmp[7:8])) return e, []
def sar(
ir, instr, dst, src)
def sar(ir, instr, dst, src): # Fixup OF, always cleared if src != 0 i0 = m2_expr.ExprInt(0, size=of.size) return _shift_tpl("a>>", ir, instr, dst, src, custom_of=i0)
def sbb(
_, instr, dst, src)
def sbb(_, instr, dst, src): e = [] arg1 = dst arg2 = src result = arg1 - (arg2 + cf.zeroExtend(src.size)) e += update_flag_arith_subwc_znp(arg1, arg2, cf) e += update_flag_af(arg1, arg2, result) e += update_flag_arith_subwc_co(arg1, arg2, cf) e.append(m2_expr.ExprAff(dst, result)) return e, []
def scas(
ir, instr, size)
def scas(ir, instr, size): loc_df_0, loc_df_0_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) loc_df_1, loc_df_1_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) loc_next_expr = m2_expr.ExprLoc(ir.get_next_loc_key(instr), ir.IRDst.size) src = mRDI[instr.mode][:instr.v_admode()] if ir.do_str_segm: if instr.additional_info.g2.value: raise NotImplementedError("add segm support") src_sgm = ir.gen_segm_expr(ES, src) else: src_sgm = src offset = m2_expr.ExprInt(size / 8, src.size) e, extra = l_cmp(ir, instr, mRAX[instr.mode][:size], ir.ExprMem(src_sgm, size)) e0 = [] e0.append(m2_expr.ExprAff(src, src + offset)) e0.append(m2_expr.ExprAff(ir.IRDst, loc_next_expr)) e0 = IRBlock(loc_df_0, [AssignBlock(e0, instr)]) e1 = [] e1.append(m2_expr.ExprAff(src, src - offset)) e1.append(m2_expr.ExprAff(ir.IRDst, loc_next_expr)) e1 = IRBlock(loc_df_1, [AssignBlock(e1, instr)]) e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(df, loc_df_1_expr, loc_df_0_expr))) return e, [e0, e1]
def set_float_cs_eip(
instr)
def set_float_cs_eip(instr): e = [] # XXX TODO check float updt e.append(m2_expr.ExprAff(float_eip, m2_expr.ExprInt(instr.offset, float_eip.size))) e.append(m2_expr.ExprAff(float_cs, CS)) return e
def seta(
_, instr, dst)
def seta(_, instr, dst): e = [] e.append( m2_expr.ExprAff( dst, m2_expr.ExprOp("CC_U>", cf, zf).zeroExtend(dst.size), ) ) return e, []
def setae(
_, instr, dst)
def setae(_, instr, dst): e = [] e.append( m2_expr.ExprAff( dst, m2_expr.ExprOp("CC_U>=", cf).zeroExtend(dst.size), ) ) return e, []
def setalc(
_, instr)
def setalc(_, instr): dst = mRAX[instr.mode][0:8] e = [] e.append( m2_expr.ExprAff(dst, m2_expr.ExprCond(cf, m2_expr.ExprInt(0xff, dst.size), m2_expr.ExprInt(0, dst.size)))) return e, []
def setb(
_, instr, dst)
def setb(_, instr, dst): e = [] e.append( m2_expr.ExprAff( dst, m2_expr.ExprOp("CC_U<", cf).zeroExtend(dst.size), ) ) return e, []
def setbe(
_, instr, dst)
def setbe(_, instr, dst): e = [] e.append( m2_expr.ExprAff( dst, m2_expr.ExprOp("CC_U<=", cf, zf).zeroExtend(dst.size), ) ) return e, []
def sete(
_, instr, dst)
def sete(_, instr, dst): e = [] e.append( m2_expr.ExprAff( dst, m2_expr.ExprOp("CC_EQ", zf).zeroExtend(dst.size), ) ) return e, []
def setg(
_, instr, dst)
def setg(_, instr, dst): e = [] e.append( m2_expr.ExprAff( dst, m2_expr.ExprOp("CC_S>", nf, of, zf).zeroExtend(dst.size), ) ) return e, []
def setge(
_, instr, dst)
def setge(_, instr, dst): e = [] e.append( m2_expr.ExprAff( dst, m2_expr.ExprOp("CC_S>=", nf, of).zeroExtend(dst.size), ) ) return e, []
def setl(
_, instr, dst)
def setl(_, instr, dst): e = [] e.append( m2_expr.ExprAff( dst, m2_expr.ExprOp("CC_S<", nf, of).zeroExtend(dst.size), ) ) return e, []
def setle(
_, instr, dst)
def setle(_, instr, dst): e = [] e.append( m2_expr.ExprAff( dst, m2_expr.ExprOp("CC_S<=", nf, of, zf).zeroExtend(dst.size), ) ) return e, []
def setna(
_, instr, dst)
def setna(_, instr, dst): e = [] e.append( m2_expr.ExprAff( dst, m2_expr.ExprOp("CC_U<=", cf, zf).zeroExtend(dst.size), ) ) return e, []
def setnb(
_, instr, dst)
def setnb(_, instr, dst): e = [] e.append( m2_expr.ExprAff( dst, m2_expr.ExprOp("CC_U>=", cf).zeroExtend(dst.size), ) ) return e, []
def setnbe(
_, instr, dst)
def setnbe(_, instr, dst): e = [] e.append( m2_expr.ExprAff( dst, m2_expr.ExprOp("CC_U>", cf, zf).zeroExtend(dst.size), ) ) return e, []
def setno(
_, instr, dst)
def setno(_, instr, dst): e = [] e.append( m2_expr.ExprAff( dst, m2_expr.ExprCond( of, m2_expr.ExprInt(0, dst.size), m2_expr.ExprInt(1, dst.size) ) ) ) return e, []
def setnp(
_, instr, dst)
def setnp(_, instr, dst): e = [] e.append( m2_expr.ExprAff( dst, m2_expr.ExprCond( pf, m2_expr.ExprInt(0, dst.size), m2_expr.ExprInt(1, dst.size) ) ) ) return e, []
def setns(
_, instr, dst)
def setns(_, instr, dst): e = [] e.append( m2_expr.ExprAff( dst, m2_expr.ExprOp("CC_NEG", ~nf).zeroExtend(dst.size), ) ) return e, []
def setnz(
_, instr, dst)
def setnz(_, instr, dst): e = [] e.append( m2_expr.ExprAff( dst, m2_expr.ExprOp("CC_EQ", ~zf).zeroExtend(dst.size), ) ) return e, []
def seto(
_, instr, dst)
def seto(_, instr, dst): e = [] e.append( m2_expr.ExprAff( dst, of.zeroExtend(dst.size) ) ) return e, []
def setp(
_, instr, dst)
def setp(_, instr, dst): e = [] e.append( m2_expr.ExprAff( dst, pf.zeroExtend(dst.size) ) ) return e, []
def sets(
_, instr, dst)
def sets(_, instr, dst): e = [] e.append( m2_expr.ExprAff( dst, m2_expr.ExprOp("CC_NEG", nf).zeroExtend(dst.size), ) ) return e, []
def sfence(
_, instr, src=None)
def sfence(_, instr, src=None): # see 3-356 on this documentation # https://www-ssl.intel.com/content/dam/www/public/us/en/documents/manuals/64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf return [], []
def shl(
ir, instr, dst, src)
def shl(ir, instr, dst, src): return _shift_tpl("<<", ir, instr, dst, src, left=True)
def shld(
ir, instr, dst, src1, src2)
def shld(ir, instr, dst, src1, src2): return _shift_tpl("<<<", ir, instr, dst, src1, src2, ">>>", left=True)
def shr(
ir, instr, dst, src)
def shr(ir, instr, dst, src): return _shift_tpl(">>", ir, instr, dst, src, custom_of=dst.msb())
def shrd(
ir, instr, dst, src1, src2)
def shrd(ir, instr, dst, src1, src2): return _shift_tpl(">>>", ir, instr, dst, src1, src2, "<<<")
def shufpd(
ir, instr, dst, src, imm8)
def shufpd(ir, instr, dst, src, imm8): out = [] control = int(imm8) out.append(dst[64:] if control & 1 else dst[:64]) out.append(src[64:] if control & 2 else src[:64]) return [m2_expr.ExprAff(dst, m2_expr.ExprCompose(*out))], []
def shufps(
ir, instr, dst, src, imm8)
def shufps(ir, instr, dst, src, imm8): out = [] control = int(imm8) for i in xrange(4): if i < 2: source = dst else: source = src out.append(_select4(source, (control >> (i * 2)) & 3)) return [m2_expr.ExprAff(dst, m2_expr.ExprCompose(*out))], []
def sidt(
ir, instr, dst)
def sidt(ir, instr, dst): e = [] if not isinstance(dst, m2_expr.ExprMem) or dst.size != 32: raise ValueError('not exprmem 32bit instance!!') ptr = dst.arg LOG_X86_SEM.warning("DEFAULT SIDT ADDRESS %s!!", str(dst)) e.append(m2_expr.ExprAff(ir.ExprMem(ptr, 32), m2_expr.ExprInt(0xe40007ff, 32))) e.append( m2_expr.ExprAff(ir.ExprMem(ptr + m2_expr.ExprInt(4, ptr.size), 16), m2_expr.ExprInt(0x8245, 16))) return e, []
def sldt(
_, instr, dst)
def sldt(_, instr, dst): LOG_X86_SEM.warning("DEFAULT SLDT ADDRESS %s!!", str(dst)) e = [m2_expr.ExprAff(dst, m2_expr.ExprInt(0, dst.size))] return e, []
def smsw(
ir, instr, dst)
def smsw(ir, instr, dst): e = [] LOG_X86_SEM.warning("DEFAULT SMSW %s!!", str(dst)) e.append(m2_expr.ExprAff(dst, m2_expr.ExprInt(0x80050033, 32)[:dst.size])) return e, []
def sqrt_gen(
_, instr, dst, src, size)
def sqrt_gen(_, instr, dst, src, size): e = [] out = [] for i in xrange(src.size / size): out.append(m2_expr.ExprOp('fsqrt', src[i * size: (i + 1) * size])) src = m2_expr.ExprCompose(*out) e.append(m2_expr.ExprAff(dst, src)) return e, []
def sqrtpd(
ir, instr, dst, src)
def sqrtpd(ir, instr, dst, src): return sqrt_gen(ir, instr, dst, src, 64)
def sqrtps(
ir, instr, dst, src)
def sqrtps(ir, instr, dst, src): return sqrt_gen(ir, instr, dst, src, 32)
def sqrtsd(
_, instr, dst, src)
def sqrtsd(_, instr, dst, src): e = [] e.append(m2_expr.ExprAff(dst[:64], m2_expr.ExprOp('fsqrt', src[:64]))) return e, []
def sqrtss(
_, instr, dst, src)
def sqrtss(_, instr, dst, src): e = [] e.append(m2_expr.ExprAff(dst[:32], m2_expr.ExprOp('fsqrt', src[:32]))) return e, []
def stc(
_, instr)
def stc(_, instr): e = [m2_expr.ExprAff(cf, m2_expr.ExprInt(1, cf.size))] return e, []
def std(
_, instr)
def std(_, instr): e = [m2_expr.ExprAff(df, m2_expr.ExprInt(1, df.size))] return e, []
def sti(
_, instr)
def sti(_, instr): e = [m2_expr.ExprAff(exception_flags, m2_expr.ExprInt(EXCEPT_PRIV_INSN, 32))] return e, []
def stmxcsr(
ir, instr, dst)
def stmxcsr(ir, instr, dst): return [m2_expr.ExprAff(dst, m2_expr.ExprInt(STMXCSR_VALUE, dst.size))], []
def stos(
ir, instr, size)
def stos(ir, instr, size): loc_df_0, loc_df_0_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) loc_df_1, loc_df_1_expr = ir.gen_loc_key_and_expr(ir.IRDst.size) loc_next_expr = m2_expr.ExprLoc(ir.get_next_loc_key(instr), ir.IRDst.size) addr_o = mRDI[instr.mode][:instr.v_admode()] addr = addr_o addr_p = addr + m2_expr.ExprInt(size / 8, addr.size) addr_m = addr - m2_expr.ExprInt(size / 8, addr.size) if ir.do_str_segm: mss = ES if instr.additional_info.g2.value: raise NotImplementedError("add segm support") addr = ir.gen_segm_expr(mss, addr) b = mRAX[instr.mode][:size] e0 = [] e0.append(m2_expr.ExprAff(addr_o, addr_p)) e0.append(m2_expr.ExprAff(ir.IRDst, loc_next_expr)) e0 = IRBlock(loc_df_0, [AssignBlock(e0, instr)]) e1 = [] e1.append(m2_expr.ExprAff(addr_o, addr_m)) e1.append(m2_expr.ExprAff(ir.IRDst, loc_next_expr)) e1 = IRBlock(loc_df_1, [AssignBlock(e1, instr)]) e = [] e.append(m2_expr.ExprAff(ir.ExprMem(addr, size), b)) e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(df, loc_df_1_expr, loc_df_0_expr))) return e, [e0, e1]
def sub(
_, instr, dst, src)
def sub(_, instr, dst, src): e = [] arg1, arg2 = dst, src result = dst - src e += update_flag_arith_sub_znp(arg1, arg2) e += update_flag_arith_sub_co(arg1, arg2, result) e += update_flag_af(dst, src, result) e.append(m2_expr.ExprAff(dst, result)) return e, []
def subpd(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def subps(
ir, instr, dst, src)
def vec_instr(ir, instr, dst, src): e = [] if isinstance(src, m2_expr.ExprMem): src = ir.ExprMem(src.arg, dst.size) reg_size = dst.size e.append(m2_expr.ExprAff(dst, sem(op, elt_size, reg_size, dst, src, apply_on_output))) return e, []
def subsd(
ir, instr, dst, src)
def vec_op_clip_instr(ir, instr, dst, src): if op == '-': result = dst[:size] - src[:size] else: result = m2_expr.ExprOp(op, dst[:size], src[:size]) if callback is not None: result = callback(result) return [m2_expr.ExprAff(dst[:size], result)], []
def subss(
ir, instr, dst, src)
def vec_op_clip_instr(ir, instr, dst, src): if op == '-': result = dst[:size] - src[:size] else: result = m2_expr.ExprOp(op, dst[:size], src[:size]) if callback is not None: result = callback(result) return [m2_expr.ExprAff(dst[:size], result)], []
def ucomisd(
_, instr, src1, src2)
def ucomisd(_, instr, src1, src2): e = [] e.append(m2_expr.ExprAff(zf, m2_expr.ExprOp( 'ucomisd_zf', src1[:64], src2[:64]))) e.append(m2_expr.ExprAff(pf, m2_expr.ExprOp( 'ucomisd_pf', src1[:64], src2[:64]))) e.append(m2_expr.ExprAff(cf, m2_expr.ExprOp( 'ucomisd_cf', src1[:64], src2[:64]))) e.append(m2_expr.ExprAff(of, m2_expr.ExprInt(0, 1))) e.append(m2_expr.ExprAff(af, m2_expr.ExprInt(0, 1))) e.append(m2_expr.ExprAff(nf, m2_expr.ExprInt(0, 1))) return e, []
def ucomiss(
_, instr, src1, src2)
def ucomiss(_, instr, src1, src2): e = [] e.append(m2_expr.ExprAff(zf, m2_expr.ExprOp( 'ucomiss_zf', src1[:32], src2[:32]))) e.append(m2_expr.ExprAff(pf, m2_expr.ExprOp( 'ucomiss_pf', src1[:32], src2[:32]))) e.append(m2_expr.ExprAff(cf, m2_expr.ExprOp( 'ucomiss_cf', src1[:32], src2[:32]))) e.append(m2_expr.ExprAff(of, m2_expr.ExprInt(0, 1))) e.append(m2_expr.ExprAff(af, m2_expr.ExprInt(0, 1))) e.append(m2_expr.ExprAff(nf, m2_expr.ExprInt(0, 1))) return e, []
def ud2(
_, instr, src=None)
def ud2(_, instr, src=None): e = [m2_expr.ExprAff(exception_flags, m2_expr.ExprInt( EXCEPT_ILLEGAL_INSN, exception_flags.size))] return e, []
def unpckhpd(
_, instr, dst, src)
def unpckhpd(_, instr, dst, src): e = [] src = m2_expr.ExprCompose(dst[64:128], src[64:128]) e.append(m2_expr.ExprAff(dst, src)) return e, []
def unpckhps(
_, instr, dst, src)
def unpckhps(_, instr, dst, src): e = [] src = m2_expr.ExprCompose(dst[64:96], src[64:96], dst[96:128], src[96:128]) e.append(m2_expr.ExprAff(dst, src)) return e, []
def unpcklpd(
_, instr, dst, src)
def unpcklpd(_, instr, dst, src): e = [] src = m2_expr.ExprCompose(dst[0:64], src[0:64]) e.append(m2_expr.ExprAff(dst, src)) return e, []
def unpcklps(
_, instr, dst, src)
def unpcklps(_, instr, dst, src): e = [] src = m2_expr.ExprCompose(dst[0:32], src[0:32], dst[32:64], src[32:64]) e.append(m2_expr.ExprAff(dst, src)) return e, []
def update_flag_add_cf(
op1, op2, res)
Compute cf in @res = @op1 + @op2
def update_flag_add_cf(op1, op2, res): "Compute cf in @res = @op1 + @op2" #return [m2_expr.ExprAff(cf, m2_expr.ExprOp("FLAG_SUB_CF", op1, -op2))] return [m2_expr.ExprAff(cf, m2_expr.ExprOp("FLAG_ADD_CF", op1, op2))]
def update_flag_add_of(
op1, op2, res)
Compute of in @res = @op1 + @op2
def update_flag_add_of(op1, op2, res): "Compute of in @res = @op1 + @op2" return [m2_expr.ExprAff(of, m2_expr.ExprOp("FLAG_ADD_OF", op1, op2))]
def update_flag_addwc_cf(
op1, op2, op3)
Compute cf in @res = @op1 + @op2 + @op3
def update_flag_addwc_cf(op1, op2, op3): "Compute cf in @res = @op1 + @op2 + @op3" return [m2_expr.ExprAff(cf, m2_expr.ExprOp("FLAG_ADDWC_CF", op1, op2, op3))]
def update_flag_addwc_of(
op1, op2, op3)
Compute of in @res = @op1 + @op2 + @op3
def update_flag_addwc_of(op1, op2, op3): "Compute of in @res = @op1 + @op2 + @op3" return [m2_expr.ExprAff(of, m2_expr.ExprOp("FLAG_ADDWC_OF", op1, op2, op3))]
def update_flag_af(
op1, op2, res)
def update_flag_af(op1, op2, res): return [m2_expr.ExprAff(af, (op1 ^ op2 ^ res)[4:5])]
def update_flag_arith(
a)
def update_flag_arith(a): e = [] e += update_flag_znp(a) return e
def update_flag_arith_add_co(
x, y, z)
def update_flag_arith_add_co(x, y, z): e = [] e += update_flag_add_cf(x, y, z) e += update_flag_add_of(x, y, z) return e
def update_flag_arith_add_znp(
arg1, arg2)
Compute znp flags for (arg1 + arg2)
def update_flag_arith_add_znp(arg1, arg2): """ Compute znp flags for (arg1 + arg2) """ e = [] e += update_flag_zf_eq(arg1, -arg2) e += [m2_expr.ExprAff(nf, m2_expr.ExprOp("FLAG_SIGN_SUB", arg1, -arg2))] e += update_flag_pf(arg1+arg2) return e
def update_flag_arith_addwc_co(
arg1, arg2, arg3)
def update_flag_arith_addwc_co(arg1, arg2, arg3): e = [] e += update_flag_addwc_cf(arg1, arg2, arg3) e += update_flag_addwc_of(arg1, arg2, arg3) return e
def update_flag_arith_addwc_znp(
arg1, arg2, arg3)
Compute znp flags for (arg1 + arg2 + cf)
def update_flag_arith_addwc_znp(arg1, arg2, arg3): """ Compute znp flags for (arg1 + arg2 + cf) """ e = [] e += update_flag_zfaddwc_eq(arg1, arg2, arg3) e += [m2_expr.ExprAff(nf, m2_expr.ExprOp("FLAG_SIGN_ADDWC", arg1, arg2, arg3))] e += update_flag_pf(arg1+arg2+arg3.zeroExtend(arg2.size)) return e
def update_flag_arith_sub_co(
x, y, z)
def update_flag_arith_sub_co(x, y, z): e = [] e += update_flag_sub_cf(x, y, z) e += update_flag_sub_of(x, y, z) return e
def update_flag_arith_sub_znp(
arg1, arg2)
Compute znp flags for (arg1 - arg2)
def update_flag_arith_sub_znp(arg1, arg2): """ Compute znp flags for (arg1 - arg2) """ e = [] e += update_flag_zf_eq(arg1, arg2) e += [m2_expr.ExprAff(nf, m2_expr.ExprOp("FLAG_SIGN_SUB", arg1, arg2))] e += update_flag_pf(arg1 - arg2) return e
def update_flag_arith_subwc_co(
arg1, arg2, arg3)
def update_flag_arith_subwc_co(arg1, arg2, arg3): e = [] e += update_flag_subwc_cf(arg1, arg2, arg3) e += update_flag_subwc_of(arg1, arg2, arg3) return e
def update_flag_arith_subwc_znp(
arg1, arg2, arg3)
Compute znp flags for (arg1 - (arg2 + cf))
def update_flag_arith_subwc_znp(arg1, arg2, arg3): """ Compute znp flags for (arg1 - (arg2 + cf)) """ e = [] e += update_flag_zfsubwc_eq(arg1, arg2, arg3) e += [m2_expr.ExprAff(nf, m2_expr.ExprOp("FLAG_SIGN_SUBWC", arg1, arg2, arg3))] e += update_flag_pf(arg1 - (arg2+arg3.zeroExtend(arg2.size))) return e
def update_flag_nf(
arg)
def update_flag_nf(arg): return [ m2_expr.ExprAff( nf, m2_expr.ExprOp("FLAG_SIGN_SUB", arg, m2_expr.ExprInt(0, arg.size)) ) ]
def update_flag_np(
result)
def update_flag_np(result): e = [] e += update_flag_nf(result) e += update_flag_pf(result) return e
def update_flag_pf(
a)
def update_flag_pf(a): return [m2_expr.ExprAff(pf, m2_expr.ExprOp('parity', a & m2_expr.ExprInt(0xFF, a.size)))]
def update_flag_sub_cf(
op1, op2, res)
Compote CF in @res = @op1 - @op2
def update_flag_sub_cf(op1, op2, res): "Compote CF in @res = @op1 - @op2" return [m2_expr.ExprAff(cf, m2_expr.ExprOp("FLAG_SUB_CF", op1, op2))]
def update_flag_sub_of(
op1, op2, res)
Compote OF in @res = @op1 - @op2
def update_flag_sub_of(op1, op2, res): "Compote OF in @res = @op1 - @op2" return [m2_expr.ExprAff(of, m2_expr.ExprOp("FLAG_SUB_OF", op1, op2))]
def update_flag_subwc_cf(
op1, op2, op3)
Compute cf in @res = @op1 + @op2 + @op3
def update_flag_subwc_cf(op1, op2, op3): "Compute cf in @res = @op1 + @op2 + @op3" return [m2_expr.ExprAff(cf, m2_expr.ExprOp("FLAG_SUBWC_CF", op1, op2, op3))]
def update_flag_subwc_of(
op1, op2, op3)
Compute of in @res = @op1 + @op2 + @op3
def update_flag_subwc_of(op1, op2, op3): "Compute of in @res = @op1 + @op2 + @op3" return [m2_expr.ExprAff(of, m2_expr.ExprOp("FLAG_SUBWC_OF", op1, op2, op3))]
def update_flag_zf(
a)
def update_flag_zf(a): return [ m2_expr.ExprAff( zf, m2_expr.ExprCond( a, m2_expr.ExprInt(0, zf.size), m2_expr.ExprInt(1, zf.size) ) ) ]
def update_flag_zf_eq(
a, b)
def update_flag_zf_eq(a, b): return [m2_expr.ExprAff(zf, m2_expr.ExprOp("FLAG_EQ_CMP", a, b))]
def update_flag_zfaddwc_eq(
arg1, arg2, arg3)
def update_flag_zfaddwc_eq(arg1, arg2, arg3): return [m2_expr.ExprAff(zf, m2_expr.ExprOp("FLAG_EQ_ADDWC", arg1, arg2, arg3))]
def update_flag_zfsubwc_eq(
arg1, arg2, arg3)
def update_flag_zfsubwc_eq(arg1, arg2, arg3): return [m2_expr.ExprAff(zf, m2_expr.ExprOp("FLAG_EQ_SUBWC", arg1, arg2, arg3))]
def update_flag_znp(
a)
def update_flag_znp(a): e = [] e += update_flag_zf(a) e += update_flag_nf(a) e += update_flag_pf(a) return e
def vec_op_clip(
op, size, callback=None)
Generate simd operations @op: the operator @size: size of an element
def vec_op_clip(op, size, callback=None): """ Generate simd operations @op: the operator @size: size of an element """ def vec_op_clip_instr(ir, instr, dst, src): if op == '-': result = dst[:size] - src[:size] else: result = m2_expr.ExprOp(op, dst[:size], src[:size]) if callback is not None: result = callback(result) return [m2_expr.ExprAff(dst[:size], result)], [] return vec_op_clip_instr
def vec_vertical_instr(
op, elt_size, apply_on_output=<function <lambda> at 0x7f19ae00c578>)
def vec_vertical_instr(op, elt_size, apply_on_output=lambda x: x): return __vec_vertical_instr_gen(op, elt_size, vec_vertical_sem, apply_on_output)
def vec_vertical_sem(
op, elt_size, reg_size, dst, src, apply_on_output)
def vec_vertical_sem(op, elt_size, reg_size, dst, src, apply_on_output): assert reg_size % elt_size == 0 n = reg_size / elt_size if op == '-': ops = [ apply_on_output((dst[i * elt_size:(i + 1) * elt_size] - src[i * elt_size:(i + 1) * elt_size])) for i in xrange(0, n) ] else: ops = [ apply_on_output(m2_expr.ExprOp(op, dst[i * elt_size:(i + 1) * elt_size], src[i * elt_size:(i + 1) * elt_size])) for i in xrange(0, n) ] return m2_expr.ExprCompose(*ops)
def wrmsr(
ir, instr)
def wrmsr(ir, instr): msr_addr = m2_expr.ExprId('MSR', 64) + m2_expr.ExprInt(8, 64) * mRCX[32].zeroExtend(64) e = [] src = m2_expr.ExprCompose(mRAX[32], mRDX[32]) e.append(m2_expr.ExprAff(ir.ExprMem(msr_addr, 64), src)) return e, []
def xadd(
_, instr, dst, src)
def xadd(_, instr, dst, src): e = [] result = dst + src e += update_flag_arith_add_znp(dst, src) e += update_flag_arith_add_co(src, dst, result) e += update_flag_af(dst, src, result) if dst != src: e.append(m2_expr.ExprAff(src, dst)) e.append(m2_expr.ExprAff(dst, result)) return e, []
def xlat(
ir, instr)
def xlat(ir, instr): e = [] ptr = mRAX[instr.mode][0:8].zeroExtend(mRBX[instr.mode].size) src = ir.ExprMem(mRBX[instr.mode] + ptr, 8) e.append(m2_expr.ExprAff(mRAX[instr.mode][0:8], src)) return e, []
def xor(
_, instr, dst, src)
def xor(_, instr, dst, src): e = [] result = dst ^ src e += [m2_expr.ExprAff(zf, m2_expr.ExprOp('FLAG_EQ_CMP', dst, src))] e += update_flag_np(result) e += null_flag_co() e.append(m2_expr.ExprAff(dst, result)) return (e, [])
def xorps(
_, instr, dst, src)
def xorps(_, instr, dst, src): e = [] e.append(m2_expr.ExprAff(dst, m2_expr.ExprOp('^', dst, src))) return e, []
Classes
class ir_x86_16
class ir_x86_16(IntermediateRepresentation): def __init__(self, loc_db=None): IntermediateRepresentation.__init__(self, mn_x86, 16, loc_db) self.do_stk_segm = False self.do_ds_segm = False self.do_str_segm = False self.do_all_segm = False self.pc = IP self.sp = SP self.IRDst = m2_expr.ExprId('IRDst', 16) # Size of memory pointer access in IR # 16 bit mode memory accesses may be greater than 16 bits # 32 bit size may be enought self.addrsize = 32 def mod_pc(self, instr, instr_ir, extra_ir): pass def ExprMem(self, ptr, size): """Generate a memory access to @ptr The ptr is resized to a fixed size self.addrsize @ptr: Expr instance to the memory address @size: size of the memory""" return m2_expr.ExprMem(expraddr(self.addrsize, ptr), size) def gen_segm_expr(self, selector, addr): ptr = m2_expr.ExprOp( 'segm', selector, addr.zeroExtend(self.addrsize) ) return ptr def get_ir(self, instr): args = instr.args[:] args = [arg.replace_expr(float_replace) for arg in args] args = fix_mem_args_size(instr, *args) my_ss = None if self.do_ds_segm: my_ss = DS if self.do_all_segm and instr.additional_info.g2.value: my_ss = {1: CS, 2: SS, 3: DS, 4: ES, 5: FS, 6: GS}[ instr.additional_info.g2.value] if my_ss is not None: for i, a in enumerate(args): if a.is_mem() and not a.is_mem_segm(): args[i] = self.ExprMem(m2_expr.ExprOp('segm', my_ss, a.arg), a.size) if not instr.name.lower() in mnemo_func: raise NotImplementedError( "Mnemonic %s not implemented" % instr.name) instr_ir, extra_ir = mnemo_func[ instr.name.lower()](self, instr, *args) self.mod_pc(instr, instr_ir, extra_ir) instr.additional_info.except_on_instr = False if instr.additional_info.g1.value & 6 == 0 or \ not instr.name in repeat_mn: return instr_ir, extra_ir if instr.name == "MOVSD" and len(instr.args) == 2: return instr_ir, extra_ir instr.additional_info.except_on_instr = True # get instruction size s = {"B": 8, "W": 16, "D": 32, 'Q': 64}[instr.name[-1]] size = instr.v_opmode() admode = instr.v_admode() c_reg = mRCX[instr.mode][:admode] out_ir = [] zf_val = None # set if zf is tested (cmps, scas) for e in instr_ir: # +[updt_c]: if e.dst == zf: zf_val = e.src cond_dec = m2_expr.ExprCond(c_reg - m2_expr.ExprInt(1, c_reg.size), m2_expr.ExprInt(0, 1), m2_expr.ExprInt(1, 1)) # end condition if zf_val is None: c_cond = cond_dec elif instr.additional_info.g1.value & 2: # REPNE c_cond = cond_dec | zf elif instr.additional_info.g1.value & 4: # REP c_cond = cond_dec | (zf ^ m2_expr.ExprInt(1, 1)) # gen while loc_do, loc_do_expr = self.gen_loc_key_and_expr(self.IRDst.size) loc_end, loc_end_expr = self.gen_loc_key_and_expr(self.IRDst.size) loc_skip = self.get_next_loc_key(instr) loc_skip_expr = m2_expr.ExprLoc(loc_skip, self.IRDst.size) loc_next = self.get_next_loc_key(instr) loc_next_expr = m2_expr.ExprLoc(loc_next, self.IRDst.size) fix_next_loc = {loc_next_expr: loc_end_expr} new_extra_ir = [irblock.modify_exprs(mod_src=lambda expr: expr.replace_expr(fix_next_loc)) for irblock in extra_ir] cond_bloc = [] cond_bloc.append(m2_expr.ExprAff(c_reg, c_reg - m2_expr.ExprInt(1, c_reg.size))) cond_bloc.append(m2_expr.ExprAff(self.IRDst, m2_expr.ExprCond(c_cond, loc_skip_expr, loc_do_expr))) cond_bloc = IRBlock(loc_end, [AssignBlock(cond_bloc, instr)]) e_do = instr_ir c = IRBlock(loc_do, [AssignBlock(e_do, instr)]) e_n = [m2_expr.ExprAff(self.IRDst, m2_expr.ExprCond(c_reg, loc_do_expr, loc_skip_expr))] return e_n, [cond_bloc, c] + new_extra_ir def expr_fix_regs_for_mode(self, e, mode=64): return e.replace_expr(replace_regs[mode]) def expraff_fix_regs_for_mode(self, e, mode=64): dst = self.expr_fix_regs_for_mode(e.dst, mode) src = self.expr_fix_regs_for_mode(e.src, mode) return m2_expr.ExprAff(dst, src) def irbloc_fix_regs_for_mode(self, irblock, mode=64): irs = [] for assignblk in irblock: new_assignblk = dict(assignblk) for dst, src in assignblk.iteritems(): del new_assignblk[dst] # Special case for 64 bits: # If destination is a 32 bit reg, zero extend the 64 bit reg if mode == 64: if (isinstance(dst, m2_expr.ExprId) and dst.size == 32 and dst in replace_regs[64]): src = src.zeroExtend(64) dst = replace_regs[64][dst].arg dst = self.expr_fix_regs_for_mode(dst, mode) src = self.expr_fix_regs_for_mode(src, mode) new_assignblk[dst] = src irs.append(AssignBlock(new_assignblk, assignblk.instr)) return IRBlock(irblock.loc_key, irs)
Ancestors (in MRO)
- ir_x86_16
- miasm2.ir.ir.IntermediateRepresentation
- __builtin__.object
Instance variables
var IRDst
var addrsize
var do_all_segm
var do_ds_segm
var do_stk_segm
var do_str_segm
var pc
var sp
Methods
def __init__(
self, loc_db=None)
def __init__(self, loc_db=None): IntermediateRepresentation.__init__(self, mn_x86, 16, loc_db) self.do_stk_segm = False self.do_ds_segm = False self.do_str_segm = False self.do_all_segm = False self.pc = IP self.sp = SP self.IRDst = m2_expr.ExprId('IRDst', 16) # Size of memory pointer access in IR # 16 bit mode memory accesses may be greater than 16 bits # 32 bit size may be enought self.addrsize = 32
def ExprMem(
self, ptr, size)
Generate a memory access to @ptr The ptr is resized to a fixed size self.addrsize
@ptr: Expr instance to the memory address @size: size of the memory
def ExprMem(self, ptr, size): """Generate a memory access to @ptr The ptr is resized to a fixed size self.addrsize @ptr: Expr instance to the memory address @size: size of the memory""" return m2_expr.ExprMem(expraddr(self.addrsize, ptr), size)
def add_asmblock_to_ircfg(
self, block, ircfg, gen_pc_updt=False)
Add a native block to the current IR @block: native assembly block @ircfg: IRCFG instance @gen_pc_updt: insert PC update effects between instructions
def add_asmblock_to_ircfg(self, block, ircfg, gen_pc_updt=False): """ Add a native block to the current IR @block: native assembly block @ircfg: IRCFG instance @gen_pc_updt: insert PC update effects between instructions """ loc_key = block.loc_key ir_blocks_all = [] assignments = [] for instr in block.lines: if loc_key is None: assignments = [] loc_key = self.get_loc_key_for_instr(instr) split = self.add_instr_to_current_state( instr, block, assignments, ir_blocks_all, gen_pc_updt ) if split: ir_blocks_all.append(IRBlock(loc_key, assignments)) loc_key = None assignments = [] if loc_key is not None: ir_blocks_all.append(IRBlock(loc_key, assignments)) new_ir_blocks_all = self.post_add_asmblock_to_ircfg(block, ircfg, ir_blocks_all) for irblock in new_ir_blocks_all: ircfg.add_irblock(irblock) return new_ir_blocks_all
def add_bloc(
self, block, gen_pc_updt=False)
DEPRECATED function Use add_block instead of add_block
def add_bloc(self, block, gen_pc_updt=False): """ DEPRECATED function Use add_block instead of add_block """ self.add_block(block, gen_pc_updt)
def add_block(
self, block, gen_pc_updt=False)
DEPRECATED function Use add_block instead of add_block
def add_block(self, block, gen_pc_updt=False): """ DEPRECATED function Use add_block instead of add_block """ warnings.warn("""DEPRECATION WARNING ircfg is now out of IntermediateRepresentation Use: ircfg = ir_arch.new_ircfg() ir_arch.add_asmblock_to_ircfg(block, ircfg) """) raise RuntimeError("API Deprecated")
def add_instr_to_current_state(
self, instr, block, assignments, ir_blocks_all, gen_pc_updt)
Add the IR effects of an instruction to the current state.
Returns a bool: True if the current assignments list must be split False in other cases.
@instr: native instruction @block: native block source @assignments: list of current AssignBlocks @ir_blocks_all: list of additional effects @gen_pc_updt: insert PC update effects between instructions
def add_instr_to_current_state(self, instr, block, assignments, ir_blocks_all, gen_pc_updt): """ Add the IR effects of an instruction to the current state. Returns a bool: * True if the current assignments list must be split * False in other cases. @instr: native instruction @block: native block source @assignments: list of current AssignBlocks @ir_blocks_all: list of additional effects @gen_pc_updt: insert PC update effects between instructions """ if gen_pc_updt is not False: self.gen_pc_update(assignments, instr) assignblk, ir_blocks_extra = self.instr2ir(instr) assignments.append(assignblk) ir_blocks_all += ir_blocks_extra if ir_blocks_extra: return True return False
def add_instr_to_ircfg(
self, instr, ircfg, loc_key=None, gen_pc_updt=False)
Add the native instruction @instr to the @ircfg @instr: instruction instance @ircfg: IRCFG instance @loc_key: loc_key instance of the instruction destination @gen_pc_updt: insert PC update effects between instructions
def add_instr_to_ircfg(self, instr, ircfg, loc_key=None, gen_pc_updt=False): """ Add the native instruction @instr to the @ircfg @instr: instruction instance @ircfg: IRCFG instance @loc_key: loc_key instance of the instruction destination @gen_pc_updt: insert PC update effects between instructions """ if loc_key is None: offset = getattr(instr, "offset", None) loc_key = self.loc_db.add_location(offset=offset) block = AsmBlock(loc_key) block.lines = [instr] self.add_asmblock_to_ircfg(block, ircfg, gen_pc_updt) return loc_key
def expr_fix_regs_for_mode(
self, e, mode=64)
def expr_fix_regs_for_mode(self, e, mode=64): return e.replace_expr(replace_regs[mode])
def expraff_fix_regs_for_mode(
self, e, mode=64)
def expraff_fix_regs_for_mode(self, e, mode=64): dst = self.expr_fix_regs_for_mode(e.dst, mode) src = self.expr_fix_regs_for_mode(e.src, mode) return m2_expr.ExprAff(dst, src)
def gen_loc_key_and_expr(
self, size)
Return a loc_key and it's corresponding ExprLoc @size: size of expression
def gen_loc_key_and_expr(self, size): """ Return a loc_key and it's corresponding ExprLoc @size: size of expression """ loc_key = self.loc_db.add_location() return loc_key, m2_expr.ExprLoc(loc_key, size)
def gen_pc_update(
self, assignments, instr)
def gen_pc_update(self, assignments, instr): offset = m2_expr.ExprInt(instr.offset, self.pc.size) assignments.append(AssignBlock({self.pc:offset}, instr))
def gen_segm_expr(
self, selector, addr)
def gen_segm_expr(self, selector, addr): ptr = m2_expr.ExprOp( 'segm', selector, addr.zeroExtend(self.addrsize) ) return ptr
def get_ir(
self, instr)
def get_ir(self, instr): args = instr.args[:] args = [arg.replace_expr(float_replace) for arg in args] args = fix_mem_args_size(instr, *args) my_ss = None if self.do_ds_segm: my_ss = DS if self.do_all_segm and instr.additional_info.g2.value: my_ss = {1: CS, 2: SS, 3: DS, 4: ES, 5: FS, 6: GS}[ instr.additional_info.g2.value] if my_ss is not None: for i, a in enumerate(args): if a.is_mem() and not a.is_mem_segm(): args[i] = self.ExprMem(m2_expr.ExprOp('segm', my_ss, a.arg), a.size) if not instr.name.lower() in mnemo_func: raise NotImplementedError( "Mnemonic %s not implemented" % instr.name) instr_ir, extra_ir = mnemo_func[ instr.name.lower()](self, instr, *args) self.mod_pc(instr, instr_ir, extra_ir) instr.additional_info.except_on_instr = False if instr.additional_info.g1.value & 6 == 0 or \ not instr.name in repeat_mn: return instr_ir, extra_ir if instr.name == "MOVSD" and len(instr.args) == 2: return instr_ir, extra_ir instr.additional_info.except_on_instr = True # get instruction size s = {"B": 8, "W": 16, "D": 32, 'Q': 64}[instr.name[-1]] size = instr.v_opmode() admode = instr.v_admode() c_reg = mRCX[instr.mode][:admode] out_ir = [] zf_val = None # set if zf is tested (cmps, scas) for e in instr_ir: # +[updt_c]: if e.dst == zf: zf_val = e.src cond_dec = m2_expr.ExprCond(c_reg - m2_expr.ExprInt(1, c_reg.size), m2_expr.ExprInt(0, 1), m2_expr.ExprInt(1, 1)) # end condition if zf_val is None: c_cond = cond_dec elif instr.additional_info.g1.value & 2: # REPNE c_cond = cond_dec | zf elif instr.additional_info.g1.value & 4: # REP c_cond = cond_dec | (zf ^ m2_expr.ExprInt(1, 1)) # gen while loc_do, loc_do_expr = self.gen_loc_key_and_expr(self.IRDst.size) loc_end, loc_end_expr = self.gen_loc_key_and_expr(self.IRDst.size) loc_skip = self.get_next_loc_key(instr) loc_skip_expr = m2_expr.ExprLoc(loc_skip, self.IRDst.size) loc_next = self.get_next_loc_key(instr) loc_next_expr = m2_expr.ExprLoc(loc_next, self.IRDst.size) fix_next_loc = {loc_next_expr: loc_end_expr} new_extra_ir = [irblock.modify_exprs(mod_src=lambda expr: expr.replace_expr(fix_next_loc)) for irblock in extra_ir] cond_bloc = [] cond_bloc.append(m2_expr.ExprAff(c_reg, c_reg - m2_expr.ExprInt(1, c_reg.size))) cond_bloc.append(m2_expr.ExprAff(self.IRDst, m2_expr.ExprCond(c_cond, loc_skip_expr, loc_do_expr))) cond_bloc = IRBlock(loc_end, [AssignBlock(cond_bloc, instr)]) e_do = instr_ir c = IRBlock(loc_do, [AssignBlock(e_do, instr)]) e_n = [m2_expr.ExprAff(self.IRDst, m2_expr.ExprCond(c_reg, loc_do_expr, loc_skip_expr))] return e_n, [cond_bloc, c] + new_extra_ir
def get_loc_key_for_instr(
self, instr)
Returns the loc_key associated to an instruction @instr: current instruction
def get_loc_key_for_instr(self, instr): """Returns the loc_key associated to an instruction @instr: current instruction""" return self.loc_db.get_or_create_offset_location(instr.offset)
def get_next_loc_key(
self, instr)
def get_next_loc_key(self, instr): loc_key = self.loc_db.get_or_create_offset_location(instr.offset + instr.l) return loc_key
def instr2ir(
self, instr)
def instr2ir(self, instr): ir_bloc_cur, extra_irblocks = self.get_ir(instr) for index, irb in enumerate(extra_irblocks): irs = [] for assignblk in irb: irs.append(AssignBlock(assignblk, instr)) extra_irblocks[index] = IRBlock(irb.loc_key, irs) assignblk = AssignBlock(ir_bloc_cur, instr) return assignblk, extra_irblocks
def irbloc_fix_regs_for_mode(
self, irblock, mode=64)
def irbloc_fix_regs_for_mode(self, irblock, mode=64): irs = [] for assignblk in irblock: new_assignblk = dict(assignblk) for dst, src in assignblk.iteritems(): del new_assignblk[dst] # Special case for 64 bits: # If destination is a 32 bit reg, zero extend the 64 bit reg if mode == 64: if (isinstance(dst, m2_expr.ExprId) and dst.size == 32 and dst in replace_regs[64]): src = src.zeroExtend(64) dst = replace_regs[64][dst].arg dst = self.expr_fix_regs_for_mode(dst, mode) src = self.expr_fix_regs_for_mode(src, mode) new_assignblk[dst] = src irs.append(AssignBlock(new_assignblk, assignblk.instr)) return IRBlock(irblock.loc_key, irs)
def is_pc_written(
self, block)
Return the first Assignblk of the @blockin which PC is written @block: IRBlock instance
def is_pc_written(self, block): """Return the first Assignblk of the @blockin which PC is written @block: IRBlock instance""" all_pc = self.arch.pc.values() for assignblk in block: if assignblk.dst in all_pc: return assignblk return None
def mod_pc(
self, instr, instr_ir, extra_ir)
def mod_pc(self, instr, instr_ir, extra_ir): pass
def new_ircfg(
self, *args, **kwargs)
Return a new instance of IRCFG
def new_ircfg(self, *args, **kwargs): """ Return a new instance of IRCFG """ return IRCFG(self.IRDst, self.loc_db, *args, **kwargs)
def new_ircfg_from_asmcfg(
self, asmcfg, *args, **kwargs)
Return a new instance of IRCFG from an @asmcfg @asmcfg: AsmCFG instance
def new_ircfg_from_asmcfg(self, asmcfg, *args, **kwargs): """ Return a new instance of IRCFG from an @asmcfg @asmcfg: AsmCFG instance """ ircfg = IRCFG(self.IRDst, self.loc_db, *args, **kwargs) for block in asmcfg.blocks: self.add_asmblock_to_ircfg(block, ircfg) return ircfg
def post_add_asmblock_to_ircfg(
self, block, ircfg, ir_blocks)
def post_add_asmblock_to_ircfg(self, block, ircfg, ir_blocks): self.set_empty_dst_to_next(block, ir_blocks) new_irblocks = [] for irblock in ir_blocks: new_irblock = self.irbloc_fix_regs_for_mode(irblock, self.attrib) ircfg.add_irblock(new_irblock) new_irblocks.append(new_irblock) return new_irblocks
def set_empty_dst_to_next(
self, block, ir_blocks)
def set_empty_dst_to_next(self, block, ir_blocks): for index, irblock in enumerate(ir_blocks): if irblock.dst is not None: continue next_loc_key = block.get_next() if next_loc_key is None: loc_key = None if block.lines: line = block.lines[-1] if line.offset is not None: loc_key = self.loc_db.get_or_create_offset_location(line.offset + line.l) if loc_key is None: loc_key = self.loc_db.add_location() block.add_cst(loc_key, AsmConstraint.c_next) else: loc_key = next_loc_key dst = m2_expr.ExprLoc(loc_key, self.pc.size) if irblock.assignblks: instr = irblock.assignblks[-1].instr else: instr = None assignblk = AssignBlock({self.IRDst: dst}, instr) ir_blocks[index] = IRBlock(irblock.loc_key, list(irblock.assignblks) + [assignblk])
class ir_x86_32
class ir_x86_32(ir_x86_16): def __init__(self, loc_db=None): IntermediateRepresentation.__init__(self, mn_x86, 32, loc_db) self.do_stk_segm = False self.do_ds_segm = False self.do_str_segm = False self.do_all_segm = False self.pc = EIP self.sp = ESP self.IRDst = m2_expr.ExprId('IRDst', 32) self.addrsize = 32
Ancestors (in MRO)
Instance variables
Methods
def __init__(
self, loc_db=None)
Inheritance:
ir_x86_16
.__init__
def __init__(self, loc_db=None): IntermediateRepresentation.__init__(self, mn_x86, 32, loc_db) self.do_stk_segm = False self.do_ds_segm = False self.do_str_segm = False self.do_all_segm = False self.pc = EIP self.sp = ESP self.IRDst = m2_expr.ExprId('IRDst', 32) self.addrsize = 32
def ExprMem(
self, ptr, size)
Inheritance:
ir_x86_16
.ExprMem
Generate a memory access to @ptr The ptr is resized to a fixed size self.addrsize
@ptr: Expr instance to the memory address @size: size of the memory
def ExprMem(self, ptr, size): """Generate a memory access to @ptr The ptr is resized to a fixed size self.addrsize @ptr: Expr instance to the memory address @size: size of the memory""" return m2_expr.ExprMem(expraddr(self.addrsize, ptr), size)
def add_asmblock_to_ircfg(
self, block, ircfg, gen_pc_updt=False)
Inheritance:
ir_x86_16
.add_asmblock_to_ircfg
Add a native block to the current IR @block: native assembly block @ircfg: IRCFG instance @gen_pc_updt: insert PC update effects between instructions
def add_asmblock_to_ircfg(self, block, ircfg, gen_pc_updt=False): """ Add a native block to the current IR @block: native assembly block @ircfg: IRCFG instance @gen_pc_updt: insert PC update effects between instructions """ loc_key = block.loc_key ir_blocks_all = [] assignments = [] for instr in block.lines: if loc_key is None: assignments = [] loc_key = self.get_loc_key_for_instr(instr) split = self.add_instr_to_current_state( instr, block, assignments, ir_blocks_all, gen_pc_updt ) if split: ir_blocks_all.append(IRBlock(loc_key, assignments)) loc_key = None assignments = [] if loc_key is not None: ir_blocks_all.append(IRBlock(loc_key, assignments)) new_ir_blocks_all = self.post_add_asmblock_to_ircfg(block, ircfg, ir_blocks_all) for irblock in new_ir_blocks_all: ircfg.add_irblock(irblock) return new_ir_blocks_all
def add_bloc(
self, block, gen_pc_updt=False)
Inheritance:
ir_x86_16
.add_bloc
DEPRECATED function Use add_block instead of add_block
def add_bloc(self, block, gen_pc_updt=False): """ DEPRECATED function Use add_block instead of add_block """ self.add_block(block, gen_pc_updt)
def add_block(
self, block, gen_pc_updt=False)
Inheritance:
ir_x86_16
.add_block
DEPRECATED function Use add_block instead of add_block
def add_block(self, block, gen_pc_updt=False): """ DEPRECATED function Use add_block instead of add_block """ warnings.warn("""DEPRECATION WARNING ircfg is now out of IntermediateRepresentation Use: ircfg = ir_arch.new_ircfg() ir_arch.add_asmblock_to_ircfg(block, ircfg) """) raise RuntimeError("API Deprecated")
def add_instr_to_current_state(
self, instr, block, assignments, ir_blocks_all, gen_pc_updt)
Inheritance:
ir_x86_16
.add_instr_to_current_state
Add the IR effects of an instruction to the current state.
Returns a bool: True if the current assignments list must be split False in other cases.
@instr: native instruction @block: native block source @assignments: list of current AssignBlocks @ir_blocks_all: list of additional effects @gen_pc_updt: insert PC update effects between instructions
def add_instr_to_current_state(self, instr, block, assignments, ir_blocks_all, gen_pc_updt): """ Add the IR effects of an instruction to the current state. Returns a bool: * True if the current assignments list must be split * False in other cases. @instr: native instruction @block: native block source @assignments: list of current AssignBlocks @ir_blocks_all: list of additional effects @gen_pc_updt: insert PC update effects between instructions """ if gen_pc_updt is not False: self.gen_pc_update(assignments, instr) assignblk, ir_blocks_extra = self.instr2ir(instr) assignments.append(assignblk) ir_blocks_all += ir_blocks_extra if ir_blocks_extra: return True return False
def add_instr_to_ircfg(
self, instr, ircfg, loc_key=None, gen_pc_updt=False)
Inheritance:
ir_x86_16
.add_instr_to_ircfg
Add the native instruction @instr to the @ircfg @instr: instruction instance @ircfg: IRCFG instance @loc_key: loc_key instance of the instruction destination @gen_pc_updt: insert PC update effects between instructions
def add_instr_to_ircfg(self, instr, ircfg, loc_key=None, gen_pc_updt=False): """ Add the native instruction @instr to the @ircfg @instr: instruction instance @ircfg: IRCFG instance @loc_key: loc_key instance of the instruction destination @gen_pc_updt: insert PC update effects between instructions """ if loc_key is None: offset = getattr(instr, "offset", None) loc_key = self.loc_db.add_location(offset=offset) block = AsmBlock(loc_key) block.lines = [instr] self.add_asmblock_to_ircfg(block, ircfg, gen_pc_updt) return loc_key
def expr_fix_regs_for_mode(
self, e, mode=64)
Inheritance:
ir_x86_16
.expr_fix_regs_for_mode
def expr_fix_regs_for_mode(self, e, mode=64): return e.replace_expr(replace_regs[mode])
def expraff_fix_regs_for_mode(
self, e, mode=64)
Inheritance:
ir_x86_16
.expraff_fix_regs_for_mode
def expraff_fix_regs_for_mode(self, e, mode=64): dst = self.expr_fix_regs_for_mode(e.dst, mode) src = self.expr_fix_regs_for_mode(e.src, mode) return m2_expr.ExprAff(dst, src)
def gen_loc_key_and_expr(
self, size)
Inheritance:
ir_x86_16
.gen_loc_key_and_expr
Return a loc_key and it's corresponding ExprLoc @size: size of expression
def gen_loc_key_and_expr(self, size): """ Return a loc_key and it's corresponding ExprLoc @size: size of expression """ loc_key = self.loc_db.add_location() return loc_key, m2_expr.ExprLoc(loc_key, size)
def gen_pc_update(
self, assignments, instr)
Inheritance:
ir_x86_16
.gen_pc_update
def gen_pc_update(self, assignments, instr): offset = m2_expr.ExprInt(instr.offset, self.pc.size) assignments.append(AssignBlock({self.pc:offset}, instr))
def gen_segm_expr(
self, selector, addr)
Inheritance:
ir_x86_16
.gen_segm_expr
def gen_segm_expr(self, selector, addr): ptr = m2_expr.ExprOp( 'segm', selector, addr.zeroExtend(self.addrsize) ) return ptr
def get_ir(
self, instr)
def get_ir(self, instr): args = instr.args[:] args = [arg.replace_expr(float_replace) for arg in args] args = fix_mem_args_size(instr, *args) my_ss = None if self.do_ds_segm: my_ss = DS if self.do_all_segm and instr.additional_info.g2.value: my_ss = {1: CS, 2: SS, 3: DS, 4: ES, 5: FS, 6: GS}[ instr.additional_info.g2.value] if my_ss is not None: for i, a in enumerate(args): if a.is_mem() and not a.is_mem_segm(): args[i] = self.ExprMem(m2_expr.ExprOp('segm', my_ss, a.arg), a.size) if not instr.name.lower() in mnemo_func: raise NotImplementedError( "Mnemonic %s not implemented" % instr.name) instr_ir, extra_ir = mnemo_func[ instr.name.lower()](self, instr, *args) self.mod_pc(instr, instr_ir, extra_ir) instr.additional_info.except_on_instr = False if instr.additional_info.g1.value & 6 == 0 or \ not instr.name in repeat_mn: return instr_ir, extra_ir if instr.name == "MOVSD" and len(instr.args) == 2: return instr_ir, extra_ir instr.additional_info.except_on_instr = True # get instruction size s = {"B": 8, "W": 16, "D": 32, 'Q': 64}[instr.name[-1]] size = instr.v_opmode() admode = instr.v_admode() c_reg = mRCX[instr.mode][:admode] out_ir = [] zf_val = None # set if zf is tested (cmps, scas) for e in instr_ir: # +[updt_c]: if e.dst == zf: zf_val = e.src cond_dec = m2_expr.ExprCond(c_reg - m2_expr.ExprInt(1, c_reg.size), m2_expr.ExprInt(0, 1), m2_expr.ExprInt(1, 1)) # end condition if zf_val is None: c_cond = cond_dec elif instr.additional_info.g1.value & 2: # REPNE c_cond = cond_dec | zf elif instr.additional_info.g1.value & 4: # REP c_cond = cond_dec | (zf ^ m2_expr.ExprInt(1, 1)) # gen while loc_do, loc_do_expr = self.gen_loc_key_and_expr(self.IRDst.size) loc_end, loc_end_expr = self.gen_loc_key_and_expr(self.IRDst.size) loc_skip = self.get_next_loc_key(instr) loc_skip_expr = m2_expr.ExprLoc(loc_skip, self.IRDst.size) loc_next = self.get_next_loc_key(instr) loc_next_expr = m2_expr.ExprLoc(loc_next, self.IRDst.size) fix_next_loc = {loc_next_expr: loc_end_expr} new_extra_ir = [irblock.modify_exprs(mod_src=lambda expr: expr.replace_expr(fix_next_loc)) for irblock in extra_ir] cond_bloc = [] cond_bloc.append(m2_expr.ExprAff(c_reg, c_reg - m2_expr.ExprInt(1, c_reg.size))) cond_bloc.append(m2_expr.ExprAff(self.IRDst, m2_expr.ExprCond(c_cond, loc_skip_expr, loc_do_expr))) cond_bloc = IRBlock(loc_end, [AssignBlock(cond_bloc, instr)]) e_do = instr_ir c = IRBlock(loc_do, [AssignBlock(e_do, instr)]) e_n = [m2_expr.ExprAff(self.IRDst, m2_expr.ExprCond(c_reg, loc_do_expr, loc_skip_expr))] return e_n, [cond_bloc, c] + new_extra_ir
def get_loc_key_for_instr(
self, instr)
Inheritance:
ir_x86_16
.get_loc_key_for_instr
Returns the loc_key associated to an instruction @instr: current instruction
def get_loc_key_for_instr(self, instr): """Returns the loc_key associated to an instruction @instr: current instruction""" return self.loc_db.get_or_create_offset_location(instr.offset)
def get_next_loc_key(
self, instr)
Inheritance:
ir_x86_16
.get_next_loc_key
def get_next_loc_key(self, instr): loc_key = self.loc_db.get_or_create_offset_location(instr.offset + instr.l) return loc_key
def instr2ir(
self, instr)
Inheritance:
ir_x86_16
.instr2ir
def instr2ir(self, instr): ir_bloc_cur, extra_irblocks = self.get_ir(instr) for index, irb in enumerate(extra_irblocks): irs = [] for assignblk in irb: irs.append(AssignBlock(assignblk, instr)) extra_irblocks[index] = IRBlock(irb.loc_key, irs) assignblk = AssignBlock(ir_bloc_cur, instr) return assignblk, extra_irblocks
def irbloc_fix_regs_for_mode(
self, irblock, mode=64)
Inheritance:
ir_x86_16
.irbloc_fix_regs_for_mode
def irbloc_fix_regs_for_mode(self, irblock, mode=64): irs = [] for assignblk in irblock: new_assignblk = dict(assignblk) for dst, src in assignblk.iteritems(): del new_assignblk[dst] # Special case for 64 bits: # If destination is a 32 bit reg, zero extend the 64 bit reg if mode == 64: if (isinstance(dst, m2_expr.ExprId) and dst.size == 32 and dst in replace_regs[64]): src = src.zeroExtend(64) dst = replace_regs[64][dst].arg dst = self.expr_fix_regs_for_mode(dst, mode) src = self.expr_fix_regs_for_mode(src, mode) new_assignblk[dst] = src irs.append(AssignBlock(new_assignblk, assignblk.instr)) return IRBlock(irblock.loc_key, irs)
def is_pc_written(
self, block)
Inheritance:
ir_x86_16
.is_pc_written
Return the first Assignblk of the @blockin which PC is written @block: IRBlock instance
def is_pc_written(self, block): """Return the first Assignblk of the @blockin which PC is written @block: IRBlock instance""" all_pc = self.arch.pc.values() for assignblk in block: if assignblk.dst in all_pc: return assignblk return None
def mod_pc(
self, instr, instr_ir, extra_ir)
def mod_pc(self, instr, instr_ir, extra_ir): pass
def new_ircfg(
self, *args, **kwargs)
Inheritance:
ir_x86_16
.new_ircfg
Return a new instance of IRCFG
def new_ircfg(self, *args, **kwargs): """ Return a new instance of IRCFG """ return IRCFG(self.IRDst, self.loc_db, *args, **kwargs)
def new_ircfg_from_asmcfg(
self, asmcfg, *args, **kwargs)
Inheritance:
ir_x86_16
.new_ircfg_from_asmcfg
Return a new instance of IRCFG from an @asmcfg @asmcfg: AsmCFG instance
def new_ircfg_from_asmcfg(self, asmcfg, *args, **kwargs): """ Return a new instance of IRCFG from an @asmcfg @asmcfg: AsmCFG instance """ ircfg = IRCFG(self.IRDst, self.loc_db, *args, **kwargs) for block in asmcfg.blocks: self.add_asmblock_to_ircfg(block, ircfg) return ircfg
def post_add_asmblock_to_ircfg(
self, block, ircfg, ir_blocks)
Inheritance:
ir_x86_16
.post_add_asmblock_to_ircfg
def post_add_asmblock_to_ircfg(self, block, ircfg, ir_blocks): self.set_empty_dst_to_next(block, ir_blocks) new_irblocks = [] for irblock in ir_blocks: new_irblock = self.irbloc_fix_regs_for_mode(irblock, self.attrib) ircfg.add_irblock(new_irblock) new_irblocks.append(new_irblock) return new_irblocks
def set_empty_dst_to_next(
self, block, ir_blocks)
Inheritance:
ir_x86_16
.set_empty_dst_to_next
def set_empty_dst_to_next(self, block, ir_blocks): for index, irblock in enumerate(ir_blocks): if irblock.dst is not None: continue next_loc_key = block.get_next() if next_loc_key is None: loc_key = None if block.lines: line = block.lines[-1] if line.offset is not None: loc_key = self.loc_db.get_or_create_offset_location(line.offset + line.l) if loc_key is None: loc_key = self.loc_db.add_location() block.add_cst(loc_key, AsmConstraint.c_next) else: loc_key = next_loc_key dst = m2_expr.ExprLoc(loc_key, self.pc.size) if irblock.assignblks: instr = irblock.assignblks[-1].instr else: instr = None assignblk = AssignBlock({self.IRDst: dst}, instr) ir_blocks[index] = IRBlock(irblock.loc_key, list(irblock.assignblks) + [assignblk])
class ir_x86_64
class ir_x86_64(ir_x86_16): def __init__(self, loc_db=None): IntermediateRepresentation.__init__(self, mn_x86, 64, loc_db) self.do_stk_segm = False self.do_ds_segm = False self.do_str_segm = False self.do_all_segm = False self.pc = RIP self.sp = RSP self.IRDst = m2_expr.ExprId('IRDst', 64) self.addrsize = 64 def mod_pc(self, instr, instr_ir, extra_ir): # fix RIP for 64 bit pc_fixed = {self.pc: m2_expr.ExprInt(instr.offset + instr.l, 64)} for i, expr in enumerate(instr_ir): dst, src = expr.dst, expr.src if dst != self.pc: dst = dst.replace_expr(pc_fixed) src = src.replace_expr(pc_fixed) instr_ir[i] = m2_expr.ExprAff(dst, src) for idx, irblock in enumerate(extra_ir): extra_ir[idx] = irblock.modify_exprs(lambda expr: expr.replace_expr(pc_fixed) \ if expr != self.pc else expr, lambda expr: expr.replace_expr(pc_fixed))
Ancestors (in MRO)
Instance variables
Methods
def __init__(
self, loc_db=None)
Inheritance:
ir_x86_16
.__init__
def __init__(self, loc_db=None): IntermediateRepresentation.__init__(self, mn_x86, 64, loc_db) self.do_stk_segm = False self.do_ds_segm = False self.do_str_segm = False self.do_all_segm = False self.pc = RIP self.sp = RSP self.IRDst = m2_expr.ExprId('IRDst', 64) self.addrsize = 64
def ExprMem(
self, ptr, size)
Inheritance:
ir_x86_16
.ExprMem
Generate a memory access to @ptr The ptr is resized to a fixed size self.addrsize
@ptr: Expr instance to the memory address @size: size of the memory
def ExprMem(self, ptr, size): """Generate a memory access to @ptr The ptr is resized to a fixed size self.addrsize @ptr: Expr instance to the memory address @size: size of the memory""" return m2_expr.ExprMem(expraddr(self.addrsize, ptr), size)
def add_asmblock_to_ircfg(
self, block, ircfg, gen_pc_updt=False)
Inheritance:
ir_x86_16
.add_asmblock_to_ircfg
Add a native block to the current IR @block: native assembly block @ircfg: IRCFG instance @gen_pc_updt: insert PC update effects between instructions
def add_asmblock_to_ircfg(self, block, ircfg, gen_pc_updt=False): """ Add a native block to the current IR @block: native assembly block @ircfg: IRCFG instance @gen_pc_updt: insert PC update effects between instructions """ loc_key = block.loc_key ir_blocks_all = [] assignments = [] for instr in block.lines: if loc_key is None: assignments = [] loc_key = self.get_loc_key_for_instr(instr) split = self.add_instr_to_current_state( instr, block, assignments, ir_blocks_all, gen_pc_updt ) if split: ir_blocks_all.append(IRBlock(loc_key, assignments)) loc_key = None assignments = [] if loc_key is not None: ir_blocks_all.append(IRBlock(loc_key, assignments)) new_ir_blocks_all = self.post_add_asmblock_to_ircfg(block, ircfg, ir_blocks_all) for irblock in new_ir_blocks_all: ircfg.add_irblock(irblock) return new_ir_blocks_all
def add_bloc(
self, block, gen_pc_updt=False)
Inheritance:
ir_x86_16
.add_bloc
DEPRECATED function Use add_block instead of add_block
def add_bloc(self, block, gen_pc_updt=False): """ DEPRECATED function Use add_block instead of add_block """ self.add_block(block, gen_pc_updt)
def add_block(
self, block, gen_pc_updt=False)
Inheritance:
ir_x86_16
.add_block
DEPRECATED function Use add_block instead of add_block
def add_block(self, block, gen_pc_updt=False): """ DEPRECATED function Use add_block instead of add_block """ warnings.warn("""DEPRECATION WARNING ircfg is now out of IntermediateRepresentation Use: ircfg = ir_arch.new_ircfg() ir_arch.add_asmblock_to_ircfg(block, ircfg) """) raise RuntimeError("API Deprecated")
def add_instr_to_current_state(
self, instr, block, assignments, ir_blocks_all, gen_pc_updt)
Inheritance:
ir_x86_16
.add_instr_to_current_state
Add the IR effects of an instruction to the current state.
Returns a bool: True if the current assignments list must be split False in other cases.
@instr: native instruction @block: native block source @assignments: list of current AssignBlocks @ir_blocks_all: list of additional effects @gen_pc_updt: insert PC update effects between instructions
def add_instr_to_current_state(self, instr, block, assignments, ir_blocks_all, gen_pc_updt): """ Add the IR effects of an instruction to the current state. Returns a bool: * True if the current assignments list must be split * False in other cases. @instr: native instruction @block: native block source @assignments: list of current AssignBlocks @ir_blocks_all: list of additional effects @gen_pc_updt: insert PC update effects between instructions """ if gen_pc_updt is not False: self.gen_pc_update(assignments, instr) assignblk, ir_blocks_extra = self.instr2ir(instr) assignments.append(assignblk) ir_blocks_all += ir_blocks_extra if ir_blocks_extra: return True return False
def add_instr_to_ircfg(
self, instr, ircfg, loc_key=None, gen_pc_updt=False)
Inheritance:
ir_x86_16
.add_instr_to_ircfg
Add the native instruction @instr to the @ircfg @instr: instruction instance @ircfg: IRCFG instance @loc_key: loc_key instance of the instruction destination @gen_pc_updt: insert PC update effects between instructions
def add_instr_to_ircfg(self, instr, ircfg, loc_key=None, gen_pc_updt=False): """ Add the native instruction @instr to the @ircfg @instr: instruction instance @ircfg: IRCFG instance @loc_key: loc_key instance of the instruction destination @gen_pc_updt: insert PC update effects between instructions """ if loc_key is None: offset = getattr(instr, "offset", None) loc_key = self.loc_db.add_location(offset=offset) block = AsmBlock(loc_key) block.lines = [instr] self.add_asmblock_to_ircfg(block, ircfg, gen_pc_updt) return loc_key
def expr_fix_regs_for_mode(
self, e, mode=64)
Inheritance:
ir_x86_16
.expr_fix_regs_for_mode
def expr_fix_regs_for_mode(self, e, mode=64): return e.replace_expr(replace_regs[mode])
def expraff_fix_regs_for_mode(
self, e, mode=64)
Inheritance:
ir_x86_16
.expraff_fix_regs_for_mode
def expraff_fix_regs_for_mode(self, e, mode=64): dst = self.expr_fix_regs_for_mode(e.dst, mode) src = self.expr_fix_regs_for_mode(e.src, mode) return m2_expr.ExprAff(dst, src)
def gen_loc_key_and_expr(
self, size)
Inheritance:
ir_x86_16
.gen_loc_key_and_expr
Return a loc_key and it's corresponding ExprLoc @size: size of expression
def gen_loc_key_and_expr(self, size): """ Return a loc_key and it's corresponding ExprLoc @size: size of expression """ loc_key = self.loc_db.add_location() return loc_key, m2_expr.ExprLoc(loc_key, size)
def gen_pc_update(
self, assignments, instr)
Inheritance:
ir_x86_16
.gen_pc_update
def gen_pc_update(self, assignments, instr): offset = m2_expr.ExprInt(instr.offset, self.pc.size) assignments.append(AssignBlock({self.pc:offset}, instr))
def gen_segm_expr(
self, selector, addr)
Inheritance:
ir_x86_16
.gen_segm_expr
def gen_segm_expr(self, selector, addr): ptr = m2_expr.ExprOp( 'segm', selector, addr.zeroExtend(self.addrsize) ) return ptr
def get_ir(
self, instr)
def get_ir(self, instr): args = instr.args[:] args = [arg.replace_expr(float_replace) for arg in args] args = fix_mem_args_size(instr, *args) my_ss = None if self.do_ds_segm: my_ss = DS if self.do_all_segm and instr.additional_info.g2.value: my_ss = {1: CS, 2: SS, 3: DS, 4: ES, 5: FS, 6: GS}[ instr.additional_info.g2.value] if my_ss is not None: for i, a in enumerate(args): if a.is_mem() and not a.is_mem_segm(): args[i] = self.ExprMem(m2_expr.ExprOp('segm', my_ss, a.arg), a.size) if not instr.name.lower() in mnemo_func: raise NotImplementedError( "Mnemonic %s not implemented" % instr.name) instr_ir, extra_ir = mnemo_func[ instr.name.lower()](self, instr, *args) self.mod_pc(instr, instr_ir, extra_ir) instr.additional_info.except_on_instr = False if instr.additional_info.g1.value & 6 == 0 or \ not instr.name in repeat_mn: return instr_ir, extra_ir if instr.name == "MOVSD" and len(instr.args) == 2: return instr_ir, extra_ir instr.additional_info.except_on_instr = True # get instruction size s = {"B": 8, "W": 16, "D": 32, 'Q': 64}[instr.name[-1]] size = instr.v_opmode() admode = instr.v_admode() c_reg = mRCX[instr.mode][:admode] out_ir = [] zf_val = None # set if zf is tested (cmps, scas) for e in instr_ir: # +[updt_c]: if e.dst == zf: zf_val = e.src cond_dec = m2_expr.ExprCond(c_reg - m2_expr.ExprInt(1, c_reg.size), m2_expr.ExprInt(0, 1), m2_expr.ExprInt(1, 1)) # end condition if zf_val is None: c_cond = cond_dec elif instr.additional_info.g1.value & 2: # REPNE c_cond = cond_dec | zf elif instr.additional_info.g1.value & 4: # REP c_cond = cond_dec | (zf ^ m2_expr.ExprInt(1, 1)) # gen while loc_do, loc_do_expr = self.gen_loc_key_and_expr(self.IRDst.size) loc_end, loc_end_expr = self.gen_loc_key_and_expr(self.IRDst.size) loc_skip = self.get_next_loc_key(instr) loc_skip_expr = m2_expr.ExprLoc(loc_skip, self.IRDst.size) loc_next = self.get_next_loc_key(instr) loc_next_expr = m2_expr.ExprLoc(loc_next, self.IRDst.size) fix_next_loc = {loc_next_expr: loc_end_expr} new_extra_ir = [irblock.modify_exprs(mod_src=lambda expr: expr.replace_expr(fix_next_loc)) for irblock in extra_ir] cond_bloc = [] cond_bloc.append(m2_expr.ExprAff(c_reg, c_reg - m2_expr.ExprInt(1, c_reg.size))) cond_bloc.append(m2_expr.ExprAff(self.IRDst, m2_expr.ExprCond(c_cond, loc_skip_expr, loc_do_expr))) cond_bloc = IRBlock(loc_end, [AssignBlock(cond_bloc, instr)]) e_do = instr_ir c = IRBlock(loc_do, [AssignBlock(e_do, instr)]) e_n = [m2_expr.ExprAff(self.IRDst, m2_expr.ExprCond(c_reg, loc_do_expr, loc_skip_expr))] return e_n, [cond_bloc, c] + new_extra_ir
def get_loc_key_for_instr(
self, instr)
Inheritance:
ir_x86_16
.get_loc_key_for_instr
Returns the loc_key associated to an instruction @instr: current instruction
def get_loc_key_for_instr(self, instr): """Returns the loc_key associated to an instruction @instr: current instruction""" return self.loc_db.get_or_create_offset_location(instr.offset)
def get_next_loc_key(
self, instr)
Inheritance:
ir_x86_16
.get_next_loc_key
def get_next_loc_key(self, instr): loc_key = self.loc_db.get_or_create_offset_location(instr.offset + instr.l) return loc_key
def instr2ir(
self, instr)
Inheritance:
ir_x86_16
.instr2ir
def instr2ir(self, instr): ir_bloc_cur, extra_irblocks = self.get_ir(instr) for index, irb in enumerate(extra_irblocks): irs = [] for assignblk in irb: irs.append(AssignBlock(assignblk, instr)) extra_irblocks[index] = IRBlock(irb.loc_key, irs) assignblk = AssignBlock(ir_bloc_cur, instr) return assignblk, extra_irblocks
def irbloc_fix_regs_for_mode(
self, irblock, mode=64)
Inheritance:
ir_x86_16
.irbloc_fix_regs_for_mode
def irbloc_fix_regs_for_mode(self, irblock, mode=64): irs = [] for assignblk in irblock: new_assignblk = dict(assignblk) for dst, src in assignblk.iteritems(): del new_assignblk[dst] # Special case for 64 bits: # If destination is a 32 bit reg, zero extend the 64 bit reg if mode == 64: if (isinstance(dst, m2_expr.ExprId) and dst.size == 32 and dst in replace_regs[64]): src = src.zeroExtend(64) dst = replace_regs[64][dst].arg dst = self.expr_fix_regs_for_mode(dst, mode) src = self.expr_fix_regs_for_mode(src, mode) new_assignblk[dst] = src irs.append(AssignBlock(new_assignblk, assignblk.instr)) return IRBlock(irblock.loc_key, irs)
def is_pc_written(
self, block)
Inheritance:
ir_x86_16
.is_pc_written
Return the first Assignblk of the @blockin which PC is written @block: IRBlock instance
def is_pc_written(self, block): """Return the first Assignblk of the @blockin which PC is written @block: IRBlock instance""" all_pc = self.arch.pc.values() for assignblk in block: if assignblk.dst in all_pc: return assignblk return None
def mod_pc(
self, instr, instr_ir, extra_ir)
def mod_pc(self, instr, instr_ir, extra_ir): # fix RIP for 64 bit pc_fixed = {self.pc: m2_expr.ExprInt(instr.offset + instr.l, 64)} for i, expr in enumerate(instr_ir): dst, src = expr.dst, expr.src if dst != self.pc: dst = dst.replace_expr(pc_fixed) src = src.replace_expr(pc_fixed) instr_ir[i] = m2_expr.ExprAff(dst, src) for idx, irblock in enumerate(extra_ir): extra_ir[idx] = irblock.modify_exprs(lambda expr: expr.replace_expr(pc_fixed) \ if expr != self.pc else expr, lambda expr: expr.replace_expr(pc_fixed))
def new_ircfg(
self, *args, **kwargs)
Inheritance:
ir_x86_16
.new_ircfg
Return a new instance of IRCFG
def new_ircfg(self, *args, **kwargs): """ Return a new instance of IRCFG """ return IRCFG(self.IRDst, self.loc_db, *args, **kwargs)
def new_ircfg_from_asmcfg(
self, asmcfg, *args, **kwargs)
Inheritance:
ir_x86_16
.new_ircfg_from_asmcfg
Return a new instance of IRCFG from an @asmcfg @asmcfg: AsmCFG instance
def new_ircfg_from_asmcfg(self, asmcfg, *args, **kwargs): """ Return a new instance of IRCFG from an @asmcfg @asmcfg: AsmCFG instance """ ircfg = IRCFG(self.IRDst, self.loc_db, *args, **kwargs) for block in asmcfg.blocks: self.add_asmblock_to_ircfg(block, ircfg) return ircfg
def post_add_asmblock_to_ircfg(
self, block, ircfg, ir_blocks)
Inheritance:
ir_x86_16
.post_add_asmblock_to_ircfg
def post_add_asmblock_to_ircfg(self, block, ircfg, ir_blocks): self.set_empty_dst_to_next(block, ir_blocks) new_irblocks = [] for irblock in ir_blocks: new_irblock = self.irbloc_fix_regs_for_mode(irblock, self.attrib) ircfg.add_irblock(new_irblock) new_irblocks.append(new_irblock) return new_irblocks
def set_empty_dst_to_next(
self, block, ir_blocks)
Inheritance:
ir_x86_16
.set_empty_dst_to_next
def set_empty_dst_to_next(self, block, ir_blocks): for index, irblock in enumerate(ir_blocks): if irblock.dst is not None: continue next_loc_key = block.get_next() if next_loc_key is None: loc_key = None if block.lines: line = block.lines[-1] if line.offset is not None: loc_key = self.loc_db.get_or_create_offset_location(line.offset + line.l) if loc_key is None: loc_key = self.loc_db.add_location() block.add_cst(loc_key, AsmConstraint.c_next) else: loc_key = next_loc_key dst = m2_expr.ExprLoc(loc_key, self.pc.size) if irblock.assignblks: instr = irblock.assignblks[-1].instr else: instr = None assignblk = AssignBlock({self.IRDst: dst}, instr) ir_blocks[index] = IRBlock(irblock.loc_key, list(irblock.assignblks) + [assignblk])