about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--example/expression/expr_translate.py11
-rw-r--r--miasm/analysis/data_flow.py26
-rw-r--r--miasm/arch/aarch64/arch.py3
-rw-r--r--miasm/ir/translators/python.py5
-rw-r--r--miasm/ir/translators/smt2.py4
-rw-r--r--test/arch/aarch64/arch.py2
6 files changed, 42 insertions, 9 deletions
diff --git a/example/expression/expr_translate.py b/example/expression/expr_translate.py
index 8562975f..31408566 100644
--- a/example/expression/expr_translate.py
+++ b/example/expression/expr_translate.py
@@ -45,3 +45,14 @@ print("-> 0x%x" % eval(target_exprs["Python"]))
 print("[+] Validate the Miasm syntax rebuilding")
 exprRebuild = eval(target_exprs["Miasm"])
 assert(expr == exprRebuild)
+
+
+a = ExprId("a", 32)
+b = ExprId("b", 32)
+cst1 = ExprInt(1, 32)
+eq_test = ExprOp("==", a, b + cst1)
+
+for lang in Translator.available_languages():
+    translator = Translator.to_language(lang)
+    print("Translate to %s:" % lang)
+    print(translator.from_expr(eq_test))
diff --git a/miasm/analysis/data_flow.py b/miasm/analysis/data_flow.py
index 40153f8b..0a96ae8d 100644
--- a/miasm/analysis/data_flow.py
+++ b/miasm/analysis/data_flow.py
@@ -1755,6 +1755,9 @@ class State(object):
         self.equivalence_classes = UnionFind()
         self.undefined = set()
 
+    def __str__(self):
+        return "{0.equivalence_classes}\n{0.undefined}".format(self)
+
     def copy(self):
         state = self.__class__()
         state.equivalence_classes = self.equivalence_classes.copy()
@@ -1983,6 +1986,9 @@ class State(object):
     def merge(self, other):
         """
         Merge the current state with @other
+        Merge rules:
+        - if two nodes are equal in both states => in equivalence class
+        - if node value is different or non present in another state => undefined
         @other: State instance
         """
         classes1 = self.equivalence_classes
@@ -2000,6 +2006,7 @@ class State(object):
             for node in component:
                 node_to_component2[node] = component
 
+        # Compute intersection of equivalence classes of states
         out = []
         nodes_ok = set()
         while components1:
@@ -2016,14 +2023,18 @@ class State(object):
                     continue
                 if node not in component2:
                     continue
+                # Found two classes containing node
                 common = component1.intersection(component2)
                 if len(common) == 1:
+                    # Intersection contains only one node => undefine node
                     if node.is_id() or node.is_mem():
                         assert(node not in nodes_ok)
                         undefined.add(node)
                         component2.discard(common.pop())
                     continue
                 if common:
+                    # Intersection contains multiple nodes
+                    # Here, common nodes don't interfer with any undefined
                     nodes_ok.update(common)
                     out.append(common)
                 diff = component1.difference(common)
@@ -2104,7 +2115,7 @@ class PropagateExpressions(object):
         """
         Merge predecessors states of irblock at location @loc_key
         @ircfg: IRCfg instance
-        @sates: Dictionary linking locations to state
+        @states: Dictionary linking locations to state
         @loc_key: location of the current irblock
         """
 
@@ -2176,15 +2187,14 @@ class PropagateExpressions(object):
             state = state.copy()
 
             new_irblock, modified_irblock = self.update_state(irblock, state)
-            if (
-                    state_orig is not None and
-                    state.equivalence_classes == state_orig.equivalence_classes and
+            if state_orig is not None:
+                # Merge current and previous state
+                state = state.merge(state_orig)
+                if (state.equivalence_classes == state_orig.equivalence_classes and
                     state.undefined == state_orig.undefined
-            ):
-                continue
+                    ):
+                    continue
 
-            if state_orig:
-                state.undefined.update(state_orig.undefined)
             states[loc_key] = state
             # Propagate to sons
             for successor in ircfg.successors(loc_key):
