Top

miasm2.expression.simplifications_cond module

################################################################################
#
# By choice, Miasm2 does not handle comparaison as a single operation, but with
# operations corresponding to comparaison computation.
# One may want to detect those comparaison; this library is designed to add them
# in Miasm2 engine thanks to :
# - Conditions computation in ExprOp
# - Simplifications to catch known condition forms
#
# Conditions currently supported :
# <u, <s, ==
#
# Authors : Fabrice DESCLAUX (CEA/DAM), Camille MOUGEY (CEA/DAM)
#
################################################################################

import miasm2.expression.expression as m2_expr


# Jokers for expression matching

jok1 = m2_expr.ExprId("jok1", 32)
jok2 = m2_expr.ExprId("jok2", 32)
jok3 = m2_expr.ExprId("jok3", 32)
jok_small = m2_expr.ExprId("jok_small", 1)


# Constructors

def __ExprOp_cond(op, arg1, arg2):
    "Return an ExprOp standing for arg1 op arg2 with size to 1"
    ec = m2_expr.ExprOp(op, arg1, arg2)
    return ec


def ExprOp_inf_signed(arg1, arg2):
    "Return an ExprOp standing for arg1 <s arg2"
    return __ExprOp_cond(m2_expr.TOK_INF_SIGNED, arg1, arg2)


def ExprOp_inf_unsigned(arg1, arg2):
    "Return an ExprOp standing for arg1 <s arg2"
    return __ExprOp_cond(m2_expr.TOK_INF_UNSIGNED, arg1, arg2)

def ExprOp_equal(arg1, arg2):
    "Return an ExprOp standing for arg1 == arg2"
    return __ExprOp_cond(m2_expr.TOK_EQUAL, arg1, arg2)


# Catching conditions forms

def __check_msb(e):
    """If @e stand for the most significant bit of its arg, return the arg;
    False otherwise"""

    if not isinstance(e, m2_expr.ExprSlice):
        return False

    arg = e.arg
    if e.start != (arg.size - 1) or e.stop != arg.size:
        return False

    return arg

def __match_expr_wrap(e, to_match, jok_list):
    "Wrapper around match_expr to canonize pattern"

    to_match = to_match.canonize()

    r = m2_expr.match_expr(e, to_match, jok_list)
    if r is False:
        return False

    if r == {}:
        return False

    return r

def expr_simp_inf_signed(expr_simp, e):
    "((x - y) ^ ((x ^ y) & ((x - y) ^ x))) [31:32] == x <s y"

    arg = __check_msb(e)
    if arg is False:
        return e
    # We want jok3 = jok1 - jok2
    to_match = jok3 ^ ((jok1 ^ jok2) & (jok3 ^ jok1))
    r = __match_expr_wrap(arg,
                        to_match,
                        [jok1, jok2, jok3])

    if r is False:
        return e

    new_j3 = expr_simp(r[jok3])
    sub = expr_simp(r[jok1] - r[jok2])

    if new_j3 == sub:
        return ExprOp_inf_signed(r[jok1], r[jok2])
    else:
        return e

def expr_simp_inf_unsigned_inversed(expr_simp, e):
    "((x - y) ^ ((x ^ y) & ((x - y) ^ x))) ^ x ^ y [31:32] == x <u y"

    arg = __check_msb(e)
    if arg is False:
        return e

    # We want jok3 = jok1 - jok2
    to_match = jok3 ^ ((jok1 ^ jok2) & (jok3 ^ jok1)) ^ jok1 ^ jok2
    r = __match_expr_wrap(arg,
                        to_match,
                        [jok1, jok2, jok3])

    if r is False:
        return e

    new_j3 = expr_simp(r[jok3])
    sub = expr_simp(r[jok1] - r[jok2])

    if new_j3 == sub:
        return ExprOp_inf_unsigned(r[jok1], r[jok2])
    else:
        return e

def expr_simp_inverse(expr_simp, e):
    """(x <u y) ^ ((x ^ y) [31:32]) == x <s y,
    (x <s y) ^ ((x ^ y) [31:32]) == x <u y"""

    to_match = (ExprOp_inf_unsigned(jok1, jok2) ^ jok_small)
    r = __match_expr_wrap(e,
                        to_match,
                        [jok1, jok2, jok_small])

    # Check for 2 symetric cases
    if r is False:
        to_match = (ExprOp_inf_signed(jok1, jok2) ^ jok_small)
        r = __match_expr_wrap(e,
                            to_match,
                            [jok1, jok2, jok_small])

        if r is False:
            return e
        cur_sig = m2_expr.TOK_INF_SIGNED
    else:
        cur_sig = m2_expr.TOK_INF_UNSIGNED


    arg = __check_msb(r[jok_small])
    if arg is False:
        return e

    if not isinstance(arg, m2_expr.ExprOp) or arg.op != "^":
        return e

    op_args = arg.args
    if len(op_args) != 2:
        return e

    if r[jok1] not in op_args or r[jok2] not in op_args:
        return e

    if cur_sig == m2_expr.TOK_INF_UNSIGNED:
        return ExprOp_inf_signed(r[jok1], r[jok2])
    else:
        return ExprOp_inf_unsigned(r[jok1], r[jok2])

