about summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--miasm/analysis/data_flow.py24
-rw-r--r--miasm/analysis/simplifier.py41
-rw-r--r--miasm/analysis/ssa.py24
3 files changed, 47 insertions, 42 deletions
diff --git a/miasm/analysis/data_flow.py b/miasm/analysis/data_flow.py
index 57837a5d..7bd6d72f 100644
--- a/miasm/analysis/data_flow.py
+++ b/miasm/analysis/data_flow.py
@@ -852,26 +852,6 @@ class PropagateThroughExprId(object):
                     def_dct[dst] = node, index
         return def_dct
 
-    def phi_has_identical_sources(self, ssa, def_dct, var):
-        """
-        If phi operation has identical source values, return it; else None
-        @ssa: SSADiGraph instance
-        @def_dct: dictionary linking variable to its assignment location
-        @var: Phi destination variable
-        """
-        loc_key, index = def_dct[var]
-        sources = ssa.graph.blocks[loc_key][index][var]
-        assert sources.is_op('Phi')
-        sources_values = set()
-        for src in sources.args:
-            assert src in def_dct
-            loc_key, index = def_dct[src]
-            value = ssa.graph.blocks[loc_key][index][src]
-            sources_values.add(value)
-        if len(sources_values) != 1:
-            return None
-        return list(sources_values)[0]
-
     def get_candidates(self, ssa, head, max_expr_depth):
         def_dct = self.get_var_definitions(ssa)
         defuse = SSADefUse.from_ssa(ssa)
@@ -888,10 +868,6 @@ class PropagateThroughExprId(object):
             if node.var.is_mem():
                 continue
             if src.is_op('Phi'):
-                ret = self.phi_has_identical_sources(ssa, def_dct, node.var)
-                if ret:
-                    to_replace[node.var] = ret
-                    node_to_reg[node] = node.var
                 continue
             to_replace[node.var] = src
             node_to_reg[node] = node.var
diff --git a/miasm/analysis/simplifier.py b/miasm/analysis/simplifier.py
index a8cd4eb8..8e9005a8 100644
--- a/miasm/analysis/simplifier.py
+++ b/miasm/analysis/simplifier.py
@@ -171,6 +171,9 @@ class IRCFGSimplifierSSA(IRCFGSimplifierCommon):
             self.do_propagate_mem,
             self.do_propagate_expr,
             self.do_dead_simp_ssa,
+            self.do_remove_empty_assignblks,
+            self.do_del_unused_edges,
+            self.do_merge_blocks,
         ]
 
 
@@ -222,8 +225,15 @@ class IRCFGSimplifierSSA(IRCFGSimplifierCommon):
         @head: Location instance of the graph head
         """
         modified = self.propag_int.propagate(ssa, head)
-        modified |= ssa.graph.simplify(self.expr_simp)
-        modified |= del_unused_edges(ssa.graph, set([head]))
+        return modified
+
+    @fix_point
+    def do_del_unused_edges(self, ssa, head):
+        """
+        Del unused edges of the ssa graph
+        @head: Location instance of the graph head
+        """
+        modified = del_unused_edges(ssa.graph, set([head]))
         return modified
 
     @fix_point
@@ -233,8 +243,6 @@ class IRCFGSimplifierSSA(IRCFGSimplifierCommon):
         @head: Location instance of the graph head
         """
         modified = self.propag_mem.propagate(ssa, head)
-        modified |= ssa.graph.simplify(self.expr_simp)
-        modified |= del_unused_edges(ssa.graph, set([head]))
         return modified
 
     @fix_point
@@ -244,8 +252,24 @@ class IRCFGSimplifierSSA(IRCFGSimplifierCommon):
         @head: Location instance of the graph head
         """
         modified = self.propag_expr.propagate(ssa, head)
-        modified |= ssa.graph.simplify(self.expr_simp)
-        modified |= del_unused_edges(ssa.graph, set([head]))
+        return modified
+
+    @fix_point
+    def do_remove_empty_assignblks(self, ssa, head):
+        """
+        Remove empty assignblks
+        @head: Location instance of the graph head
+        """
+        modified = remove_empty_assignblks(ssa.graph)
+        return modified
+
+    @fix_point
+    def do_merge_blocks(self, ssa, head):
+        """
+        Merge blocks with one parent/son
+        @head: Location instance of the graph head
+        """
+        modified = merge_blocks(ssa.graph, set([head]))
         return modified
 
     @fix_point
@@ -262,10 +286,7 @@ class IRCFGSimplifierSSA(IRCFGSimplifierCommon):
         @ircfg: IRCFG instance to simplify
         @head: Location instance of the ircfg head
         """
-        modified = self.deadremoval(ssa)
-        modified |= remove_empty_assignblks(ssa.graph)
-        modified |= del_unused_edges(ssa.graph, set([head]))
-        modified |= merge_blocks(ssa.graph, set([head]))
+        modified = self.deadremoval(ssa.graph)
         return modified
 
     def do_simplify(self, ssa, head):
diff --git a/miasm/analysis/ssa.py b/miasm/analysis/ssa.py
index 827be009..7f0b0f13 100644
--- a/miasm/analysis/ssa.py
+++ b/miasm/analysis/ssa.py
@@ -73,9 +73,6 @@ class SSA(object):
         # IRCFG instance
         self.ircfg = ircfg
 
-        # SSA blocks
-        self.blocks = {}
-
         # stack for RHS
         self._stack_rhs = {}
         # stack for LHS
@@ -120,7 +117,6 @@ class SSA(object):
 
     def reset(self):
         """Resets SSA transformation"""
-        self.blocks = {}
         self.expressions = {}
         self._stack_rhs = {}
         self._stack_lhs = {}
@@ -427,12 +423,13 @@ class SSADiGraph(SSA):
         a set of IRBlocks in which the variable gets assigned
         """
 
+        visited_loc = set()
         for loc_key in self.graph.walk_depth_first_forward(head):
             irblock = self.get_block(loc_key)
             if irblock is None:
                 # Incomplete graph
                 continue
-
+            visited_loc.add(loc_key)
             # search for block's IR definitions/destinations
             for assignblk in irblock.assignblks:
                 for dst in assignblk:
@@ -443,6 +440,8 @@ class SSADiGraph(SSA):
                             continue
                         # map variable definition to blocks
                         self.defs.setdefault(dst, set()).add(irblock.loc_key)
+        if visited_loc != set(self.graph.blocks):
+            raise RuntimeError("Cannot operate on a non connected graph")
 
     def _place_phi(self, head):
         """
@@ -608,9 +607,18 @@ class SSADiGraph(SSA):
             if irblock is None:
                 continue
             assignblk = AssignBlock(self._phinodes[loc_key])
-            # insert at the beginning
-            new_irs = IRBlock(loc_key, [assignblk] + list(irblock.assignblks))
-            self.ircfg.blocks[loc_key] = new_irs
+            if irblock_has_phi(irblock):
+                # If first block contains phi, we are updating an existing ssa form
+                # so update phi
+                assignblks = list(irblock.assignblks)
+                out = dict(assignblks[0])
+                out.update(dict(assignblk))
+                assignblks[0] = AssignBlock(out, assignblk.instr)
+                new_irblock = IRBlock(loc_key, assignblks)
+            else:
+                # insert at the beginning
+                new_irblock = IRBlock(loc_key, [assignblk] + list(irblock.assignblks))
+            self.ircfg.blocks[loc_key] = new_irblock
 
     def _fix_no_def_var(self, head):
         """