(self, ail_graph: networkx.DiGraph)
return ail_graph
Remove single-target indirect jumps and calls and replace them with direct jumps or calls.
Remove single-target indirect jumps and calls and replace them with direct jumps or calls.
Remove single - target indirect jumps and calls and replace them with direct jumps or calls .
def _replace_single_target_indirect_transitions(self, ail_graph: networkx.DiGraph) -> networkx.DiGraph:
        """
        Remove single-target indirect jumps and calls and replace them with direct jumps or calls.
        """
        if self._cfg is None:
            return ail_graph

        for block in ail_graph.nodes():
            if not block.statements:
                continue
            last_stmt = block.statements[-1]
            if isinstance(last_stmt, ailment.Stmt.Call) and not isinstance(last_stmt.target, ailment.Expr.Const):
                # indirect call
                # consult CFG to see if this is a call with a single successor
                node = self._cfg.get_any_node(block.addr)
                if node is None:
                    continue
                successors = self._cfg.get_successors(node, excluding_fakeret=True, jumpkind='Ijk_Call')
                if len(successors) == 1 and \
                        not isinstance(self.project.hooked_by(successors[0].addr), UnresolvableCallTarget):
                    # found a single successor - replace the last statement
                    new_last_stmt = last_stmt.copy()
                    new_last_stmt.target = ailment.Expr.Const(None, None, successors[0].addr, last_stmt.target.bits)
                    block.statements[-1] = new_last_stmt

            elif isinstance(last_stmt, ailment.Stmt.Jump) and not isinstance(last_stmt.target, ailment.Expr.Const):
                # indirect jump
                # consult CFG to see if there is a jump with a single successor
                node = self._cfg.get_any_node(block.addr)
                if node is None:
                    continue
                successors = self._cfg.get_successors(node, excluding_fakeret=True, jumpkind='Ijk_Boring')
                if len(successors) == 1 and \
                        not isinstance(self.project.hooked_by(successors[0].addr), UnresolvableJumpTarget):
                    # found a single successor - replace the last statement
                    new_last_stmt = last_stmt.copy()
                    new_last_stmt.target = ailment.Expr.Const(None, None, successors[0].addr, last_stmt.target.bits)
                    block.statements[-1] = new_last_stmt

        return ail_graph
def _replace_single_target_indirect_transitions ( self , ail_graph : networkx . DiGraph ) -> networkx . DiGraph : if self . _cfg is None : return ail_graph for block in ail_graph . nodes ( ) : if not block . statements : continue last_stmt = block . statements [ - 1 ] if isinstance ( last_stmt , ailment . Stmt . Call ) and not isinstance ( last_stmt . target , ailment . Expr . Const ) : # indirect call # consult CFG to see if this is a call with a single successor node = self . _cfg . get_any_node ( block . addr ) if node is None : continue successors = self . _cfg . get_successors ( node , excluding_fakeret = True , jumpkind = 'Ijk_Call' ) if len ( successors ) == 1 and not isinstance ( self . project . hooked_by ( successors [ 0 ] . addr ) , UnresolvableCallTarget ) : # found a single successor - replace the last statement new_last_stmt = last_stmt . copy ( ) new_last_stmt . target = ailment . Expr . Const ( None , None , successors [ 0 ] . addr , last_stmt . target . bits ) block . statements [ - 1 ] = new_last_stmt elif isinstance ( last_stmt , ailment . Stmt . Jump ) and not isinstance ( last_stmt . target , ailment . Expr . Const ) : # indirect jump # consult CFG to see if there is a jump with a single successor node = self . _cfg . get_any_node ( block . addr ) if node is None : continue successors = self . _cfg . get_successors ( node , excluding_fakeret = True , jumpkind = 'Ijk_Boring' ) if len ( successors ) == 1 and not isinstance ( self . project . hooked_by ( successors [ 0 ] . addr ) , UnresolvableJumpTarget ) : # found a single successor - replace the last statement new_last_stmt = last_stmt . copy ( ) new_last_stmt . target = ailment . Expr . Const ( None , None , successors [ 0 ] . addr , last_stmt . target . bits ) block . statements [ - 1 ] = new_last_stmt return ail_graph