def expr_simp_equal(expr_simp, e):
    """(x - y)?(0:1) == (x == y)"""

    to_match = m2_expr.ExprCond(jok1 + jok2, m2_expr.ExprInt(0, 1), m2_expr.ExprInt(1, 1))
    r = __match_expr_wrap(e,
                          to_match,
                          [jok1, jok2])
    if r is False:
        return e

    return ExprOp_equal(r[jok1], expr_simp(-r[jok2]))

# Compute conditions

def exec_inf_unsigned(expr_simp, e):
    "Compute x <u y"
    if e.op != m2_expr.TOK_INF_UNSIGNED:
        return e

    arg1, arg2 = e.args

    if isinstance(arg1, m2_expr.ExprInt) and isinstance(arg2, m2_expr.ExprInt):
        return m2_expr.ExprInt(1, 1) if (arg1.arg < arg2.arg) else m2_expr.ExprInt(0, 1)
    else:
        return e


def __comp_signed(arg1, arg2):
    """Return ExprInt(1, 1) if arg1 <s arg2 else ExprInt(0, 1)
    @arg1, @arg2: ExprInt"""

    val1 = int(arg1)
    if val1 >> (arg1.size - 1) == 1:
        val1 = - ((int(arg1.mask) ^ val1) + 1)

    val2 = int(arg2)
    if val2 >> (arg2.size - 1) == 1:
        val2 = - ((int(arg2.mask) ^ val2) + 1)

    return m2_expr.ExprInt(1, 1) if (val1 < val2) else m2_expr.ExprInt(0, 1)

def exec_inf_signed(expr_simp, e):
    "Compute x <s y"

    if e.op != m2_expr.TOK_INF_SIGNED:
        return e

    arg1, arg2 = e.args

    if isinstance(arg1, m2_expr.ExprInt) and isinstance(arg2, m2_expr.ExprInt):
        return __comp_signed(arg1, arg2)
    else:
        return e

def exec_equal(expr_simp, e):
    "Compute x == y"

    if e.op != m2_expr.TOK_EQUAL:
        return e

    arg1, arg2 = e.args
    if isinstance(arg1, m2_expr.ExprInt) and isinstance(arg2, m2_expr.ExprInt):
        return m2_expr.ExprInt(1, 1) if (arg1.arg == arg2.arg) else m2_expr.ExprInt(0, 1)
    else:
        return e

Module variables

var jok1

var jok2

var jok3

var jok_small

Functions

def ExprOp_equal(

arg1, arg2)

Return an ExprOp standing for arg1 == arg2

def ExprOp_equal(arg1, arg2):
    "Return an ExprOp standing for arg1 == arg2"
    return __ExprOp_cond(m2_expr.TOK_EQUAL, arg1, arg2)

def ExprOp_inf_signed(

arg1, arg2)

Return an ExprOp standing for arg1 <s arg2

def ExprOp_inf_signed(arg1, arg2):
    "Return an ExprOp standing for arg1 <s arg2"
    return __ExprOp_cond(m2_expr.TOK_INF_SIGNED, arg1, arg2)

def ExprOp_inf_unsigned(

arg1, arg2)

Return an ExprOp standing for arg1 <s arg2

def ExprOp_inf_unsigned(arg1, arg2):
    "Return an ExprOp standing for arg1 <s arg2"
    return __ExprOp_cond(m2_expr.TOK_INF_UNSIGNED, arg1, arg2)

def exec_equal(

expr_simp, e)

Compute x == y

def exec_equal(expr_simp, e):
    "Compute x == y"

    if e.op != m2_expr.TOK_EQUAL:
        return e

    arg1, arg2 = e.args
    if isinstance(arg1, m2_expr.ExprInt) and isinstance(arg2, m2_expr.ExprInt):
        return m2_expr.ExprInt(1, 1) if (arg1.arg == arg2.arg) else m2_expr.ExprInt(0, 1)
    else:
        return e

def exec_inf_signed(

expr_simp, e)

Compute x <s y

def exec_inf_signed(expr_simp, e):
    "Compute x <s y"

    if e.op != m2_expr.TOK_INF_SIGNED:
        return e

    arg1, arg2 = e.args

    if isinstance(arg1, m2_expr.ExprInt) and isinstance(arg2, m2_expr.ExprInt):
        return __comp_signed(arg1, arg2)
    else:
        return e

