def _detect_loop(self, sim_run, new_tpl, simrun_key, new_call_stack_suffix, new_addr, new_jumpkind,
                     current_exit_wrapper, current_function_addr):
        """
        Loop detection.

        :param sim_run:
        :param new_tpl:
        :param simrun_key:
        :param new_call_stack_suffix:
        :param new_addr:
        :param new_jumpkind:
        :param current_exit_wrapper:
        :param current_function_addr:
        :return:
        """
        assert isinstance(sim_run, simuvex.SimIRSB)

        if new_jumpkind.startswith("Ijk_Sys"):
            return

        # Loop detection only applies to SimIRSBs
        # The most f****** case: An IRSB branches to itself
        if new_tpl == simrun_key:
            l.debug("%s is branching to itself. That's a loop.", sim_run)
            if (sim_run.addr, sim_run.addr) not in self._loop_back_edges_set:
                self._loop_back_edges_set.add((sim_run.addr, sim_run.addr))
                self._loop_back_edges.append((simrun_key, new_tpl))
        elif new_jumpkind != "Ijk_Call" and new_jumpkind != "Ijk_Ret" and \
                current_exit_wrapper.bbl_in_stack(
                    new_call_stack_suffix, current_function_addr, new_addr):
            '''
            There are two cases:
            # The loop header we found is a single IRSB that doesn't overlap with
            other IRSBs
            or
            # The loop header we found is a subset of the original loop header IRSB,
            as IRSBa could be inside IRSBb if they don't start at the same address but
            end at the same address
            We should take good care of these two cases.
            '''  # pylint:disable=W0105
            # First check if this is an overlapped loop header
            next_irsb = self._nodes[new_tpl]

            other_preds = set()

            for node_key, node in self._nodes_by_addr[next_irsb.addr]:
                predecessors = self.graph.predecessors(node)
                for pred in predecessors:
                    if pred.addr != sim_run.addr:
                        other_preds.add(pred)

            if len(other_preds) > 0:
                is_overlapping = False
                for p in other_preds:
                    if isinstance(p, simuvex.SimIRSB):
                        if p.addr + p.irsb.size() == sim_run.addr + sim_run.irsb.size():
                            # Overlapping!
                            is_overlapping = True
                            break
                if is_overlapping:
                    # Case 2, it's overlapped with another loop header
                    # Pending. We should remove all exits from sim_run
                    self._overlapped_loop_headers.append(sim_run)
                    l.debug("Found an overlapped loop header %s", sim_run)
                else:
                    # Case 1
                    if (sim_run.addr, next_irsb.addr) not in self._loop_back_edges_set:
                        self._loop_back_edges_set.add((sim_run.addr, next_irsb.addr))
                        self._loop_back_edges.append((simrun_key, new_tpl))
                        l.debug("Found a loop, back edge %s --> %s", sim_run, next_irsb)
            else:
                # Case 1, it's not over lapping with any other things
                if (sim_run.addr, next_irsb.addr) not in self._loop_back_edges_set:
                    self._loop_back_edges_set.add((sim_run.addr, next_irsb.addr))
                    self._loop_back_edges.append((simrun_key, new_tpl))
                l.debug("Found a loop, back edge %s --> %s", sim_run, next_irsb)
dataset/ETHPy150Open angr/angr/angr/analyses/cfg_accurate.py/CFGAccurate._detect_loop/original