diff options
| -rw-r--r-- | miasm/analysis/data_flow.py | 24 | ||||
| -rw-r--r-- | miasm/analysis/simplifier.py | 41 | ||||
| -rw-r--r-- | miasm/analysis/ssa.py | 24 |
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): """ |