def simp_cond_int(expr_simp, expr):
    if (expr.cond.is_op(TOK_EQUAL) and expr.cond.args[1].is_int()
            and expr.cond.args[0].is_compose()
            and len(expr.cond.args[0].args) == 2
            and expr.cond.args[0].args[1].is_int(0)):
        # ({X, 0} == int) => X == int[:]
        src = expr.cond.args[0].args[0]
        int_val = int(expr.cond.args[1])
        new_int = ExprInt(int_val, src.size)
        expr = expr_simp(
            ExprCond(ExprOp(TOK_EQUAL, src, new_int), expr.src1, expr.src2))
    elif (expr.cond.is_op() and expr.cond.op in [
            TOK_EQUAL, TOK_INF_SIGNED, TOK_INF_EQUAL_SIGNED, TOK_INF_UNSIGNED,
            TOK_INF_EQUAL_UNSIGNED
    ] and expr.cond.args[1].is_int() and expr.cond.args[0].is_op("+")
          and expr.cond.args[0].args[-1].is_int()):
        # X + int1 == int2 => X == int2-int1
        left, right = expr.cond.args
        left, int_diff = left.args[:-1], left.args[-1]
        if len(left) == 1:
            left = left[0]
        else:
            left = ExprOp('+', *left)
        new_int = expr_simp(right - int_diff)
        expr = expr_simp(
            ExprCond(ExprOp(expr.cond.op, left, new_int), expr.src1,
                     expr.src2))
    return expr
Beispiel #2
0
def simp_cond(_, expr):
    """
    Common simplifications on ExprCond.
    Eval exprcond src1/src2 with satifiable/unsatisfiable condition propagation
    """
    if (not expr.cond.is_int()) and expr.cond.size == 1:
        src1 = expr.src1.replace_expr({expr.cond: ExprInt(1, 1)})
        src2 = expr.src2.replace_expr({expr.cond: ExprInt(0, 1)})
        if src1 != expr.src1 or src2 != expr.src2:
            return ExprCond(expr.cond, src1, src2)

    # -A ? B:C => A ? B:C
    if expr.cond.is_op('-') and len(expr.cond.args) == 1:
        expr = ExprCond(expr.cond.args[0], expr.src1, expr.src2)
    # a?x:x
    elif expr.src1 == expr.src2:
        expr = expr.src1
    # int ? A:B => A or B
    elif expr.cond.is_int():
        if expr.cond.arg == 0:
            expr = expr.src2
        else:
            expr = expr.src1
    # a?(a?b:c):x => a?b:x
    elif expr.src1.is_cond() and expr.cond == expr.src1.cond:
        expr = ExprCond(expr.cond, expr.src1.src1, expr.src2)
    # a?x:(a?b:c) => a?x:c
    elif expr.src2.is_cond() and expr.cond == expr.src2.cond:
        expr = ExprCond(expr.cond, expr.src1, expr.src2.src2)
    # a|int ? b:c => b with int != 0
    elif (expr.cond.is_op('|') and
          expr.cond.args[1].is_int() and
          expr.cond.args[1].arg != 0):
        return expr.src1

    # (C?int1:int2)?(A:B) =>
    elif (expr.cond.is_cond() and
          expr.cond.src1.is_int() and
          expr.cond.src2.is_int()):
        int1 = expr.cond.src1.arg.arg
        int2 = expr.cond.src2.arg.arg
        if int1 and int2:
            expr = expr.src1
        elif int1 == 0 and int2 == 0:
            expr = expr.src2
        elif int1 == 0 and int2:
            expr = ExprCond(expr.cond.cond, expr.src2, expr.src1)
        elif int1 and int2 == 0:
            expr = ExprCond(expr.cond.cond, expr.src1, expr.src2)

    elif expr.cond.is_compose():
        # {0, X, 0}?(A:B) => X?(A:B)
        args = [arg for arg in expr.cond.args if not arg.is_int(0)]
        if len(args) == 1:
            arg = args.pop()
            return ExprCond(arg, expr.src1, expr.src2)
        elif len(args) < len(expr.cond.args):
            return ExprCond(ExprCompose(*args), expr.src1, expr.src2)
    return expr
Beispiel #3
0
 def eval_exprcond(self, expr, **kwargs):
     """[DEV]: Evaluate an ExprCond using the current state"""
     cond = self.eval_expr_visitor(expr.cond, **kwargs)
     src1 = self.eval_expr_visitor(expr.src1, **kwargs)
     src2 = self.eval_expr_visitor(expr.src2, **kwargs)
     ret = ExprCond(cond, src1, src2)
     return ret
