about summary refs log tree commit diff stats
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--miasm2/arch/mips32/arch.py4
-rw-r--r--miasm2/core/asmbloc.py80
-rw-r--r--miasm2/core/parse_asm.py13
3 files changed, 64 insertions, 33 deletions
diff --git a/miasm2/arch/mips32/arch.py b/miasm2/arch/mips32/arch.py
index a5463b6f..f64e09e5 100644
--- a/miasm2/arch/mips32/arch.py
+++ b/miasm2/arch/mips32/arch.py
@@ -189,7 +189,7 @@ class instruction_mips32(cpu.instruction):
 
 
 class mn_mips32(cpu.cls_mn):
-    delayslot = 0
+    delayslot = 1
     name = "mips32"
     regs = regs
     bintree = {}
@@ -297,7 +297,7 @@ class mips32_fccreg(mips32_reg):
     parser = reg_info.parser
 
 class mips32_imm(cpu.imm_noarg):
-    parser = cpu.base_expr
+    parser = base_expr
 
 
 class mips32_s16imm_noarg(mips32_imm):
diff --git a/miasm2/core/asmbloc.py b/miasm2/core/asmbloc.py
index fb910b3a..904ccfdc 100644
--- a/miasm2/core/asmbloc.py
+++ b/miasm2/core/asmbloc.py
@@ -77,7 +77,10 @@ class asm_constraint(object):
     c_next = "c_next"
     c_bad = "c_bad"
 
-    def __init__(self, label=None, c_t=c_to):
+    def __init__(self, label, c_t=c_to):
+        # Sanity check
+        assert isinstance(label, asm_label)
+
         self.label = label
         self.c_t = c_t
 
@@ -87,21 +90,21 @@ class asm_constraint(object):
 
 class asm_constraint_next(asm_constraint):
 
-    def __init__(self, label=None):
+    def __init__(self, label):
         super(asm_constraint_next, self).__init__(
             label, c_t=asm_constraint.c_next)
 
 
 class asm_constraint_to(asm_constraint):
 
-    def __init__(self, label=None):
+    def __init__(self, label):
         super(asm_constraint_to, self).__init__(
             label, c_t=asm_constraint.c_to)
 
 
 class asm_constraint_bad(asm_constraint):
 
-    def __init__(self, label=None):
+    def __init__(self, label):
         super(asm_constraint_bad, self).__init__(
             label, c_t=asm_constraint.c_bad)
 
@@ -218,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:
 
@@ -431,13 +474,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,
@@ -455,8 +500,6 @@ def split_bloc(mnemo, attrib, pool_bin, blocs,
     bloc_dst = [symbol_pool._offset2label[x] for x in more_ref]
     for b in blocs:
         for c in b.bto:
-            if not isinstance(c.label, asm_label):
-                continue
             if c.c_t == asm_constraint.c_bad:
                 continue
             bloc_dst.append(c.label)
@@ -479,9 +522,7 @@ def split_bloc(mnemo, attrib, pool_bin, blocs,
                 log_asmbloc.error("cannot split %x!!", off)
                 continue
             if dis_bloc_callback:
-                offsets_to_dis = set(
-                    [x.label.offset for x in new_b.bto
-                     if isinstance(x.label, asm_label)])
+                offsets_to_dis = set(x.label.offset for x in new_b.bto)
                 dis_bloc_callback(mn=mnemo, attrib=attrib, pool_bin=pool_bin,
                                   cur_bloc=new_b, offsets_to_dis=offsets_to_dis,
                                   symbol_pool=symbol_pool)
@@ -582,15 +623,7 @@ def bloc2graph(blocks, label=False, lines=True):
     # Generate links
     for block in blocks:
         for next_b in block.bto:
-            if (isinstance(next_b.label, m2_expr.ExprId) or
-                    isinstance(next_b.label, asm_label)):
-                src, dst, cst = block.label.name, next_b.label.name, next_b.c_t
-            else:
-                continue
-            if isinstance(src, asm_label):
-                src = src.name
-            if isinstance(dst, asm_label):
-                dst = dst.name
+            src, dst, cst = block.label.name, next_b.label.name, next_b.c_t
 
             edge_color = "black"
             if next_b.c_t == asm_constraint.c_next:
@@ -1099,8 +1132,7 @@ class basicblocs:
         self.blocs[b.label] = b
         self.g.add_node(b.label)
         for dst in b.bto:
-            if isinstance(dst.label, asm_label):
-                self.g.add_edge(b.label, dst.label)
+            self.g.add_edge(b.label, dst.label)
 
     def add_blocs(self, ab):
         for b in ab:
@@ -1118,7 +1150,7 @@ class basicblocs:
 def find_parents(blocs, l):
     p = set()
     for b in blocs:
-        if l in [x.label for x in b.bto if isinstance(x.label, asm_label)]:
+        if l in [x.label for x in b.bto]:
             p.add(b.label)
     return p
 
@@ -1266,8 +1298,6 @@ def bloc_merge(blocs, dont_merge=[]):
 
         # update parents
         for s in b.bto:
-            if not isinstance(s.label, asm_label):
-                continue
             if s.label.name == None:
                 continue
             if not s.label in blocby_label:
diff --git a/miasm2/core/parse_asm.py b/miasm2/core/parse_asm.py
index 646ad445..e55a9af8 100644
--- a/miasm2/core/parse_asm.py
+++ b/miasm2/core/parse_asm.py
@@ -238,10 +238,9 @@ def parse_txt(mnemo, attrib, txt, symbol_pool=None):
     delayslot = 0
     while i < len(lines):
         if delayslot:
+            delayslot -= 1
             if delayslot == 0:
                 state = STATE_NO_BLOC
-            else:
-                delayslot -= 1
         line = lines[i]
         # no current block
         if state == STATE_NO_BLOC:
@@ -306,18 +305,20 @@ def parse_txt(mnemo, attrib, txt, symbol_pool=None):
                             continue
                         if dst in mnemo.regs.all_regs_ids:
                             continue
-                        cur_block.addto(asmbloc.asm_constraint(dst, C_TO))
+                        cur_block.addto(asmbloc.asm_constraint(dst.name, C_TO))
 
                 if not line.splitflow():
                     block_to_nlink = None
 
-                delayslot = line.delayslot
-                if delayslot == 0:
-                    state = STATE_NO_BLOC
+                delayslot = line.delayslot + 1
             else:
                 raise RuntimeError("unknown class %s" % line.__class__)
         i += 1
 
     for block in blocks:
+        # Fix multiple constraints
+        block.fix_constraints()
+
+        # Log block
         asmbloc.log_asmbloc.info(block)
     return blocks, symbol_pool