diff options
Diffstat (limited to 'miasm2/expression/simplifications_common.py')
| -rw-r--r-- | miasm2/expression/simplifications_common.py | 142 |
1 files changed, 111 insertions, 31 deletions
diff --git a/miasm2/expression/simplifications_common.py b/miasm2/expression/simplifications_common.py index e7dacc91..7db4e819 100644 --- a/miasm2/expression/simplifications_common.py +++ b/miasm2/expression/simplifications_common.py @@ -509,7 +509,7 @@ def simp_slice(e_s, expr): if (expr.arg.is_mem() and expr.start == 0 and expr.arg.size > expr.stop and expr.stop % 8 == 0): - return ExprMem(expr.arg.arg, size=expr.stop) + return ExprMem(expr.arg.ptr, size=expr.stop) # distributivity of slice and & # (a & int)[x:y] => 0 if int[x:y] == 0 if expr.arg.is_op("&") and expr.arg.args[-1].is_int(): @@ -576,9 +576,9 @@ def simp_compose(e_s, expr): 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) + gap = e_s(nxt.ptr - arg.ptr) if gap.is_int() and arg.size % 8 == 0 and int(gap) == arg.size / 8: - args = args[:i] + [ExprMem(arg.arg, + args = args[:i] + [ExprMem(arg.ptr, arg.size + nxt.size)] + args[i + 2:] return ExprCompose(*args) @@ -664,8 +664,8 @@ 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 + if expr.ptr.is_cond(): + cond = expr.ptr ret = ExprCond(cond.cond, ExprMem(cond.src1, expr.size), ExprMem(cond.src2, expr.size)) @@ -884,35 +884,34 @@ def simp_cond_flag(expr_simp, expr): return expr -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)): +def simp_cmp_int(expr_simp, expr): + # ({X, 0} == int) => X == int[:] + # X + int1 == int2 => X == int2-int1 + if (expr.is_op(TOK_EQUAL) and + expr.args[1].is_int() and + expr.args[0].is_compose() and + len(expr.args[0].args) == 2 and + expr.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]) + src = expr.args[0].args[0] + int_val = int(expr.args[1]) new_int = ExprInt(int_val, src.size) expr = expr_simp( - ExprCond( - ExprOp(TOK_EQUAL, src, new_int), - expr.src1, - expr.src2) + ExprOp(TOK_EQUAL, src, new_int) ) - elif (expr.cond.is_op() and - expr.cond.op in [ + elif (expr.is_op() and + expr.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()): + expr.args[1].is_int() and + expr.args[0].is_op("+") and + expr.args[0].args[-1].is_int()): # X + int1 == int2 => X == int2-int1 - left, right = expr.cond.args + # WARNING: + # X - 0x10 <=u 0x20 gives X in [0x10 0x30] + # which is not equivalet to A <=u 0x10 + + left, right = expr.args left, int_diff = left.args[:-1], left.args[-1] if len(left) == 1: left = left[0] @@ -920,10 +919,7 @@ def simp_cond_int(expr_simp, expr): 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) + ExprOp(expr.op, left, new_int), ) return expr @@ -1047,6 +1043,20 @@ def simp_zeroext_eq_cst(expr_s, expr): return ExprInt(0, 1) return ExprOp(TOK_EQUAL, src, ExprInt(int(arg2), src.size)) +def simp_ext_eq_ext(expr_s, expr): + # A.zeroExt(X) == B.zeroExt(X) => A == B + # A.signExt(X) == B.signExt(X) => A == B + if not expr.is_op(TOK_EQUAL): + return expr + arg1, arg2 = expr.args + if (not ((arg1.is_op() and arg1.op.startswith("zeroExt") and + arg2.is_op() and arg2.op.startswith("zeroExt")) or + (arg1.is_op() and arg1.op.startswith("signExt") and + arg2.is_op() and arg2.op.startswith("signExt")))): + return expr + if arg1.args[0].size != arg2.args[0].size: + return expr + return ExprOp(TOK_EQUAL, arg1.args[0], arg2.args[0]) def simp_cond_eq_zero(expr_s, expr): # (X == 0)?(A:B) => X?(B:A) @@ -1058,3 +1068,73 @@ def simp_cond_eq_zero(expr_s, expr): return expr new_expr = ExprCond(arg1, expr.src2, expr.src1) return new_expr + + +def simp_cmp_int_int(expr_s, expr): + # IntA <s IntB => int + # IntA <u IntB => int + # IntA <=s IntB => int + # IntA <=u IntB => int + # IntA == IntB => int + if expr.op not in [ + TOK_EQUAL, + TOK_INF_SIGNED, TOK_INF_UNSIGNED, + TOK_INF_EQUAL_SIGNED, TOK_INF_EQUAL_UNSIGNED, + ]: + return expr + if not all(arg.is_int() for arg in expr.args): + return expr + int_a, int_b = expr.args + if expr.is_op(TOK_EQUAL): + if int_a == int_b: + return ExprInt(1, 1) + else: + return ExprInt(0, 1) + + if expr.op in [TOK_INF_SIGNED, TOK_INF_EQUAL_SIGNED]: + int_a = int(mod_size2int[int_a.size](int(int_a))) + int_b = int(mod_size2int[int_b.size](int(int_b))) + else: + int_a = int(mod_size2uint[int_a.size](int(int_a))) + int_b = int(mod_size2uint[int_b.size](int(int_b))) + + if expr.op in [TOK_INF_SIGNED, TOK_INF_UNSIGNED]: + ret = int_a < int_b + else: + ret = int_a <= int_b + + if ret: + ret = 1 + else: + ret = 0 + return ExprInt(ret, 1) + + +def simp_ext_cst(expr_s, expr): + # Int.zeroExt(X) => Int + # Int.signExt(X) => Int + if not (expr.op.startswith("zeroExt") or expr.op.startswith("signExt")): + return expr + arg = expr.args[0] + if not arg.is_int(): + return expr + if expr.op.startswith("zeroExt"): + ret = int(arg) + else: + ret = int(mod_size2int[arg.size](int(arg))) + ret = ExprInt(ret, expr.size) + return ret + + +def simp_slice_of_ext(expr_s, expr): + # zeroExt(X)[0:size(X)] => X + if expr.start != 0: + return expr + if not expr.arg.is_op(): + return expr + if not expr.arg.op.startswith("zeroExt"): + return expr + arg = expr.arg.args[0] + if arg.size != expr.size: + return expr + return arg |