def simp_cond_op_int(e_s, expr):
    "Extract conditions from operations"


    # x?a:b + x?c:d + e => x?(a+c+e:b+d+e)
    if not expr.op in ["+", "|", "^", "&", "*", '<<', '>>', 'a>>']:
        return expr
    if len(expr.args) < 2:
        return expr
    conds = set()
    for arg in expr.args:
        if arg.is_cond():
            conds.add(arg)
    if len(conds) != 1:
        return expr
    cond = list(conds).pop()

    args1, args2 = [], []
    for arg in expr.args:
        if arg.is_cond():
            args1.append(arg.src1)
            args2.append(arg.src2)
        else:
            args1.append(arg)
            args2.append(arg)

    return ExprCond(cond.cond,
                    ExprOp(expr.op, *args1),
                    ExprOp(expr.op, *args2))
Beispiel #5
0
def simp_cond_logic_ext(expr_s, expr):
    """(X.zeroExt() + ... + Int) ? A:B => X + ... + int[:] ? A:B"""
    cond = expr.cond
    if not cond.is_op():
        return expr
    if cond.op not in ["&", "^", "|"]:
        return expr
    is_ok = True
    sizes = set()
    for arg in cond.args:
        if arg.is_int():
            continue
        if (arg.is_op() and
            arg.op.startswith("zeroExt")):
            sizes.add(arg.args[0].size)
            continue
        is_ok = False
        break
    if not is_ok:
        return expr
    if len(sizes) != 1:
        return expr
    size = list(sizes)[0]
    args = [expr_s(arg[:size]) for arg in cond.args]
    cond = ExprOp(cond.op, *args)
    return ExprCond(cond, expr.src1, expr.src2)
Beispiel #6
0
def csinc(ir, instr, arg1, arg2, arg3, arg4):
    e = []
    cond_expr = cond2expr[arg4.name]
    e.append(
        ExprAssign(arg1, ExprCond(cond_expr, arg2,
                                  arg3 + ExprInt(1, arg3.size))))
    return e, []
def simp_cond_factor(e_s, expr):
    "Merge similar conditions"
    if not expr.op in ["+", "|", "^", "&", "*", '<<', '>>', 'a>>']:
        return expr
    if len(expr.args) < 2:
        return expr
    conds = {}
    not_conds = []
    multi_cond = False
    for arg in expr.args:
        if not arg.is_cond():
            not_conds.append(arg)
            continue
        cond = arg.cond
        if not cond in conds:
            conds[cond] = []
        else:
            multi_cond = True
        conds[cond].append(arg)
    if not multi_cond:
        return expr
    c_out = not_conds[:]
    for cond, vals in conds.items():
        new_src1 = [x.src1 for x in vals]
        new_src2 = [x.src2 for x in vals]
        src1 = e_s.expr_simp_wrapper(ExprOp(expr.op, *new_src1))
        src2 = e_s.expr_simp_wrapper(ExprOp(expr.op, *new_src2))
        c_out.append(ExprCond(cond, src1, src2))

    if len(c_out) == 1:
        new_e = c_out[0]
    else:
        new_e = ExprOp(expr.op, *c_out)
    return new_e
Beispiel #8
0
def sbvck3(ir, instr, r0, rn, rm):
    """SBVCK3 - Check substraction overflow"""

    # if(Overflow(Rn-Rm)) R0<-1 else R0<-0 (Signed)

    # Substract registers
    reg_sub = ExprOp("+", rn, rm)

    # Get the register storing the highest value
    max_rn_rm = ExprCond(ExprOp(">", rn, rm), rn, rm)

    # Check for an overflow
    overflow_test = ExprOp(">", reg_sub, max_rn_rm)

    # Return the result
    condition = ExprCond(overflow_test, ExprInt(1, 32), ExprInt(0, 32))
    return [ExprAff(r0, condition)], []
Beispiel #9
0
def cset(ir, instr, arg1, arg2):
    e = []
    cond_expr = cond2expr[arg2.name]
    e.append(
        ExprAssign(
            arg1,
            ExprCond(cond_expr, ExprInt(1, arg1.size), ExprInt(0, arg1.size))))
    return e, []
def simp_mem(e_s, expr):
    "Common simplifications on ExprMem"

    # @32[x?a:b] => x?@32[a]:@32[b]
    if expr.arg.is_cond():
        cond = expr.arg
        ret = ExprCond(cond.cond, ExprMem(cond.src1, expr.size),
                       ExprMem(cond.src2, expr.size))
        return ret
    return expr
Beispiel #11
0
def simp_cond_eq_zero(_, expr):
    """(X == 0)?(A:B) => X?(B:A)"""
    cond = expr.cond
    if not cond.is_op(TOK_EQUAL):
        return expr
    arg1, arg2 = cond.args
    if not arg2.is_int(0):
        return expr
    new_expr = ExprCond(arg1, expr.src2, expr.src1)
    return new_expr
Beispiel #12
0
 def eval_exprcond(self, expr, **kwargs):
     """[DEV]: Evaluate an ExprCond using the current state"""
     cond = self.eval_expr_visitor(expr.cond, **kwargs)
     src1 = self.eval_expr_visitor(expr.src1, **kwargs)
     src2 = self.eval_expr_visitor(expr.src2, **kwargs)
     if cond.is_id(TOPSTR) or src1.is_id(TOPSTR) or src2.is_id(TOPSTR):
         ret = exprid_top(expr)
     else:
         ret = ExprCond(cond, src1, src2)
     return ret
