def csetm(ir, instr, arg1, arg2): e = [] cond_expr = cond2expr[arg2.name] e.append( m2_expr.ExprAff( arg1, m2_expr.ExprCond(cond_expr, m2_expr.ExprInt(-1, arg1.size), m2_expr.ExprInt(0, arg1.size)))) return e, []
def csinc(ir, instr, arg1, arg2, arg3, arg4): e = [] cond_expr = cond2expr[arg4.name] e.append( m2_expr.ExprAff( arg1, m2_expr.ExprCond(cond_expr, arg2, arg3 + m2_expr.ExprInt(1, arg3.size)))) return e, []
def csetm(ir, instr, arg1, arg2): e = [] cond_expr = cond2expr[arg2.name] e.append( m2_expr.ExprAff( arg1, m2_expr.ExprCond(cond_expr, m2_expr.ExprInt_from(arg1, -1), m2_expr.ExprInt_from(arg1, 0)))) return e, []
def expr_simp_equal(expr_simp, e): """(x - y)?(0:1) == (x == y)""" to_match = m2_expr.ExprCond(jok1 + jok2, m2_expr.ExprInt1(0), m2_expr.ExprInt1(1)) r = __MatchExprWrap(e, to_match, [jok1, jok2]) if r is False: return e return ExprOp_equal(r[jok1], expr_simp(-r[jok2]))
def bgez(ir, instr, a, b): """Branches on @b if the quantities of register @a is greater than or equal to zero""" e = [] n = m2_expr.ExprId(ir.get_next_break_label(instr)) dst_o = m2_expr.ExprCond(a.msb(), n, b) e = [m2_expr.ExprAff(PC, dst_o), m2_expr.ExprAff(ir.IRDst, dst_o) ] return e, []
def movz(ir, instr, a, b, c): lbl_do = m2_expr.ExprId(ir.gen_label(), 32) lbl_skip = m2_expr.ExprId(ir.get_next_instr(instr), 32) e_do = [] e_do.append(m2_expr.ExprAff(a, b)) e_do.append(m2_expr.ExprAff(ir.IRDst, lbl_skip)) e = [] e.append(m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(c, lbl_skip, lbl_do))) return e, [irbloc(lbl_do.name, [e_do], [])]
def apply_expr_on_state_visit_cache(self, expr, state, cache, level=0): """ Deep First evaluate nodes: 1. evaluate node's sons 2. simplify """ expr = self.expr_simp(expr) #print '\t'*level, "Eval:", expr if expr in cache: ret = cache[expr] #print "In cache!", ret elif expr.is_int(): return expr elif expr.is_id(): if isinstance(expr.name, asmblock.AsmLabel) and expr.name.offset is not None: ret = m2_expr.ExprInt(expr.name.offset, expr.size) else: ret = state.get(expr, expr) elif expr.is_mem(): ptr = self.apply_expr_on_state_visit_cache(expr.arg, state, cache, level+1) ret = m2_expr.ExprMem(ptr, expr.size) ret = self.get_mem_state(ret) assert expr.size == ret.size elif expr.is_cond(): cond = self.apply_expr_on_state_visit_cache(expr.cond, state, cache, level+1) src1 = self.apply_expr_on_state_visit_cache(expr.src1, state, cache, level+1) src2 = self.apply_expr_on_state_visit_cache(expr.src2, state, cache, level+1) ret = m2_expr.ExprCond(cond, src1, src2) elif expr.is_slice(): arg = self.apply_expr_on_state_visit_cache(expr.arg, state, cache, level+1) ret = m2_expr.ExprSlice(arg, expr.start, expr.stop) elif expr.is_op(): args = [] for oarg in expr.args: arg = self.apply_expr_on_state_visit_cache(oarg, state, cache, level+1) assert oarg.size == arg.size args.append(arg) ret = m2_expr.ExprOp(expr.op, *args) elif expr.is_compose(): args = [] for arg in expr.args: args.append(self.apply_expr_on_state_visit_cache(arg, state, cache, level+1)) ret = m2_expr.ExprCompose(*args) else: raise TypeError("Unknown expr type") #print '\t'*level, "Result", ret ret = self.expr_simp(ret) #print '\t'*level, "Result simpl", ret assert expr.size == ret.size cache[expr] = ret return ret
def ccmp(ir, instr, arg1, arg2, arg3, arg4): e = [] if (arg2.is_int): arg2 = m2_expr.ExprInt(arg2.arg.arg, arg1.size) default_nf = arg3[0:1] default_zf = arg3[1:2] default_cf = arg3[2:3] default_of = arg3[3:4] cond_expr = cond2expr[arg4.name] res = arg1 - arg2 new_nf = nf new_zf = update_flag_zf(res)[0].src new_cf = update_flag_sub_cf(arg1, arg2, res).src new_of = update_flag_sub_of(arg1, arg2, res).src e.append( m2_expr.ExprAff(nf, m2_expr.ExprCond(cond_expr, new_nf, default_nf))) e.append( m2_expr.ExprAff(zf, m2_expr.ExprCond(cond_expr, new_zf, default_zf))) e.append( m2_expr.ExprAff(cf, m2_expr.ExprCond(cond_expr, new_cf, default_cf))) e.append( m2_expr.ExprAff(of, m2_expr.ExprCond(cond_expr, new_of, default_of))) return e, []
def teq(ir, instr, arg1, arg2): e = [] 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_except = [] do_except.append( m2_expr.ExprAssign( exception_flags, m2_expr.ExprInt(EXCEPT_DIV_BY_ZERO, exception_flags.size))) do_except.append(m2_expr.ExprAssign(ir.IRDst, loc_next_expr)) blk_except = IRBlock(loc_except.index, [AssignBlock(do_except, instr)]) cond = arg1 - arg2 e = [] e.append( m2_expr.ExprAssign( ir.IRDst, m2_expr.ExprCond(cond, loc_next_expr, loc_except_expr))) return e, [blk_except]
def teq(ir, instr, arg1, arg2): e = [] lbl_except, lbl_except_expr = ir.gen_label_and_expr(ir.IRDst.size) lbl_next = ir.get_next_label(instr) lbl_next_expr = m2_expr.ExprId(lbl_next, ir.IRDst.size) 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, lbl_next_expr)) blk_except = IRBlock(lbl_except, [AssignBlock(do_except, instr)]) cond = arg1 - arg2 e = [] e.append( m2_expr.ExprAff(ir.IRDst, m2_expr.ExprCond(cond, lbl_next_expr, lbl_except_expr))) return e, [blk_except]
def to_constraint(self): cst1, cst2 = m2_expr.ExprInt(0, 1), m2_expr.ExprInt(1, 1) return m2_expr.ExprAff(cst1, m2_expr.ExprCond(self.expr, cst1, cst2))
def update_flag_zf(a): return [m2_expr.ExprAff(zf, m2_expr.ExprCond(a, m2_expr.ExprInt(0, 1), m2_expr.ExprInt(1, 1)))]
def update_flag_zf(a): return [ m2_expr.ExprAff( zf, m2_expr.ExprCond(a, m2_expr.ExprInt1(0), m2_expr.ExprInt1(1))) ]
def patch_shift_tpl(op, ir, instr, a, b, c=None, op_inv=None, left=False, custom_of=None): # assert c is not None 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(regs.cf, new_cf), m2_expr.ExprAff( regs.of, m2_expr.ExprCond(shifter - i1, m2_expr.ExprInt(0, regs.of.size), value_of)), m2_expr.ExprAff(a, res), ] e_do += update_flag_znp(res) return (e_do, [])
def remove_jmp_blocks(self): """ Remove irblock with only IRDst set, by linking it's parent destination to the block destination. """ # Find candidates jmp_blocks = set() for block in self.blocks.itervalues(): if len(block) != 1: continue assignblk = block[0] if len(assignblk) > 1: continue assert set(assignblk.keys()) == set([self.IRDst]) if len(self.graph.successors(block.loc_key)) != 1: continue if not assignblk[self.IRDst].is_loc(): continue dst = assignblk[self.IRDst].loc_key if dst == block.loc_key: # Infinite loop block continue jmp_blocks.add(block.loc_key) # Remove them, relink graph modified = False for loc_key in jmp_blocks: block = self.blocks[loc_key] dst_loc_key = block.dst parents = self.graph.predecessors(block.loc_key) for lbl in parents: parent = self.blocks.get(lbl, None) if parent is None: continue dst = parent.dst if dst.is_id(block.loc_key): dst = m2_expr.ExprLoc(dst_loc_key, dst.size) self.graph.discard_edge(lbl, block.loc_key) self.graph.discard_edge(block.loc_key, dst_loc_key) self.graph.add_uniq_edge(lbl, dst_loc_key) modified = True elif dst.is_cond(): src1, src2 = dst.src1, dst.src2 if src1.is_id(block.loc_key): dst = m2_expr.ExprCond(dst.cond, m2_expr.ExprLoc(dst_loc_key, dst.size), dst.src2) self.graph.discard_edge(lbl, block.loc_key) self.graph.discard_edge(block.loc_key, dst_loc_key) self.graph.add_uniq_edge(lbl, dst_loc_key) modified = True if src2.is_id(block.loc_key): dst = m2_expr.ExprCond(dst.cond, dst.src1, m2_expr.ExprLoc(dst_loc_key, dst.size)) self.graph.discard_edge(lbl, block.loc_key) self.graph.discard_edge(block.loc_key, dst_loc_key) self.graph.add_uniq_edge(lbl, dst_loc_key) modified = True if dst.src1 == dst.src2: dst = dst.src1 else: continue new_parent = parent.set_dst(dst) self.blocks[parent.loc_key] = new_parent # Remove unlinked useless nodes for loc_key in jmp_blocks: if (len(self.graph.predecessors(loc_key)) == 0 and len(self.graph.successors(loc_key)) == 0): self.graph.del_node(loc_key) del self.blocks[loc_key] return modified
def remove_jmp_blocks(self): """ Remove irblock with only IRDst set, by linking it's parent destination to the block destination. """ # Find candidates jmp_blocks = set() for block in self.blocks.itervalues(): if len(block.irs) != 1: continue assignblk = block.irs[0] if len(assignblk) > 1: continue assert set(assignblk.keys()) == set([self.IRDst]) if len(self.graph.successors(block.label)) != 1: continue if not expr_is_label(assignblk[self.IRDst]): continue jmp_blocks.add(block) # Remove them, relink graph modified = False for block in jmp_blocks: dst_label = block.dst.name parents = self.graph.predecessors(block.label) for lbl in parents: parent = self.blocks.get(lbl, None) if parent is None: continue dst = parent.dst if dst.is_id(block.label): dst = m2_expr.ExprId(dst_label, dst.size) self.graph.discard_edge(lbl, block.label) self.graph.discard_edge(block.label, dst_label) self.graph.add_uniq_edge(lbl, dst_label) modified = True elif dst.is_cond(): src1, src2 = dst.src1, dst.src2 if src1.is_id(block.label): dst = m2_expr.ExprCond( dst.cond, m2_expr.ExprId(dst_label, dst.size), dst.src2) self.graph.discard_edge(lbl, block.label) self.graph.discard_edge(block.label, dst_label) self.graph.add_uniq_edge(lbl, dst_label) modified = True if src2.is_id(block.label): dst = m2_expr.ExprCond( dst.cond, dst.src1, m2_expr.ExprId(dst_label, dst.size)) self.graph.discard_edge(lbl, block.label) self.graph.discard_edge(block.label, dst_label) self.graph.add_uniq_edge(lbl, dst_label) modified = True if dst.src1 == dst.src2: dst = src1 else: continue parent.dst = dst # Remove unlinked useless nodes for block in jmp_blocks: if (len(self.graph.predecessors(block.label)) == 0 and len(self.graph.successors(block.label)) == 0): self.graph.del_node(block.label) return modified
def csneg(ir, instr, arg1, arg2, arg3, arg4): e = [] cond_expr = cond2expr[arg4.name] e.append(m2_expr.ExprAff(arg1, m2_expr.ExprCond(cond_expr, arg2, -arg3))) return e, []