about summary refs log tree commit diff stats
path: root/src/miasm/expression/simplifications.py
diff options
context:
space:
mode:
authorTheofilos Augoustis <theofilos.augoustis@gmail.com>2025-10-14 09:09:29 +0000
committerTheofilos Augoustis <theofilos.augoustis@gmail.com>2025-10-14 09:09:29 +0000
commit579cf1d03fb932083e6317967d1613d5c2587fb6 (patch)
tree629f039935382a2a7391bce9253f6c9968159049 /src/miasm/expression/simplifications.py
parent51c15d3ea2e16d4fc5f0f01a3b9befc66b1f982e (diff)
downloadmiasm-579cf1d03fb932083e6317967d1613d5c2587fb6.tar.gz
miasm-579cf1d03fb932083e6317967d1613d5c2587fb6.zip
Convert to src-layout ta/nix
Diffstat (limited to 'src/miasm/expression/simplifications.py')
-rw-r--r--src/miasm/expression/simplifications.py201
1 files changed, 201 insertions, 0 deletions
diff --git a/src/miasm/expression/simplifications.py b/src/miasm/expression/simplifications.py
new file mode 100644
index 00000000..88e59983
--- /dev/null
+++ b/src/miasm/expression/simplifications.py
@@ -0,0 +1,201 @@
+#                                                                              #
+#                     Simplification methods library                           #
+#                                                                              #
+
+import logging
+
+from future.utils import viewitems
+
+from miasm.expression import simplifications_common
+from miasm.expression import simplifications_cond
+from miasm.expression import simplifications_explicit
+from miasm.expression.expression_helper import fast_unify
+import miasm.expression.expression as m2_expr
+from miasm.expression.expression import ExprVisitorCallbackBottomToTop
+
+# Expression Simplifier
+# ---------------------
+
+log_exprsimp = logging.getLogger("exprsimp")
+console_handler = logging.StreamHandler()
+console_handler.setFormatter(logging.Formatter("[%(levelname)-8s]: %(message)s"))
+log_exprsimp.addHandler(console_handler)
+log_exprsimp.setLevel(logging.WARNING)
+
+
+class ExpressionSimplifier(ExprVisitorCallbackBottomToTop):
+
+    """Wrapper on expression simplification passes.
+
+    Instance handle passes lists.
+
+    Available passes lists are:
+     - commons: common passes such as constant folding
+     - heavy  : rare passes (for instance, in case of obfuscation)
+    """
+
+    # Common passes
+    PASS_COMMONS = {
+        m2_expr.ExprOp: [
+            simplifications_common.simp_cst_propagation,
+            simplifications_common.simp_cond_op_int,
+            simplifications_common.simp_cond_factor,
+            simplifications_common.simp_add_multiple,
+            # CC op
+            simplifications_common.simp_cc_conds,
+            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,
+            simplifications_common.simp_ext_eq_ext,
+            simplifications_common.simp_ext_cond_int,
+            simplifications_common.simp_sub_cf_zero,
+
+            simplifications_common.simp_cmp_int,
+            simplifications_common.simp_cmp_bijective_op,
+            simplifications_common.simp_sign_inf_zeroext,
+            simplifications_common.simp_cmp_int_int,
+            simplifications_common.simp_ext_cst,
+            simplifications_common.simp_zeroext_and_cst_eq_cst,
+            simplifications_common.simp_test_signext_inf,
+            simplifications_common.simp_test_zeroext_inf,
+            simplifications_common.simp_cond_inf_eq_unsigned_zero,
+            simplifications_common.simp_compose_and_mask,
+            simplifications_common.simp_bcdadd_cf,
+            simplifications_common.simp_bcdadd,
+            simplifications_common.simp_smod_sext,
+            simplifications_common.simp_flag_cst,
+        ],
+
+        m2_expr.ExprSlice: [
+            simplifications_common.simp_slice,
+            simplifications_common.simp_slice_of_ext,
+            simplifications_common.simp_slice_of_sext,
+            simplifications_common.simp_slice_of_op_ext,
+        ],
+        m2_expr.ExprCompose: [simplifications_common.simp_compose],
+        m2_expr.ExprCond: [
+            simplifications_common.simp_cond,
+            simplifications_common.simp_cond_zeroext,
+            simplifications_common.simp_cond_add,
+            # CC op
+            simplifications_common.simp_cond_flag,
+            simplifications_common.simp_cmp_int_arg,
+
+            simplifications_common.simp_cond_eq_zero,
+            simplifications_common.simp_x_and_cst_eq_cst,
+            simplifications_common.simp_cond_logic_ext,
+            simplifications_common.simp_cond_sign_bit,
+            simplifications_common.simp_cond_eq_1_0,
+            simplifications_common.simp_cond_cc_flag,
+            simplifications_common.simp_cond_sub_cf,
+        ],
+        m2_expr.ExprMem: [simplifications_common.simp_mem],
+
+    }
+
+
+    # Heavy passes
+    PASS_HEAVY = {}
+
+    # Cond passes
+    PASS_COND = {
+        m2_expr.ExprSlice: [
+            simplifications_cond.expr_simp_inf_signed,
+            simplifications_cond.expr_simp_inf_unsigned_inversed
+        ],
+        m2_expr.ExprOp: [
+            simplifications_cond.expr_simp_inverse,
+        ],
+        m2_expr.ExprCond: [
+            simplifications_cond.expr_simp_equal
+        ]
+    }
+
+
+    # Available passes lists are:
+    #  - highlevel: transform high level operators to explicit computations
+    PASS_HIGH_TO_EXPLICIT = {
+        m2_expr.ExprOp: [
+            simplifications_explicit.simp_flags,
+            simplifications_explicit.simp_ext,
+        ],
+    }
+
+
+    def __init__(self):
+        super(ExpressionSimplifier, self).__init__(self.expr_simp_inner)
+        self.expr_simp_cb = {}
+
+    def enable_passes(self, passes):
+        """Add passes from @passes
+        @passes: dict(Expr class : list(callback))
+
+        Callback signature: Expr callback(ExpressionSimplifier, Expr)
+        """
+
+        # Clear cache of simplifiied expressions when adding a new pass
+        self.cache.clear()
+
+        for k, v in viewitems(passes):
+            self.expr_simp_cb[k] = fast_unify(self.expr_simp_cb.get(k, []) + v)
+
+    def apply_simp(self, expression):
+        """Apply enabled simplifications on expression
+        @expression: Expr instance
+        Return an Expr instance"""
+
+        cls = expression.__class__
+        debug_level = log_exprsimp.level >= logging.DEBUG
+        for simp_func in self.expr_simp_cb.get(cls, []):
+            # Apply simplifications
+            before = expression
+            expression = simp_func(self, expression)
+            after = expression
+
+            if debug_level and before != after:
+                log_exprsimp.debug("[%s] %s => %s", simp_func, before, after)
+
+            # If class changes, stop to prevent wrong simplifications
+            if expression.__class__ is not cls:
+                break
+
+        return expression
+
+    def expr_simp_inner(self, expression):
+        """Apply enabled simplifications on expression and find a stable state
+        @expression: Expr instance
+        Return an Expr instance"""
+
+        # Find a stable state
+        while True:
+            # Canonize and simplify
+            new_expr = self.apply_simp(expression.canonize())
+            if new_expr == expression:
+                return new_expr
+            # Run recursively simplification on fresh new expression
+            new_expr = self.visit(new_expr)
+            expression = new_expr
+        return new_expr
+
+    def expr_simp(self, expression):
+        "Call simplification recursively"
+        return self.visit(expression)
+
+    def __call__(self, expression):
+        "Call simplification recursively"
+        return self.visit(expression)
+
+
+# Public ExprSimplificationPass instance with commons passes
+expr_simp = ExpressionSimplifier()
+expr_simp.enable_passes(ExpressionSimplifier.PASS_COMMONS)
+
+expr_simp_high_to_explicit = ExpressionSimplifier()
+expr_simp_high_to_explicit.enable_passes(ExpressionSimplifier.PASS_HIGH_TO_EXPLICIT)
+
+expr_simp_explicit = ExpressionSimplifier()
+expr_simp_explicit.enable_passes(ExpressionSimplifier.PASS_COMMONS)
+expr_simp_explicit.enable_passes(ExpressionSimplifier.PASS_HIGH_TO_EXPLICIT)