Beispiel #13
0
    def test_bgei(self):
        """Test BGEI execution"""

        # BGEI Rn,imm4,disp17.align2
        exec_instruction(
            "BGEI R1, 0x5, 0x10000", [(ExprId("R1", 32), ExprInt(0x10, 32))],
            [(ExprId("PC", 32),
              ExprCond(ExprOp(">=", ExprInt(0x10, 32), ExprInt(0x5, 32)),
                       ExprInt(0xFFFF0010, 32), ExprInt(0x14, 32)))],
            offset=0x10)
Beispiel #14
0
    def categorize(self, node, lvl=0, **kwargs):
        """Recursively apply rules to @node

        @node: ExprNode to analyze
        @lvl: actual recusion level
        """

        expr = node.expr
        log_reduce.debug("\t" * lvl + "Reduce...: %s", node.expr)
        if isinstance(expr, ExprId):
            node = ExprNodeId(expr)
        elif isinstance(expr, ExprInt):
            node = ExprNodeInt(expr)
        elif isinstance(expr, ExprLoc):
            node = ExprNodeLoc(expr)
        elif isinstance(expr, ExprMem):
            arg = self.categorize(node.arg, lvl=lvl + 1, **kwargs)
            node = ExprNodeMem(ExprMem(arg.expr, expr.size))
            node.arg = arg
        elif isinstance(expr, ExprSlice):
            arg = self.categorize(node.arg, lvl=lvl + 1, **kwargs)
            node = ExprNodeSlice(ExprSlice(arg.expr, expr.start, expr.stop))
            node.arg = arg
        elif isinstance(expr, ExprOp):
            new_args = []
            for arg in node.args:
                new_a = self.categorize(arg, lvl=lvl + 1, **kwargs)
                assert new_a.expr.size == arg.expr.size
                new_args.append(new_a)
            node = ExprNodeOp(ExprOp(expr.op, *[x.expr for x in new_args]))
            node.args = new_args
            expr = node.expr
        elif isinstance(expr, ExprCompose):
            new_args = []
            new_expr_args = []
            for arg in node.args:
                arg = self.categorize(arg, lvl=lvl + 1, **kwargs)
                new_args.append(arg)
                new_expr_args.append(arg.expr)
            new_expr = ExprCompose(*new_expr_args)
            node = ExprNodeCompose(new_expr)
            node.args = new_args
        elif isinstance(expr, ExprCond):
            cond = self.categorize(node.cond, lvl=lvl + 1, **kwargs)
            src1 = self.categorize(node.src1, lvl=lvl + 1, **kwargs)
            src2 = self.categorize(node.src2, lvl=lvl + 1, **kwargs)
            node = ExprNodeCond(ExprCond(cond.expr, src1.expr, src2.expr))
            node.cond, node.src1, node.src2 = cond, src1, src2
        else:
            raise TypeError("Unknown Expr Type %r", type(expr))

        node.info = self.apply_rules(node, lvl=lvl, **kwargs)
        log_reduce.debug("\t" * lvl + "Reduce result: %s %r", node.expr,
                         node.info)
        return node
Beispiel #15
0
def ccmp(ir, instr, arg1, arg2, arg3, arg4):
    e = []
    if (arg2.is_int()):
        arg2 = 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)[0].src
    new_of = update_flag_sub_of(arg1, arg2)[0].src

    e.append(ExprAssign(nf, ExprCond(cond_expr, new_nf, default_nf)))
    e.append(ExprAssign(zf, ExprCond(cond_expr, new_zf, default_zf)))
    e.append(ExprAssign(cf, ExprCond(cond_expr, new_cf, default_cf)))
    e.append(ExprAssign(of, ExprCond(cond_expr, new_of, default_of)))
    return e, []
Beispiel #16
0
def simp_cond_zeroext(_, expr):
    """
    X.zeroExt()?(A:B) => X ? A:B
    X.signExt()?(A:B) => X ? A:B
    """
    if not (expr.cond.is_op() and (expr.cond.op.startswith("zeroExt")
                                   or expr.cond.op.startswith("signExt"))):
        return expr

    ret = ExprCond(expr.cond.args[0], expr.src1, expr.src2)
    return ret
Beispiel #17
0
def simp_mem(_, expr):
    """
    Common simplifications on ExprMem:
    @32[x?a:b] => x?@32[a]:@32[b]
    """
    if expr.ptr.is_cond():
        cond = expr.ptr
        ret = ExprCond(cond.cond, ExprMem(cond.src1, expr.size),
                       ExprMem(cond.src2, expr.size))
        return ret
    return expr
