about summary refs log tree commit diff stats
path: root/miasm2/analysis/ssa.py
diff options
context:
space:
mode:
authorCamille Mougey <commial@gmail.com>2018-08-06 22:26:36 +0200
committerGitHub <noreply@github.com>2018-08-06 22:26:36 +0200
commite38b5dd91d10ad66d537675e4592f68eda9fcce2 (patch)
tree912333c96758461e9c226d8da037c0084d3c10a0 /miasm2/analysis/ssa.py
parente4a255d9c6175b5d9f2ab15471d848705fe1cc4e (diff)
parentefc5ec2e8c394475e3a2be68bc29821e4d980b1b (diff)
downloadmiasm-e38b5dd91d10ad66d537675e4592f68eda9fcce2.tar.gz
miasm-e38b5dd91d10ad66d537675e4592f68eda9fcce2.zip
Merge pull request #816 from serpilliere/operator_high_level
Operator high level
Diffstat (limited to 'miasm2/analysis/ssa.py')
-rw-r--r--miasm2/analysis/ssa.py120
1 files changed, 120 insertions, 0 deletions
diff --git a/miasm2/analysis/ssa.py b/miasm2/analysis/ssa.py
index 63d0c4fb..2f25e4b8 100644
--- a/miasm2/analysis/ssa.py
+++ b/miasm2/analysis/ssa.py
@@ -568,7 +568,127 @@ class SSADiGraph(SSA):
         into IRBlock at the beginning"""
         for loc_key in self._phinodes:
             irblock = self.get_block(loc_key)
+            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
+
+
+
+def get_assignblk(graph, loc, index):
+    """
+    Return the dictionnary of the AssignBlock from @graph at location @loc at
+    @index
+    @graph: IRCFG instance
+    @loc: Location instance
+    @index: assignblock index
+    """
+
+    irblock = graph.blocks[loc]
+    assignblks = irblock.assignblks
+    assignblk = assignblks[index]
+    assignblk_dct = dict(assignblk)
+    return assignblk_dct
+
+
+def set_assignblk(graph, loc, index, assignblk_dct):
+    """
+    Set the Assignblock in @graph at location @loc at @index using dictionnary
+    @assignblk_dct
+
+    @graph: IRCFG instance
+    @loc: Location instance
+    @index: assignblock index
+    @assignblk_dct: dictionnary representing the AssignBlock
+    """
+
+    irblock = graph.blocks[loc]
+    assignblks = list(irblock.assignblks)
+    assignblk = assignblks[index]
+
+    assignblks[index] = AssignBlock(
+        assignblk_dct,
+        assignblk.instr
+    )
+    new_irblock = IRBlock(loc, assignblks)
+    return new_irblock
+
+
+def remove_phi(ssa, head):
+    """
+    Remove Phi using naive algorithm
+    Note: The _ssa_variable_to_expr must be up to date
+
+    @ssa: a SSADiGraph instance
+    @head: the loc_key of the graph head
+    """
+
+    phivar2var = {}
+
+    all_ssa_vars = ssa._ssa_variable_to_expr
+
+    # Retrive Phi nodes
+    phi_nodes = []
+    for irblock in ssa.graph.blocks.itervalues():
+        for index, assignblk in enumerate(irblock):
+            for dst, src in assignblk.iteritems():
+                if src.is_op('Phi'):
+                    phi_nodes.append((irblock.loc_key, index))
+
+
+    for phi_loc, phi_index in phi_nodes:
+        assignblk_dct = get_assignblk(ssa.graph, phi_loc, phi_index)
+        for dst, src in assignblk_dct.iteritems():
+            if src.is_op('Phi'):
+                break
+        else:
+            raise RuntimeError('Cannot find phi?')
+        node_src = src
+        var = dst
+
+        # Create new variable
+        new_var = ExprId('var%d' % len(phivar2var), var.size)
+        phivar2var[var] = new_var
+        phi_sources = set(node_src.args)
+
+        # Place var init for non ssa variables
+        to_remove = set()
+        for phi_source in list(phi_sources):
+            if phi_source not in all_ssa_vars.union(phivar2var):
+                assignblk_dct = get_assignblk(ssa.graph, head, 0)
+                assignblk_dct[new_var] = phi_source
+                new_irblock = set_assignblk(ssa.graph, head, 0, assignblk_dct)
+                ssa.graph.blocks[head] = new_irblock
+                to_remove.add(phi_source)
+        phi_sources.difference_update(to_remove)
+
+        var_to_replace = set([var])
+        var_to_replace.update(phi_sources)
+
+
+
+
+        # Replace variables
+        to_replace_dct = {x:new_var for x in var_to_replace}
+        for loc in ssa.graph.blocks:
+            irblock = ssa.graph.blocks[loc]
+            assignblks = []
+            for assignblk in irblock:
+                assignblk_dct = {}
+                for dst, src in assignblk.iteritems():
+                    dst = dst.replace_expr(to_replace_dct)
+                    src = src.replace_expr(to_replace_dct)
+                    assignblk_dct[dst] = src
+                assignblks.append(AssignBlock(assignblk_dct, assignblk.instr))
+            new_irblock = IRBlock(loc, assignblks)
+            ssa.graph.blocks[loc] = new_irblock
+
+        # Remove phi
+        assignblk_dct = get_assignblk(ssa.graph, phi_loc, phi_index)
+        del assignblk_dct[new_var]
+
+
+        new_irblock = set_assignblk(ssa.graph, phi_loc, phi_index, assignblk_dct)
+        ssa.graph.blocks[phi_loc] = new_irblock