(self, region, graph: networkx.DiGraph)
If there are multiple successors of a loop, convert them into conditional gotos. Eventually there should be
        only one loop successor.

        :param GraphRegion region:      The cyclic region to refine.
        :param networkx.DiGraph graph:  The current graph that is being structured.
        :return:                        None
If there are multiple successors of a loop, convert them into conditional gotos. Eventually there should be
        only one loop successor.
If there are multiple successors of a loop convert them into conditional gotos . Eventually there should be only one loop successor .
def _refine_loop_successors(self, region, graph: networkx.DiGraph):
        """
        If there are multiple successors of a loop, convert them into conditional gotos. Eventually there should be
        only one loop successor.

        :param GraphRegion region:      The cyclic region to refine.
        :param networkx.DiGraph graph:  The current graph that is being structured.
        :return:                        None
        """
        if len(region.successors) <= 1:
            return

        # recover reaching conditions
        self.cond_proc.recover_reaching_conditions(region, with_successors=True)

        successors = list(region.successors)

        condnode_addr = next(CONDITIONNODE_ADDR)
        # create a new successor
        cond = ConditionNode(
            condnode_addr,
            None,
            self.cond_proc.reaching_conditions[successors[0]],
            successors[0],
            false_node=None,
        )
        for succ in successors[1:]:
            cond = ConditionNode(condnode_addr,
                                 None,
                                 self.cond_proc.reaching_conditions[succ],
                                 succ,
                                 false_node=cond,
                                 )

        g = region.graph_with_successors

        # modify region in place
        region.successors = {cond}
        for succ in successors:
            for src, _, data in list(g.in_edges(succ, data=True)):
                removed_edges = [ ]
                for src2src, _, data_ in list(g.in_edges(src, data=True)):
                    removed_edges.append((src2src, src, data_))
                    g.remove_edge(src2src, src)
                g.remove_edge(src, succ)

                # TODO: rewrite the conditional jumps in src so that it goes to cond-node instead.

                # modify the last statement of src so that it jumps to cond
                replaced_any_stmt = False
                last_stmts = self.cond_proc.get_last_statements(src)
                for last_stmt in last_stmts:
                    if isinstance(last_stmt, ailment.Stmt.ConditionalJump):
                        if last_stmt.true_target.value == succ.addr:
                            new_last_stmt = ailment.Stmt.ConditionalJump(
                                last_stmt.idx,
                                last_stmt.condition,
                                ailment.Expr.Const(None, None, condnode_addr, self.project.arch.bits),
                                last_stmt.false_target,
                                ins_addr=last_stmt.ins_addr,
                            )
                        elif last_stmt.false_target.value == succ.addr:
                            new_last_stmt = ailment.Stmt.ConditionalJump(
                                last_stmt.idx,
                                last_stmt.condition,
                                last_stmt.true_target,
                                ailment.Expr.Const(None, None, condnode_addr, self.project.arch.bits),
                                ins_addr=last_stmt.ins_addr,
                            )
                        else:
                            # none of the two branches is jumping out of the loop
                            continue
                    else:
                        new_last_stmt = ailment.Stmt.Jump(
                            last_stmt.idx,
                            ailment.Expr.Const(None, None, condnode_addr, self.project.arch.bits),
                            ins_addr=last_stmt.ins_addr,
                        )
                    replace_last_statement(src, last_stmt, new_last_stmt)
                    replaced_any_stmt = True
                if not replaced_any_stmt:
                    l.warning("No statement was replaced. Is there anything wrong?")
                    # raise Exception()

                # add src back
                for src2src, _, data_ in removed_edges:
                    g.add_edge(src2src, src, **data_)

                g.add_edge(src, cond, **data)

        # modify graph
        graph.add_edge(region, cond)
        for succ in successors:
            edge_data = graph.get_edge_data(region, succ)
            graph.remove_edge(region, succ)
            graph.add_edge(cond, succ, **edge_data)
def _refine_loop_successors ( self , region , graph : networkx . DiGraph ) : if len ( region . successors ) <= 1 : return # recover reaching conditions self . cond_proc . recover_reaching_conditions ( region , with_successors = True ) successors = list ( region . successors ) condnode_addr = next ( CONDITIONNODE_ADDR ) # create a new successor cond = ConditionNode ( condnode_addr , None , self . cond_proc . reaching_conditions [ successors [ 0 ] ] , successors [ 0 ] , false_node = None , ) for succ in successors [ 1 : ] : cond = ConditionNode ( condnode_addr , None , self . cond_proc . reaching_conditions [ succ ] , succ , false_node = cond , ) g = region . graph_with_successors # modify region in place region . successors = { cond } for succ in successors : for src , _ , data in list ( g . in_edges ( succ , data = True ) ) : removed_edges = [ ] for src2src , _ , data_ in list ( g . in_edges ( src , data = True ) ) : removed_edges . append ( ( src2src , src , data_ ) ) g . remove_edge ( src2src , src ) g . remove_edge ( src , succ ) # TODO: rewrite the conditional jumps in src so that it goes to cond-node instead. # modify the last statement of src so that it jumps to cond replaced_any_stmt = False last_stmts = self . cond_proc . get_last_statements ( src ) for last_stmt in last_stmts : if isinstance ( last_stmt , ailment . Stmt . ConditionalJump ) : if last_stmt . true_target . value == succ . addr : new_last_stmt = ailment . Stmt . ConditionalJump ( last_stmt . idx , last_stmt . condition , ailment . Expr . Const ( None , None , condnode_addr , self . project . arch . bits ) , last_stmt . false_target , ins_addr = last_stmt . ins_addr , ) elif last_stmt . false_target . value == succ . addr : new_last_stmt = ailment . Stmt . ConditionalJump ( last_stmt . idx , last_stmt . condition , last_stmt . true_target , ailment . Expr . Const ( None , None , condnode_addr , self . project . arch . bits ) , ins_addr = last_stmt . ins_addr , ) else : # none of the two branches is jumping out of the loop continue else : new_last_stmt = ailment . Stmt . Jump ( last_stmt . idx , ailment . Expr . Const ( None , None , condnode_addr , self . project . arch . bits ) , ins_addr = last_stmt . ins_addr , ) replace_last_statement ( src , last_stmt , new_last_stmt ) replaced_any_stmt = True if not replaced_any_stmt : l . warning ( "No statement was replaced. Is there anything wrong?" ) # raise Exception() # add src back for src2src , _ , data_ in removed_edges : g . add_edge ( src2src , src , * * data_ ) g . add_edge ( src , cond , * * data ) # modify graph graph . add_edge ( region , cond ) for succ in successors : edge_data = graph . get_edge_data ( region , succ ) graph . remove_edge ( region , succ ) graph . add_edge ( cond , succ , * * edge_data )