Beispiel #18
0
def simp_cmp_int_arg(_, expr):
    """
    (0x10 <= R0) ? A:B
    =>
    (R0 < 0x10) ? B:A
    """
    cond = expr.cond
    if not cond.is_op():
        return expr
    op = cond.op
    if op not in [
            TOK_EQUAL,
            TOK_INF_SIGNED,
            TOK_INF_EQUAL_SIGNED,
            TOK_INF_UNSIGNED,
            TOK_INF_EQUAL_UNSIGNED
    ]:
        return expr
    arg1, arg2 = cond.args
    if arg2.is_int():
        return expr
    if not arg1.is_int():
        return expr
    src1, src2 = expr.src1, expr.src2
    if op == TOK_EQUAL:
        return ExprCond(ExprOp(TOK_EQUAL, arg2, arg1), src1, src2)

    arg1, arg2 = arg2, arg1
    src1, src2 = src2, src1
    if op == TOK_INF_SIGNED:
        op = TOK_INF_EQUAL_SIGNED
    elif op == TOK_INF_EQUAL_SIGNED:
        op = TOK_INF_SIGNED
    elif op == TOK_INF_UNSIGNED:
        op = TOK_INF_EQUAL_UNSIGNED
    elif op == TOK_INF_EQUAL_UNSIGNED:
        op = TOK_INF_UNSIGNED
    return ExprCond(ExprOp(op, arg1, arg2), src1, src2)
Beispiel #19
0
    def test_div(self):
        """Test DIV execution"""

        # DIV Rn,Rm
        exec_instruction("DIV R0, R1",
                         [(ExprId("R0", 32), ExprInt(0x80, 32)),
                          (ExprId("R1", 32), ExprInt(0x0, 32)),
                          (ExprId("HI", 32), ExprInt(0, 32)),
                          (ExprId("LO", 32), ExprInt(0, 32))],
                         [(ExprId("HI", 32), ExprInt(0, 32)),
                          (ExprId("LO", 32), ExprInt(0, 32)),
                          (ExprId("exception_flags", 32), ExprInt(EXCEPT_DIV_BY_ZERO, 32))])

        # Negative numbers
        exec_instruction("DIV R0, R1",
                         [(ExprId("R0", 32), ExprInt(-4, 32)),
                          (ExprId("R1", 32), ExprInt(-2, 32))],
                         [(ExprId("HI", 32), ExprInt(0, 32)),
                          (ExprId("LO", 32), ExprInt(2, 32))])

        exec_instruction("DIV R0, R1",
                         [(ExprId("R0", 32), ExprInt(-5, 32)),
                          (ExprId("R1", 32), ExprInt(-2, 32))],
                         [(ExprId("HI", 32), ExprInt(1, 32)),
                          (ExprId("LO", 32), ExprInt(2, 32))])

        # Positive numbers
        exec_instruction("DIV R0, R1",
                         [(ExprId("R0", 32), ExprInt(4, 32)),
                          (ExprId("R1", 32), ExprInt(2, 32))],
                         [(ExprId("HI", 32), ExprCond(ExprOp("==",
                                                             ExprInt(0, 32),
                                                             ExprInt(0x80000000, 32)),
                                                      ExprInt(0, 32),
                                                      ExprInt(0xFFFFFFFC, 32))),
                          (ExprId("LO", 32), ExprCond(ExprOp("==",
                                                             ExprInt(0, 32),
                                                             ExprInt(0x80000000, 32)),
                                                       ExprInt(2, 32),
                                                       ExprInt(0, 32)))])

        # Negative & positive numbers
        exec_instruction("DIV R0, R1",
                         [(ExprId("R0", 32), ExprInt(-5, 32)),
                          (ExprId("R1", 32), ExprInt(2, 32))],
                         [(ExprId("HI", 32), ExprCond(ExprOp("==", ExprInt(0, 32), ExprInt(0x80000000, 32)),
                                                      ExprInt(1, 32), ExprInt(0xFFFFFFFF, 32))),
                          (ExprId("LO", 32), ExprCond(ExprOp("==", ExprInt(0, 32), ExprInt(0x80000000, 32)),
                                                      ExprInt(0x7FFFFFFD, 32), ExprInt(0xFFFFFFFE, 32)))])

        exec_instruction("DIV R0, R1",
                         [(ExprId("R0", 32), ExprInt(5, 32)),
                          (ExprId("R1", 32), ExprInt(-2, 32))],
                         [(ExprId("HI", 32), ExprCond(ExprOp("==", ExprInt(0, 32), ExprInt(0x80000000, 32)),
                                                      ExprInt(5, 32), ExprInt(0xFFFFFFFF, 32))),
                          (ExprId("LO", 32), ExprCond(ExprOp("==", ExprInt(0, 32), ExprInt(0x80000000, 32)),
                                                      ExprInt(0, 32), ExprInt(0xFFFFFFFE, 32)))])
