about summary refs log tree commit diff stats
path: root/example/expression/expr_reduce.py
diff options
context:
space:
mode:
Diffstat (limited to 'example/expression/expr_reduce.py')
-rw-r--r--example/expression/expr_reduce.py93
1 files changed, 93 insertions, 0 deletions
diff --git a/example/expression/expr_reduce.py b/example/expression/expr_reduce.py
new file mode 100644
index 00000000..b5fc96c8
--- /dev/null
+++ b/example/expression/expr_reduce.py
@@ -0,0 +1,93 @@
+from miasm2.expression.expression import ExprId, ExprInt, ExprMem
+from miasm2.expression.expression_reduce import ExprReducer
+
+
+class StructLookup(ExprReducer):
+    """
+    ExprReduce example.
+    This example retrieve the nature of a given expression
+    Input:
+    ECX is a pointer on a structure STRUCT_A
+
+    Reduction rules:
+    ECX              -> FIELD_A_PTR
+    ECX + CST        -> FIELD_A_PTR
+    ECX + CST*CST... -> FIELD_A_PTR
+    @ECX             -> FIELD_A
+    @(ECX + CST)     -> FIELD_A
+    """
+    CST = "CST"
+    FIELD_A_PTR = "FIELD_A_PTR"
+    FIELD_A = "FIELD_A"
+
+    def reduce_int(self, node, _):
+        """
+        Reduction: int -> CST
+        """
+        if node.expr.is_int():
+            return self.CST
+        return None
+
+    def reduce_ptr_struct(self, node, _):
+        """
+        Reduction: ECX -> FIELD_A_PTR
+        """
+        if node.expr.is_id("ECX"):
+            return self.FIELD_A_PTR
+        return None
+
+    def reduce_ptr_plus_int(self, node, _):
+        """
+        Reduction: ECX + CST -> FIELD_A_PTR
+        """
+        if not node.expr.is_op('+'):
+            return None
+        if [arg.info for arg in node.args] == [self.FIELD_A_PTR, self.CST]:
+            return self.FIELD_A_PTR
+        return None
+
+    def reduce_cst_op(self, node, _):
+        """
+        Reduction: CST + CST -> CST
+        """
+        if not node.expr.is_op():
+            return None
+        if set(arg.info for arg in node.args) == set([self.CST]):
+            return self.CST
+        return None
+
+    def reduce_at_struct_ptr(self, node, _):
+        """
+        Reduction: @FIELD_A_PTR -> FIELD_A
+        """
+        if not node.expr.is_mem():
+            return None
+        return self.FIELD_A
+
+    reduction_rules = [reduce_int,
+                       reduce_ptr_struct,
+                       reduce_ptr_plus_int,
+                       reduce_cst_op,
+                       reduce_at_struct_ptr
+                      ]
+
+
+def test():
+    struct_lookup = StructLookup()
+
+    ptr = ExprId('ECX')
+    int4 = ExprInt(4, 32)
+    tests = [
+        (ptr, StructLookup.FIELD_A_PTR),
+        (ptr + int4, StructLookup.FIELD_A_PTR),
+        (ptr + int4 * int4, StructLookup.FIELD_A_PTR),
+        (ExprMem(ptr), StructLookup.FIELD_A),
+        (ExprMem(ptr + int4 * int4), StructLookup.FIELD_A),
+    ]
+
+    for expr_in, result in tests:
+        assert struct_lookup.reduce(expr_in).info == result
+
+
+if __name__ == "__main__":
+    test()