diff --git a/miasm/arch/aarch64/arch.py b/miasm/arch/aarch64/arch.py
index 16fbcaea..25bf5c12 100644
--- a/miasm/arch/aarch64/arch.py
+++ b/miasm/arch/aarch64/arch.py
@@ -1738,6 +1738,7 @@ simm7 = bs(l=7, cls=(aarch64_int64_noarg,), fname="imm", order=-1)
 nzcv = bs(l=4, cls=(aarch64_uint64_noarg, aarch64_arg), fname="nzcv", order=-1)
 uimm4 = bs(l=4, cls=(aarch64_uint64_noarg, aarch64_arg), fname="imm", order=-1)
 uimm5 = bs(l=5, cls=(aarch64_uint64_noarg, aarch64_arg), fname="imm", order=-1)
+uimm6 = bs(l=6, cls=(aarch64_uint64_noarg, aarch64_arg), fname="imm", order=-1)
 uimm12 = bs(l=12, cls=(aarch64_uint64_noarg,), fname="imm", order=-1)
 uimm16 = bs(l=16, cls=(aarch64_uint64_noarg, aarch64_arg), fname="imm", order=-1)
 uimm7 = bs(l=7, cls=(aarch64_uint64_noarg,), fname="imm", order=-1)
@@ -2136,7 +2137,7 @@ aarch64op("udiv", [sf, bs('0'), bs('0'), bs('11010110'), rm, bs('00001'), bs('0'
 
 
 # extract register p.150
-aarch64op("extr", [sf, bs('00100111'), bs(l=1, cls=(aarch64_eq,), ref="sf"), bs('0'), rm, simm6, rn, rd], [rd, rn, rm, simm6])
+aarch64op("extr", [sf, bs('00100111'), bs(l=1, cls=(aarch64_eq,), ref="sf"), bs('0'), rm, uimm6, rn, rd], [rd, rn, rm, uimm6])
 
 # shift reg p.155
 shiftr_name = {'LSL': 0b00, 'LSR': 0b01, 'ASR': 0b10, 'ROR': 0b11}
diff --git a/miasm/ir/translators/python.py b/miasm/ir/translators/python.py
index 0da2318d..4e5cc5e1 100644
--- a/miasm/ir/translators/python.py
+++ b/miasm/ir/translators/python.py
@@ -1,6 +1,7 @@
 from builtins import map
 from miasm.expression.expression import ExprInt
 from miasm.ir.translators.translator import Translator
+from miasm.expression.expression import ExprCond, ExprInt
 
 
 class TranslatorPython(Translator):
@@ -71,6 +72,10 @@ class TranslatorPython(Translator):
                 )
         elif expr.op == "parity":
             return "(%s & 0x1)" % self.from_expr(expr.args[0])
+        elif expr.op == "==":
+            return self.from_expr(
+                ExprCond(expr.args[0] - expr.args[1], ExprInt(0, 1), ExprInt(1, 1))
+            )
 
         elif expr.op in ["<<<", ">>>"]:
             amount_raw = expr.args[1]
diff --git a/miasm/ir/translators/smt2.py b/miasm/ir/translators/smt2.py
index c4260eb4..d3366b8b 100644
--- a/miasm/ir/translators/smt2.py
+++ b/miasm/ir/translators/smt2.py
@@ -4,6 +4,8 @@ import logging
 
 from miasm.ir.translators.translator import Translator
 from miasm.expression.smt2_helper import *
+from miasm.expression.expression import ExprCond, ExprInt
+
 
 log = logging.getLogger("translator_smt2")
 console_handler = logging.StreamHandler()
@@ -226,6 +228,8 @@ class TranslatorSMT2(Translator):
                     res = bv_rotate_left(res, arg, expr.size)
                 elif expr.op == ">>>":
                     res = bv_rotate_right(res, arg, expr.size)
+                elif expr.op == "==":
+                    res = self.from_expr(ExprCond(expr.args[0] - expr.args[1], ExprInt(0, 1), ExprInt(1, 1)))
                 else:
                     raise NotImplementedError("Unsupported OP yet: %s" % expr.op)
         elif expr.op == 'parity':
diff --git a/test/arch/aarch64/arch.py b/test/arch/aarch64/arch.py
index c78007b8..dc505bdd 100644
--- a/test/arch/aarch64/arch.py
+++ b/test/arch/aarch64/arch.py
@@ -1730,6 +1730,8 @@ reg_tests_aarch64 = [
 
     ("0006C588    EXTR       W2, W2, W2, 0x1F",
      "427C8213"),
+    ("XXXXXXXX    EXTR       X12, X12, X12, 0x20",
+     "8C81CC93"),
 
     ("00458AB8    CCMP       X3, X5, 0x8, GE",
      "68A045FA"),