def simp_compose(e_s, expr):
    "Commons simplification on ExprCompose"
    args = merge_sliceto_slice(expr)
    out = []
    # compose of compose
    for arg in args:
        if arg.is_compose():
            out += arg.args
        else:
            out.append(arg)
    args = out
    # Compose(a) with a.size = compose.size => a
    if len(args) == 1 and args[0].size == expr.size:
        return args[0]

    # {(X[z:], 0, X.size-z), (0, X.size-z, X.size)} => (X >> z)
    if len(args) == 2 and args[1].is_int(0):
        if (args[0].is_slice() and
            args[0].stop == args[0].arg.size and
            args[0].size + args[1].size == args[0].arg.size):
            new_expr = args[0].arg >> ExprInt(args[0].start, args[0].arg.size)
            return new_expr

    # {@X[base + i] 0 X, @Y[base + i + X] X (X + Y)} => @(X+Y)[base + i]
    for i, arg in enumerate(args[:-1]):
        nxt = args[i + 1]
        if arg.is_mem() and nxt.is_mem():
            gap = e_s(nxt.arg - arg.arg)
            if gap.is_int() and arg.size % 8 == 0 and int(gap) == arg.size / 8:
                args = args[:i] + [ExprMem(arg.arg,
                                          arg.size + nxt.size)] + args[i + 2:]
                return ExprCompose(*args)

    # {a, x?b:d, x?c:e, f} => x?{a, b, c, f}:{a, d, e, f}
    conds = set(arg.cond for arg in expr.args if arg.is_cond())
    if len(conds) == 1:
        cond = list(conds)[0]
        args1, args2 = [], []
        for arg in expr.args:
            if arg.is_cond():
                args1.append(arg.src1)
                args2.append(arg.src2)
            else:
                args1.append(arg)
                args2.append(arg)
        arg1 = e_s(ExprCompose(*args1))
        arg2 = e_s(ExprCompose(*args2))
        return ExprCond(cond, arg1, arg2)
    return ExprCompose(*args)
Beispiel #21
0
def simp_cond_sign_bit(_, expr):
    """(a & .. & 0x80000000) ? A:B => (a & ...) <s 0 ? A:B"""
    cond = expr.cond
    if not cond.is_op('&'):
        return expr
    last = cond.args[-1]
    if not last.is_int(1 << (last.size - 1)):
        return expr
    zero = ExprInt(0, expr.cond.size)
    if len(cond.args) == 2:
        args = [cond.args[0], zero]
    else:
        args = [ExprOp('&', *list(cond.args[:-1])), zero]
    cond = ExprOp(TOK_INF_SIGNED, *args)
    return ExprCond(cond, expr.src1, expr.src2)
def simp_ext(_, expr):
    if expr.op.startswith('zeroExt_'):
        arg = expr.args[0]
        if expr.size == arg.size:
            return arg
        return ExprCompose(arg, ExprInt(0, expr.size - arg.size))

    if expr.op.startswith("signExt_"):
        arg = expr.args[0]
        add_size = expr.size - arg.size
        new_expr = ExprCompose(
            arg,
            ExprCond(arg.msb(), ExprInt(size2mask(add_size), add_size),
                     ExprInt(0, add_size)))
        return new_expr
    return expr
Beispiel #23
0
    def call_effects(self, ad, instr):
        call_assignblk = AssignBlock(
            [
                ExprAff(
                    self.ret_reg,
                    ExprOp(
                        'call_func_ret',
                        ad,
                        self.arch.regs.R0,
                        self.arch.regs.R1,
                        self.arch.regs.R2,
                        self.arch.regs.R3,
                    )
                ),
                ExprAff(
                    self.sp,
                    ExprOp('call_func_stack', ad, self.sp)
                ),
            ],
            instr
        )


        cond = instr.additional_info.cond
        if cond == 14: # COND_ALWAYS:
            return [call_assignblk], []

        # Call is a conditional instruction
        cond = tab_cond[cond]

        loc_next = self.get_next_loc_key(instr)
        loc_next_expr = ExprLoc(loc_next, 32)
        loc_do = self.loc_db.add_location()
        loc_do_expr = ExprLoc(loc_do, 32)
        dst_cond = ExprCond(cond, loc_do_expr, loc_next_expr)

        call_assignblks = [
            call_assignblk,
            AssignBlock([ExprAff(self.IRDst, loc_next_expr)], instr),
        ]
        e_do = IRBlock(loc_do, call_assignblks)
        assignblks_out = [
            AssignBlock([ExprAff(self.IRDst, dst_cond)], instr)
        ]
        return assignblks_out, [e_do]
