about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--miasm2/core/asmbloc.py46
-rw-r--r--miasm2/core/parse_asm.py4
2 files changed, 48 insertions, 2 deletions
diff --git a/miasm2/core/asmbloc.py b/miasm2/core/asmbloc.py
index e44f27ed..203a49f0 100644
--- a/miasm2/core/asmbloc.py
+++ b/miasm2/core/asmbloc.py
@@ -221,6 +221,46 @@ class asm_bloc(object):
                 return x.label
         return None
 
+    @staticmethod
+    def _filter_constraint(constraints):
+        """Sort and filter @constraints for asm_bloc.bto
+        @constraints: non-empty set of asm_constraint instance
+
+        Always the same type -> one of the constraint
+        c_bad and something -> error
+        c_next and c_to -> c_next
+        """
+        # Only one constraint
+        if len(constraints) == 1:
+            return next(iter(constraints))
+
+        # Constraint type -> set of corresponding constraint
+        cbytype = {}
+        for cons in constraints:
+            cbytype.setdefault(cons.c_t, set()).add(cons)
+
+        # Only one type -> any constraint is OK
+        if len(cbytype) == 1:
+            return next(iter(constraints))
+
+        # At least one c_bad and one other constraint
+        if asm_constraint.c_bad in cbytype:
+            raise RuntimeError("Bad type of constraints for the same destination")
+
+        # At least 2 types, c_bad not in types -> types = {c_next, c_to}
+        # c_to is included in c_next
+        return next(iter(cbytype[asm_constraint.c_next]))
+
+    def fix_constraints(self):
+        """Fix next block constraints"""
+        # destination -> associated constraints
+        dests = {}
+        for constraint in self.bto:
+            dests.setdefault(constraint.label, set()).add(constraint)
+
+        self.bto = set(self._filter_constraint(constraints)
+                       for constraints in dests.itervalues())
+
 
 class asm_symbol_pool:
 
@@ -435,13 +475,15 @@ def dis_bloc(mnemo, pool_bin, cur_bloc, offset, job_done, symbol_pool,
     for c in cur_bloc.bto:
         if c.c_t == asm_constraint.c_bad:
             continue
-        if isinstance(c.label, asm_label):
-            offsets_to_dis.add(c.label.offset)
+        offsets_to_dis.add(c.label.offset)
 
     if add_next_offset:
         cur_bloc.add_cst(offset, asm_constraint.c_next, symbol_pool)
         offsets_to_dis.add(offset)
 
+    # Fix multiple constraints
+    cur_bloc.fix_constraints()
+
     if dis_bloc_callback is not None:
         dis_bloc_callback(mn=mnemo, attrib=attrib, pool_bin=pool_bin,
                           cur_bloc=cur_bloc, offsets_to_dis=offsets_to_dis,
diff --git a/miasm2/core/parse_asm.py b/miasm2/core/parse_asm.py
index 5437ca22..e55a9af8 100644
--- a/miasm2/core/parse_asm.py
+++ b/miasm2/core/parse_asm.py
@@ -316,5 +316,9 @@ def parse_txt(mnemo, attrib, txt, symbol_pool=None):
         i += 1
 
     for block in blocks:
+        # Fix multiple constraints
+        block.fix_constraints()
+
+        # Log block
         asmbloc.log_asmbloc.info(block)
     return blocks, symbol_pool