Resolve indirect jumps specified by sim_successors.addr.

        :param SimSuccessors sim_successors: The SimSuccessors instance.
        :param CFGNode cfg_node:                     The CFGNode instance.
        :param int func_addr:                        Current function address.
        :param list successors:                      A list of successors.
        :param tuple exception_info:                 The sys.exc_info() of the exception or None if none occured.
        :param artifacts:                            A container of collected information.
        :return:                                     Resolved successors
        :rtype:                                      list

def _try_resolving_indirect_jumps(self, sim_successors, cfg_node, func_addr, successors, exception_info, artifacts):
        """
        Resolve indirect jumps specified by sim_successors.addr.

        :param SimSuccessors sim_successors: The SimSuccessors instance.
        :param CFGNode cfg_node:                     The CFGNode instance.
        :param int func_addr:                        Current function address.
        :param list successors:                      A list of successors.
        :param tuple exception_info:                 The sys.exc_info() of the exception or None if none occured.
        :param artifacts:                            A container of collected information.
        :return:                                     Resolved successors
        :rtype:                                      list
        """

        # Try to resolve indirect jumps with advanced backward slicing (if enabled)
        if sim_successors.sort == 'IRSB' and \
                self._is_indirect_jump(cfg_node, sim_successors):
            l.debug('IRSB %#x has an indirect jump as its default exit', cfg_node.addr)

            # We need input states to perform backward slicing
            if self._advanced_backward_slicing and self._keep_state:

                # Optimization: make sure we only try to resolve an indirect jump if any of the following criteria holds
                # - It's a jump (Ijk_Boring), and its target is either fully symbolic, or its resolved target is within
                #   the current binary
                # - It's a call (Ijk_Call), and its target is fully symbolic
                # TODO: This is very hackish, please refactor this part of code later
                should_resolve = True
                legit_successors = [suc for suc in successors if suc.history.jumpkind in ('Ijk_Boring', 'Ijk_InvalICache', 'Ijk_Call')]
                if legit_successors:
                    legit_successor = legit_successors[0]
                    if legit_successor.ip.symbolic:
                        if not legit_successor.history.jumpkind == 'Ijk_Call':
                            should_resolve = False
                    else:
                        if legit_successor.history.jumpkind == 'Ijk_Call':
                            should_resolve = False
                        else:
                            concrete_target = legit_successor.solver.eval(legit_successor.ip)
                            if not self.project.loader.find_object_containing(
                                    concrete_target) is self.project.loader.main_object:
                                should_resolve = False

                else:
                    # No interesting successors... skip
                    should_resolve = False

                # TODO: Handle those successors
                if not should_resolve:
                    l.debug("This might not be an indirect jump that has multiple targets. Skipped.")
                    self.kb.unresolved_indirect_jumps.add(cfg_node.addr)

                else:
                    more_successors = self._backward_slice_indirect(cfg_node, sim_successors, func_addr)

                    if more_successors:
                        # Remove the symbolic successor
                        # TODO: Now we are removing all symbolic successors. Is it possible
                        # TODO: that there is more than one symbolic successor?
                        all_successors = [suc for suc in successors if not suc.solver.symbolic(suc.ip)]
                        # Insert new successors
                        # We insert new successors in the beginning of all_successors list so that we don't break the
                        # assumption that Ijk_FakeRet is always the last element in the list
                        for suc_addr in more_successors:
                            a = sim_successors.all_successors[0].copy()
                            a.ip = suc_addr
                            all_successors.insert(0, a)

                        l.debug('The indirect jump is successfully resolved.')

                        self.kb.resolved_indirect_jumps.add(cfg_node.addr)

                    else:
                        l.debug('Failed to resolve the indirect jump.')
                        self.kb.unresolved_indirect_jumps.add(cfg_node.addr)

            else:
                if not successors:
                    l.debug('Cannot resolve the indirect jump without advanced backward slicing enabled: %s',
                            cfg_node)

        # Try to find more successors if we failed to resolve the indirect jump before
        if exception_info is None and (cfg_node.is_simprocedure or self._is_indirect_jump(cfg_node, sim_successors)):
            has_call_jumps = any(suc_state.history.jumpkind == 'Ijk_Call' for suc_state in successors)
            if has_call_jumps:
                concrete_successors = [suc_state for suc_state in successors if
                                       suc_state.history.jumpkind != 'Ijk_FakeRet' and not suc_state.solver.symbolic(
                                           suc_state.ip)]
            else:
                concrete_successors = [suc_state for suc_state in successors if
                                       not suc_state.solver.symbolic(suc_state.ip)]
            symbolic_successors = [suc_state for suc_state in successors if suc_state.solver.symbolic(suc_state.ip)]

            resolved = True if not symbolic_successors else False
            if symbolic_successors:
                for suc in symbolic_successors:
                    if o.SYMBOLIC in suc.options:
                        targets = suc.solver.eval_upto(suc.ip, 32)
                        if len(targets) < 32:
                            all_successors = []
                            resolved = True
                            for t in targets:
                                new_ex = suc.copy()
                                new_ex.ip = suc.solver.BVV(t, suc.ip.size())
                                all_successors.append(new_ex)
                        else:
                            break

            if not resolved and (
                        (symbolic_successors and not concrete_successors) or
                        (not cfg_node.is_simprocedure and self._is_indirect_jump(cfg_node, sim_successors))
            ):
                l.debug("%s has an indirect jump. See what we can do about it.", cfg_node)

                if sim_successors.sort == 'SimProcedure' and \
                        sim_successors.artifacts['adds_exits']:
                    # Skip those SimProcedures that don't create new SimExits
                    l.debug('We got a SimProcedure %s in fastpath mode that creates new exits.', sim_successors.description)
                    if self._enable_symbolic_back_traversal:
                        successors = self._symbolically_back_traverse(sim_successors, artifacts, cfg_node)
                        # mark jump as resolved if we got successors
                        if successors:
                            self.kb.resolved_indirect_jumps.add(cfg_node.addr)
                        else:
                            self.kb.unresolved_indirect_jumps.add(cfg_node.addr)
                        l.debug("Got %d concrete exits in symbolic mode.", len(successors))
                    else:
                        self.kb.unresolved_indirect_jumps.add(cfg_node.addr)
                        # keep fake_rets
                        successors = [s for s in successors if s.history.jumpkind == "Ijk_FakeRet"]

                elif sim_successors.sort == 'IRSB'and \
                        any([ex.history.jumpkind != 'Ijk_Ret' for ex in successors]):
                    # We cannot properly handle Return as that requires us start execution from the caller...
                    l.debug("Try traversal backwards in symbolic mode on %s.", cfg_node)
                    if self._enable_symbolic_back_traversal:
                        successors = self._symbolically_back_traverse(sim_successors, artifacts, cfg_node)

                        # Remove successors whose IP doesn't make sense
                        successors = [suc for suc in successors
                                          if self._is_address_executable(suc.solver.eval_one(suc.ip))]

                        # mark jump as resolved if we got successors
                        if successors:
                            self.kb.resolved_indirect_jumps.add(cfg_node.addr)
                        else:
                            self.kb.unresolved_indirect_jumps.add(cfg_node.addr)
                        l.debug('Got %d concrete exits in symbolic mode', len(successors))
                    else:
                        self.kb.unresolved_indirect_jumps.add(cfg_node.addr)
                        successors = []

                elif successors and all([ex.history.jumpkind == 'Ijk_Ret' for ex in successors]):
                    l.debug('All exits are returns (Ijk_Ret). It will be handled by pending exits.')

                else:
                    l.debug('Cannot resolve this indirect jump: %s', cfg_node)
                    self.kb.unresolved_indirect_jumps.add(cfg_node.addr)

        return successors