Beispiel #24
0
def div(rn, rm):
    """DIV - Signed division"""

    # LO <- Rn / Rm, HI <- Rn % Rm (Signed)

    # Mask sign bits
    sign_mask = i32(0x80000000)
    sign_rn = rn & sign_mask
    sign_rm = rm & sign_mask

    # Check if both numbers are positive or negative
    are_both_neg = sign_rn & sign_rm
    are_both_pos = ExprCond(
        are_both_neg - sign_mask,
        ExprInt(0, are_both_neg.size),
        ExprInt(1, are_both_neg.size)
    )


    # Invert both numbers
    rn_inv = ~rn + i32(1)
    rm_inv = ~rm + i32(1)

    # Used to delay the arithmetic computations
    tmp_rm = rm if rm else i32(1)
    tmp_rm_inv = rm_inv if rm_inv else i32(1)

    # Results if only rn, or rm is negative
    LO_rn_neg = (~(rn_inv / tmp_rm) + i32(1)) if sign_rn else (~(rn / tmp_rm_inv) + i32(1))
    HI_rn_neg = (~(rn_inv % tmp_rm) + i32(1)) if sign_rn else (~(rn % tmp_rm_inv) + i32(1))

    # Results if both numbers are positive
    LO_pos = rn / tmp_rm if are_both_pos else LO_rn_neg
    HI_pos = rn % tmp_rm if are_both_pos else HI_rn_neg

    # Results if both numbers are negative
    LO_neg = rn_inv / tmp_rm_inv if are_both_neg else LO_pos
    HI_neg = rn_inv % tmp_rm_inv if are_both_neg else HI_pos

    # Results if rm is equal to zero
    LO = LO_neg if rm else LO
    HI = HI_neg if rm else HI

    exception_flags = i32(0) if rm else i32(EXCEPT_DIV_BY_ZERO)
def simp_cond_factor(e_s, expr):
    "Merge similar conditions"
    if not expr.op in ["+", "|", "^", "&", "*", '<<', '>>', 'a>>']:
        return expr
    if len(expr.args) < 2:
        return expr

    if expr.op in ['>>', '<<', 'a>>']:
        assert len(expr.args) == 2

    # Note: the following code is correct for non-commutative operation only if
    # there is 2 arguments. Otherwise, the order is not conserved

    # Regroup sub-expression by similar conditions
    conds = {}
    not_conds = []
    multi_cond = False
    for arg in expr.args:
        if not arg.is_cond():
            not_conds.append(arg)
            continue
        cond = arg.cond
        if not cond in conds:
            conds[cond] = []
        else:
            multi_cond = True
        conds[cond].append(arg)
    if not multi_cond:
        return expr

    # Rebuild the new expression
    c_out = not_conds
    for cond, vals in conds.items():
        new_src1 = [x.src1 for x in vals]
        new_src2 = [x.src2 for x in vals]
        src1 = e_s.expr_simp_wrapper(ExprOp(expr.op, *new_src1))
        src2 = e_s.expr_simp_wrapper(ExprOp(expr.op, *new_src2))
        c_out.append(ExprCond(cond, src1, src2))

    if len(c_out) == 1:
        new_e = c_out[0]
    else:
        new_e = ExprOp(expr.op, *c_out)
    return new_e
Beispiel #26
0
def simp_x_and_cst_eq_cst(_, expr):
    """
    (x & ... & onebitmask == onebitmask) ? A:B => (x & ... & onebitmask) ? A:B
    """
    cond = expr.cond
    if not cond.is_op(TOK_EQUAL):
        return expr
    arg1, mask2 = cond.args
    if not mask2.is_int():
        return expr
    if not test_one_bit_set(int(mask2)):
        return expr
    if not arg1.is_op('&'):
        return expr
    mask1 = arg1.args[-1]
    if mask1 != mask2:
        return expr
    cond = ExprOp('&', *arg1.args)
    return ExprCond(cond, expr.src1, expr.src2)
Beispiel #27
0
def simp_cond_add(expr_s, expr):
    """
    (a+b)?X:Y => (a == b)?Y:X
    (a^b)?X:Y => (a == b)?Y:X
    """
    cond = expr.cond
    if not cond.is_op():
        return expr
    if cond.op not in ['+', '^']:
        return expr
    if len(cond.args) != 2:
        return expr
    arg1, arg2 = cond.args
    if cond.is_op('+'):
        new_cond = ExprOp('==', arg1, expr_s(-arg2))
    elif cond.is_op('^'):
        new_cond = ExprOp('==', arg1, arg2)
    else:
        raise ValueError('Bad case')
    return ExprCond(new_cond, expr.src2, expr.src1)
def simp_cond(e_s, expr):
    "Common simplifications on ExprCond"
    # eval exprcond src1/src2 with satifiable/unsatisfiable condition
    # propagation
    if (not expr.cond.is_int()) and expr.cond.size == 1:
        src1 = expr.src1.replace_expr({expr.cond: ExprInt(1, 1)})
        src2 = expr.src2.replace_expr({expr.cond: ExprInt(0, 1)})
        if src1 != expr.src1 or src2 != expr.src2:
            return ExprCond(expr.cond, src1, src2)

    # -A ? B:C => A ? B:C
    if expr.cond.is_op('-') and len(expr.cond.args) == 1:
        expr = ExprCond(expr.cond.args[0], expr.src1, expr.src2)
    # a?x:x
    elif expr.src1 == expr.src2:
        expr = expr.src1
    # int ? A:B => A or B
    elif expr.cond.is_int():
        if expr.cond.arg == 0:
            expr = expr.src2
        else:
            expr = expr.src1
    # a?(a?b:c):x => a?b:x
    elif expr.src1.is_cond() and expr.cond == expr.src1.cond:
        expr = ExprCond(expr.cond, expr.src1.src1, expr.src2)
    # a?x:(a?b:c) => a?x:c
    elif expr.src2.is_cond() and expr.cond == expr.src2.cond:
        expr = ExprCond(expr.cond, expr.src1, expr.src2.src2)
    # a|int ? b:c => b with int != 0
    elif (expr.cond.is_op('|') and
          expr.cond.args[1].is_int() and
          expr.cond.args[1].arg != 0):
        return expr.src1

    # (C?int1:int2)?(A:B) =>
    elif (expr.cond.is_cond() and
          expr.cond.src1.is_int() and
          expr.cond.src2.is_int()):
        int1 = expr.cond.src1.arg.arg
        int2 = expr.cond.src2.arg.arg
        if int1 and int2:
            expr = expr.src1
        elif int1 == 0 and int2 == 0:
            expr = expr.src2
        elif int1 == 0 and int2:
            expr = ExprCond(expr.cond.cond, expr.src2, expr.src1)
        elif int1 and int2 == 0:
            expr = ExprCond(expr.cond.cond, expr.src1, expr.src2)
    return expr