def exec_inf_unsigned(

expr_simp, e)

Compute x <u y

def exec_inf_unsigned(expr_simp, e):
    "Compute x <u y"
    if e.op != m2_expr.TOK_INF_UNSIGNED:
        return e

    arg1, arg2 = e.args

    if isinstance(arg1, m2_expr.ExprInt) and isinstance(arg2, m2_expr.ExprInt):
        return m2_expr.ExprInt(1, 1) if (arg1.arg < arg2.arg) else m2_expr.ExprInt(0, 1)
    else:
        return e

def expr_simp_equal(

expr_simp, e)

(x - y)?(0:1) == (x == y)

def expr_simp_equal(expr_simp, e):
    """(x - y)?(0:1) == (x == y)"""

    to_match = m2_expr.ExprCond(jok1 + jok2, m2_expr.ExprInt(0, 1), m2_expr.ExprInt(1, 1))
    r = __match_expr_wrap(e,
                          to_match,
                          [jok1, jok2])
    if r is False:
        return e

    return ExprOp_equal(r[jok1], expr_simp(-r[jok2]))

def expr_simp_inf_signed(

expr_simp, e)

((x - y) ^ ((x ^ y) & ((x - y) ^ x))) [31:32] == x <s y

def expr_simp_inf_signed(expr_simp, e):
    "((x - y) ^ ((x ^ y) & ((x - y) ^ x))) [31:32] == x <s y"

    arg = __check_msb(e)
    if arg is False:
        return e
    # We want jok3 = jok1 - jok2
    to_match = jok3 ^ ((jok1 ^ jok2) & (jok3 ^ jok1))
    r = __match_expr_wrap(arg,
                        to_match,
                        [jok1, jok2, jok3])

    if r is False:
        return e

    new_j3 = expr_simp(r[jok3])
    sub = expr_simp(r[jok1] - r[jok2])

    if new_j3 == sub:
        return ExprOp_inf_signed(r[jok1], r[jok2])
    else:
        return e

def expr_simp_inf_unsigned_inversed(

expr_simp, e)

((x - y) ^ ((x ^ y) & ((x - y) ^ x))) ^ x ^ y [31:32] == x <u y

def expr_simp_inf_unsigned_inversed(expr_simp, e):
    "((x - y) ^ ((x ^ y) & ((x - y) ^ x))) ^ x ^ y [31:32] == x <u y"

    arg = __check_msb(e)
    if arg is False:
        return e

    # We want jok3 = jok1 - jok2
    to_match = jok3 ^ ((jok1 ^ jok2) & (jok3 ^ jok1)) ^ jok1 ^ jok2
    r = __match_expr_wrap(arg,
                        to_match,
                        [jok1, jok2, jok3])

    if r is False:
        return e

    new_j3 = expr_simp(r[jok3])
    sub = expr_simp(r[jok1] - r[jok2])

    if new_j3 == sub:
        return ExprOp_inf_unsigned(r[jok1], r[jok2])
    else:
        return e

def expr_simp_inverse(

expr_simp, e)

(x <u y) ^ ((x ^ y) [31:32]) == x <s y, (x <s y) ^ ((x ^ y) [31:32]) == x <u y

def expr_simp_inverse(expr_simp, e):
    """(x <u y) ^ ((x ^ y) [31:32]) == x <s y,
    (x <s y) ^ ((x ^ y) [31:32]) == x <u y"""

    to_match = (ExprOp_inf_unsigned(jok1, jok2) ^ jok_small)
    r = __match_expr_wrap(e,
                        to_match,
                        [jok1, jok2, jok_small])

    # Check for 2 symetric cases
    if r is False:
        to_match = (ExprOp_inf_signed(jok1, jok2) ^ jok_small)
        r = __match_expr_wrap(e,
                            to_match,
                            [jok1, jok2, jok_small])

        if r is False:
            return e
        cur_sig = m2_expr.TOK_INF_SIGNED
    else:
        cur_sig = m2_expr.TOK_INF_UNSIGNED


    arg = __check_msb(r[jok_small])
    if arg is False:
        return e

    if not isinstance(arg, m2_expr.ExprOp) or arg.op != "^":
        return e

    op_args = arg.args
    if len(op_args) != 2:
        return e

    if r[jok1] not in op_args or r[jok2] not in op_args:
        return e

    if cur_sig == m2_expr.TOK_INF_UNSIGNED:
        return ExprOp_inf_signed(r[jok1], r[jok2])
    else:
        return ExprOp_inf_unsigned(r[jok1], r[jok2])