docs: def _find_exits(self, src_block, target_block):
          """
          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
                  }
          """
  
          # Enumerate all statements and find exit statements
          # Since we don't have a state, we have to rely on the pyvex block instead of SimIRSB
          # Just create the block from pyvex again - not a big deal
  
          if self.project.is_hooked(src_block.addr):
              # Just return all exits for now
              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
  
          # And of course, it has a default exit
          # Don't forget about it.
          exit_stmt_ids[DEFAULT_STATEMENT] = None
  
          # Find all paths from src_block to target_block
          # FIXME: This is some crappy code written in a hurry. Replace the all_simple_paths() later.
          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:
                  # Oops, it looks that src_block and target_block are the same guy?
                  continue
  
              if self._same_function:
                  # Examine this path and make sure it does not have call or return edge
                  for i in range(len(simple_path) - 1):
                      jumpkind = self._cfg.graph[simple_path[i]][simple_path[i + 1]]['jumpkind']
                      if jumpkind in ('Ijk_Call', 'Ijk_Ret'):
                          return {  }
  
              # Get the first two nodes
              a, b = simple_path[0], simple_path[1]
              # Get the exit statement ID from CFG
              exit_stmt_id = self._cfg.get_exit_stmt_idx(a, b)
              if exit_stmt_id is None:
                  continue
  
              # Mark it!
              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