Beispiel #29
0
def casp(ir, instr, arg1, arg2, arg3):
    # XXX TODO: memory barrier
    e = []
    if arg1.size == 32:
        regs = gpregs32_expr
    else:
        regs = gpregs64_expr
    index1 = regs.index(arg1)
    index2 = regs.index(arg2)

    # TODO endianness
    comp_value = ExprCompose(regs[index1], regs[index1 + 1])
    new_value = ExprCompose(regs[index2], regs[index2 + 1])
    assert arg3.is_op('preinc')
    ptr = arg3.args[0]
    data = ExprMem(ptr, comp_value.size)

    loc_store = ExprLoc(ir.loc_db.add_location(), ir.IRDst.size)
    loc_do = ExprLoc(ir.loc_db.add_location(), ir.IRDst.size)
    loc_next = ExprLoc(ir.get_next_loc_key(instr), ir.IRDst.size)

    e.append(
        ExprAssign(
            ir.IRDst,
            ExprCond(ExprOp("FLAG_EQ_CMP", data, comp_value), loc_do,
                     loc_store)))

    e_store = []
    e_store.append(ExprAssign(data, new_value))
    e_store.append(ExprAssign(ir.IRDst, loc_do))
    blk_store = IRBlock(loc_store.loc_key, [AssignBlock(e_store, instr)])

    e_do = []
    e_do.append(ExprAssign(regs[index1], data[:data.size / 2]))
    e_do.append(ExprAssign(regs[index1 + 1], data[data.size / 2:]))
    e_do.append(ExprAssign(ir.IRDst, loc_next))
    blk_do = IRBlock(loc_do.loc_key, [AssignBlock(e_do, instr)])

    return e, [blk_store, blk_do]
