diff options
Diffstat (limited to 'miasm2/expression')
| -rw-r--r-- | miasm2/expression/expression_reduce.py | 164 | ||||
| -rw-r--r-- | miasm2/expression/simplifications.py | 2 | ||||
| -rw-r--r-- | miasm2/expression/simplifications_common.py | 19 |
3 files changed, 154 insertions, 31 deletions
diff --git a/miasm2/expression/expression_reduce.py b/miasm2/expression/expression_reduce.py index 22ac8d8d..ab38dfdb 100644 --- a/miasm2/expression/expression_reduce.py +++ b/miasm2/expression/expression_reduce.py @@ -14,38 +14,128 @@ log_reduce.addHandler(console_handler) log_reduce.setLevel(logging.WARNING) + class ExprNode(object): """Clone of Expression object with additionnal information""" def __init__(self, expr): self.expr = expr - # Generic field to store custom node information - self.info = None - self.arg, self.args = None, None - self.cond, self.src1, self.src2 = None, None, None + +class ExprNodeInt(ExprNode): + def __init__(self, expr): + assert expr.is_int() + super(ExprNodeInt, self).__init__(expr) + self.arg = None + + def __repr__(self): + if self.info is not None: + out = repr(self.info) + else: + out = str(self.expr) + return out + + +class ExprNodeId(ExprNode): + def __init__(self, expr): + assert expr.is_id() + super(ExprNodeId, self).__init__(expr) + self.arg = None + + def __repr__(self): + if self.info is not None: + out = repr(self.info) + else: + out = str(self.expr) + return out + + +class ExprNodeLoc(ExprNode): + def __init__(self, expr): + assert expr.is_loc() + super(ExprNodeLoc, self).__init__(expr) + self.arg = None + + def __repr__(self): + if self.info is not None: + out = repr(self.info) + else: + out = str(self.expr) + return out + + +class ExprNodeMem(ExprNode): + def __init__(self, expr): + assert expr.is_mem() + super(ExprNodeMem, self).__init__(expr) + self.arg = None def __repr__(self): - expr = self.expr if self.info is not None: out = repr(self.info) - elif expr.is_int() or expr.is_id() or expr.is_loc(): - out = str(expr) - elif expr.is_mem(): + else: out = "@%d[%r]" % (self.expr.size, self.arg) - elif expr.is_slice(): - out = "%r[%d:%d]" % (self.arg, expr.start, expr.stop) - elif expr.is_op(): + return out + + +class ExprNodeOp(ExprNode): + def __init__(self, expr): + assert expr.is_op() + super(ExprNodeOp, self).__init__(expr) + self.args = None + + def __repr__(self): + if self.info is not None: + out = repr(self.info) + else: if len(self.args) == 1: - out = "(%s(%r))" % (expr.op, self.args[0]) + out = "(%s(%r))" % (self.expr.op, self.args[0]) else: - out = "(%s)" % expr.op.join(repr(arg) for arg in self.args) - elif expr.is_compose(): + out = "(%s)" % self.expr.op.join(repr(arg) for arg in self.args) + return out + + +class ExprNodeSlice(ExprNode): + def __init__(self, expr): + assert expr.is_slice() + super(ExprNodeSlice, self).__init__(expr) + self.arg = None + + def __repr__(self): + if self.info is not None: + out = repr(self.info) + else: + out = "%r[%d:%d]" % (self.arg, self.expr.start, self.expr.stop) + return out + + +class ExprNodeCompose(ExprNode): + def __init__(self, expr): + assert expr.is_compose() + super(ExprNodeCompose, self).__init__(expr) + self.args = None + + def __repr__(self): + if self.info is not None: + out = repr(self.info) + else: out = "{%s}" % ', '.join(repr(arg) for arg in self.args) - elif expr.is_cond(): - out = "(%r?%r:%r)" % (self.cond, self.src1, self.src2) + return out + + +class ExprNodeCond(ExprNode): + def __init__(self, expr): + assert expr.is_cond() + super(ExprNodeCond, self).__init__(expr) + self.cond = None + self.src1 = None + self.src2 = None + + def __repr__(self): + if self.info is not None: + out = repr(self.info) else: - raise TypeError("Unknown node Type %r", type(expr)) + out = "(%r?%r:%r)" % (self.cond, self.src1, self.src2) return out @@ -76,22 +166,30 @@ class ExprReducer(object): @expr: Expression to analyze """ - if isinstance(expr, (ExprId, ExprLoc, ExprInt)): - node = ExprNode(expr) - elif isinstance(expr, (ExprMem, ExprSlice)): + if isinstance(expr, ExprId): + node = ExprNodeId(expr) + elif isinstance(expr, ExprLoc): + node = ExprNodeLoc(expr) + elif isinstance(expr, ExprInt): + node = ExprNodeInt(expr) + elif isinstance(expr, ExprMem): + son = self.expr2node(expr.arg) + node = ExprNodeMem(expr) + node.arg = son + elif isinstance(expr, ExprSlice): son = self.expr2node(expr.arg) - node = ExprNode(expr) + node = ExprNodeSlice(expr) node.arg = son elif isinstance(expr, ExprOp): sons = [self.expr2node(arg) for arg in expr.args] - node = ExprNode(expr) + node = ExprNodeOp(expr) node.args = sons elif isinstance(expr, ExprCompose): sons = [self.expr2node(arg) for arg in expr.args] - node = ExprNode(expr) + node = ExprNodeCompose(expr) node.args = sons elif isinstance(expr, ExprCond): - node = ExprNode(expr) + node = ExprNodeCond(expr) node.cond = self.expr2node(expr.cond) node.src1 = self.expr2node(expr.src1) node.src2 = self.expr2node(expr.src2) @@ -118,15 +216,19 @@ class ExprReducer(object): expr = node.expr log_reduce.debug("\t" * lvl + "Reduce...: %s", node.expr) - if isinstance(expr, (ExprId, ExprInt, ExprLoc)): - pass + 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 = ExprNode(ExprMem(arg.expr, expr.size)) + node = ExprNodeMem(ExprMem(arg.expr, expr.size)) node.arg = arg elif isinstance(expr, ExprSlice): arg = self.categorize(node.arg, lvl=lvl + 1, **kwargs) - node = ExprNode(ExprSlice(arg.expr, expr.start, expr.stop)) + node = ExprNodeSlice(ExprSlice(arg.expr, expr.start, expr.stop)) node.arg = arg elif isinstance(expr, ExprOp): new_args = [] @@ -134,7 +236,7 @@ class ExprReducer(object): new_a = self.categorize(arg, lvl=lvl + 1, **kwargs) assert new_a.expr.size == arg.expr.size new_args.append(new_a) - node = ExprNode(ExprOp(expr.op, *[x.expr for x in new_args])) + node = ExprNodeOp(ExprOp(expr.op, *[x.expr for x in new_args])) node.args = new_args expr = node.expr elif isinstance(expr, ExprCompose): @@ -145,13 +247,13 @@ class ExprReducer(object): new_args.append(arg) new_expr_args.append(arg.expr) new_expr = ExprCompose(*new_expr_args) - node = ExprNode(new_expr) + 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 = ExprNode(ExprCond(cond.expr, src1.expr, src2.expr)) + 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)) diff --git a/miasm2/expression/simplifications.py b/miasm2/expression/simplifications.py index 712488e3..d3628ae8 100644 --- a/miasm2/expression/simplifications.py +++ b/miasm2/expression/simplifications.py @@ -42,6 +42,8 @@ class ExpressionSimplifier(object): simplifications_common.simp_subwc_cf, simplifications_common.simp_subwc_of, simplifications_common.simp_sign_subwc_cf, + simplifications_common.simp_double_zeroext, + simplifications_common.simp_double_signext, simplifications_common.simp_zeroext_eq_cst, ], diff --git a/miasm2/expression/simplifications_common.py b/miasm2/expression/simplifications_common.py index 5f947f8a..b01b1d1d 100644 --- a/miasm2/expression/simplifications_common.py +++ b/miasm2/expression/simplifications_common.py @@ -987,6 +987,25 @@ def simp_sign_subwc_cf(expr_s, expr): return ExprOp("FLAG_SIGN_SUB", op1, op2) +def simp_double_zeroext(expr_s, expr): + # A.zeroExt(X).zeroExt(Y) => A.zeroExt(Y) + if not (expr.is_op() and expr.op.startswith("zeroExt")): + return expr + arg1 = expr.args[0] + if not (arg1.is_op() and arg1.op.startswith("zeroExt")): + return expr + arg2 = arg1.args[0] + return ExprOp(expr.op, arg2) + +def simp_double_signext(expr_s, expr): + # A.signExt(X).signExt(Y) => A.signExt(Y) + if not (expr.is_op() and expr.op.startswith("signExt")): + return expr + arg1 = expr.args[0] + if not (arg1.is_op() and arg1.op.startswith("signExt")): + return expr + arg2 = arg1.args[0] + return ExprOp(expr.op, arg2) def simp_zeroext_eq_cst(expr_s, expr): # A.zeroExt(X) == int => A == int[:A.size] |