'Source block has more than one exit, and through some of those exits, the control flow can eventually go to
the target block. This method returns exits that lead to the target block.
:param src_block:       The block that has multiple exits.
:param target_block:    The target block to reach.
:returns: a dict of statement ID -> a list of target IPs (or None if the exit should not be taken), each
corresponds to an exit to take in order to reach the target.
For example, it returns the following dict:
\'default\': None, # It has a default exit, but shouldn\'t be taken
15: [ 0x400080 ], # Statement 15 is an exit statement, and should be taken when the target is
# 0x400080
28: None  # Statement 28 is an exit statement, but shouldn\'t be taken'

def _find_exits(self, src_block, target_block):

    if self.project.is_hooked(src_block.addr):
        return {(-1): [target_block.addr]}
    block = self.project.factory.block(src_block.addr)
    vex_block = block.vex
    exit_stmt_ids = {}
    for (stmt_idx, stmt) in enumerate(vex_block.statements):
        if isinstance(stmt, pyvex.IRStmt.Exit):
            exit_stmt_ids[stmt_idx] = None
    exit_stmt_ids['default'] = None
    all_simple_paths = list(networkx.all_simple_paths(self._cfg.graph, src_block, target_block, cutoff=3))
    for simple_path in all_simple_paths:
        if (len(simple_path) <= 1):
            continue
        if self._same_function:
            for i in xrange((len(simple_path) - 1)):
                jumpkind = self._cfg.graph[simple_path[i]][simple_path[(i + 1)]]['jumpkind']
                if (jumpkind in ('Ijk_Call', 'Ijk_Ret')):
                    return {}
        (a, b) = (simple_path[0], simple_path[1])
        exit_stmt_id = self._cfg.get_exit_stmt_idx(a, b)
        if (exit_stmt_id is None):
            continue
        if (exit_stmt_ids[exit_stmt_id] is None):
            exit_stmt_ids[exit_stmt_id] = [b.addr]
        else:
            exit_stmt_ids[exit_stmt_id].append(b.addr)
    return exit_stmt_ids