Beispiel #30
0
def simp_cc_conds(expr_simp, expr):
    if (expr.is_op("CC_U>=") and
          test_cc_eq_args(
              expr,
              "FLAG_SUB_CF"
          )):
        expr = ExprCond(
            ExprOp(TOK_INF_UNSIGNED, *expr.args[0].args),
            ExprInt(0, 1),
            ExprInt(1, 1))

    elif (expr.is_op("CC_U<") and
          test_cc_eq_args(
              expr,
              "FLAG_SUB_CF"
          )):
        expr = ExprOp(TOK_INF_UNSIGNED, *expr.args[0].args)

    elif (expr.is_op("CC_NEG") and
          test_cc_eq_args(
              expr,
              "FLAG_SIGN_SUB"
          )):
        expr = ExprOp(TOK_INF_SIGNED, *expr.args[0].args)

    elif (expr.is_op("CC_POS") and
          test_cc_eq_args(
              expr,
              "FLAG_SIGN_SUB"
          )):
        expr = ExprCond(
            ExprOp(TOK_INF_SIGNED, *expr.args[0].args),
            ExprInt(0, 1),
            ExprInt(1, 1)
        )

    elif (expr.is_op("CC_EQ") and
          test_cc_eq_args(
              expr,
              "FLAG_EQ"
          )):
        arg = expr.args[0].args[0]
        expr = ExprOp(TOK_EQUAL, arg, ExprInt(0, arg.size))

    elif (expr.is_op("CC_NE") and
          test_cc_eq_args(
              expr,
              "FLAG_EQ"
          )):
        arg = expr.args[0].args[0]
        expr = ExprCond(
            ExprOp(TOK_EQUAL,arg, ExprInt(0, arg.size)),
            ExprInt(0, 1),
            ExprInt(1, 1)
        )
    elif (expr.is_op("CC_NE") and
          test_cc_eq_args(
              expr,
              "FLAG_EQ_CMP"
          )):
        expr = ExprCond(
            ExprOp(TOK_EQUAL, *expr.args[0].args),
            ExprInt(0, 1),
            ExprInt(1, 1)
        )

    elif (expr.is_op("CC_EQ") and
          test_cc_eq_args(
              expr,
              "FLAG_EQ_CMP"
          )):
        expr = ExprOp(TOK_EQUAL, *expr.args[0].args)

    elif (expr.is_op("CC_NE") and
          test_cc_eq_args(
              expr,
              "FLAG_EQ_AND"
          )):
        expr = ExprOp("&", *expr.args[0].args)

    elif (expr.is_op("CC_EQ") and
          test_cc_eq_args(
              expr,
              "FLAG_EQ_AND"
          )):
        expr = ExprCond(
            ExprOp("&", *expr.args[0].args),
            ExprInt(0, 1),
            ExprInt(1, 1)
        )

    elif (expr.is_op("CC_S>") and
          test_cc_eq_args(
              expr,
              "FLAG_SIGN_SUB",
              "FLAG_SUB_OF",
              "FLAG_EQ_CMP",
          )):
        expr = ExprCond(
            ExprOp(TOK_INF_EQUAL_SIGNED, *expr.args[0].args),
            ExprInt(0, 1),
            ExprInt(1, 1)
        )

    elif (expr.is_op("CC_S>") and
          len(expr.args) == 3 and
          expr.args[0].is_op("FLAG_SIGN_SUB") and
          expr.args[2].is_op("FLAG_EQ_CMP") and
          expr.args[0].args == expr.args[2].args and
          expr.args[1].is_int(0)):
        expr = ExprCond(
            ExprOp(TOK_INF_EQUAL_SIGNED, *expr.args[0].args),
            ExprInt(0, 1),
            ExprInt(1, 1)
        )



    elif (expr.is_op("CC_S>=") and
          test_cc_eq_args(
              expr,
              "FLAG_SIGN_SUB",
              "FLAG_SUB_OF"
          )):
        expr = ExprCond(
            ExprOp(TOK_INF_SIGNED, *expr.args[0].args),
            ExprInt(0, 1),
            ExprInt(1, 1)
        )

    elif (expr.is_op("CC_S<") and
          test_cc_eq_args(
              expr,
              "FLAG_SIGN_SUB",
              "FLAG_SUB_OF"
          )):
        expr = ExprOp(TOK_INF_SIGNED, *expr.args[0].args)

    elif (expr.is_op("CC_S<=") and
          test_cc_eq_args(
              expr,
              "FLAG_SIGN_SUB",
              "FLAG_SUB_OF",
              "FLAG_EQ_CMP",
          )):
        expr = ExprOp(TOK_INF_EQUAL_SIGNED, *expr.args[0].args)

    elif (expr.is_op("CC_S<=") and
          len(expr.args) == 3 and
          expr.args[0].is_op("FLAG_SIGN_SUB") and
          expr.args[2].is_op("FLAG_EQ_CMP") and
          expr.args[0].args == expr.args[2].args and
          expr.args[1].is_int(0)):
        expr = ExprOp(TOK_INF_EQUAL_SIGNED, *expr.args[0].args)

    elif (expr.is_op("CC_U<=") and
          test_cc_eq_args(
              expr,
              "FLAG_SUB_CF",
              "FLAG_EQ_CMP",
          )):
        expr = ExprOp(TOK_INF_EQUAL_UNSIGNED, *expr.args[0].args)

    elif (expr.is_op("CC_U>") and
          test_cc_eq_args(
              expr,
              "FLAG_SUB_CF",
              "FLAG_EQ_CMP",
          )):
        expr = ExprCond(
            ExprOp(TOK_INF_EQUAL_UNSIGNED, *expr.args[0].args),
            ExprInt(0, 1),
            ExprInt(1, 1)
        )

    elif (expr.is_op("CC_S<") and
          test_cc_eq_args(
              expr,
              "FLAG_SIGN_ADD",
              "FLAG_ADD_OF"
          )):
        arg0, arg1 = expr.args[0].args
        expr = ExprOp(TOK_INF_SIGNED, arg0, -arg1)

    return expr
Beispiel #31
0
            print k, v
            reqs.append((k, v))
        all_info.append((addr, reqs))

    all_cases = set()

    symbexec = SymbolicExecutionEngine(ir_arch)
    for addr, reqs_cond in all_info:
        out = ['(set-logic QF_ABV)', '(set-info :smt-lib-version 2.0)']

        conditions = []
        all_ids = set()
        for expr, value in reqs_cond:

            all_ids.update(get_expr_ids(expr))
            expr_test = ExprCond(expr, ExprInt(1, value.size),
                                 ExprInt(0, value.size))
            cond = translator_smt2.from_expr(ExprAssign(expr_test, value))
            conditions.append(cond)

        for name in all_ids:
            out.append("(declare-fun %s () (_ BitVec %d))" % (name, name.size))
        if not out:
            continue

        out += conditions
        out.append('(check-sat)')
        open('out.dot', 'w').write('\n'.join(out))
        try:
            cases = subprocess.check_output([
                "/home/serpilliere/tools/stp/stp", "-p", '--SMTLIB2', "out.dot"
            ])