diff options
Diffstat (limited to 'miasm2/analysis')
| -rw-r--r-- | miasm2/analysis/ssa.py | 41 |
1 files changed, 39 insertions, 2 deletions
diff --git a/miasm2/analysis/ssa.py b/miasm2/analysis/ssa.py index 489b4328..501cdd5e 100644 --- a/miasm2/analysis/ssa.py +++ b/miasm2/analysis/ssa.py @@ -1,9 +1,46 @@ from collections import deque -from miasm2.expression.expression import ExprId, ExprAssign, ExprOp, get_expr_ids +from miasm2.expression.expression import ExprId, ExprAssign, ExprOp, \ + ExprLoc, get_expr_ids from miasm2.ir.ir import AssignBlock, IRBlock +def sanitize_graph_head(ircfg, head): + """ + In multiple algorithm, the @head of the ircfg may not have predecessors. + The function transform the @ircfg in order to ensure this property + @ircfg: IRCFG instance + @head: the location of the graph's head + """ + + if not ircfg.predecessors(head): + return + original_edges = ircfg.predecessors(head) + sub_head = ircfg.loc_db.add_location() + + # Duplicate graph, replacing references to head by sub_head + replaced_expr = { + ExprLoc(head, ircfg.IRDst.size): + ExprLoc(sub_head, ircfg.IRDst.size) + } + ircfg.simplify( + lambda expr:expr.replace_expr(replaced_expr) + ) + # Duplicate head block + ircfg.add_irblock(IRBlock(sub_head, list(ircfg.blocks[head]))) + + # Remove original head block + ircfg.del_node(head) + + for src in original_edges: + ircfg.add_edge(src, sub_head) + + # Create new head, jumping to sub_head + assignblk = AssignBlock({ircfg.IRDst:ExprLoc(sub_head, ircfg.IRDst.size)}) + new_irblock = IRBlock(head, [assignblk]) + ircfg.add_irblock(new_irblock) + + class SSA(object): """ Generic class for static single assignment (SSA) transformation @@ -366,7 +403,7 @@ class SSADiGraph(SSA): def transform(self, head): """Transforms into SSA""" - assert not self.graph.predecessors(head) + sanitize_graph_head(self.graph, head) self._init_variable_defs(head) self._place_phi(head) self._rename(head) |