Generate new jobs for all possible successor targets when there are more than one possible concrete value for
        successor.ip

        :param VFGJob job: The VFGJob instance.
        :param SimState successor: The succeeding state.
        :param list all_successors: All succeeding states from the same VFGJob.
        :return: A list of new succeeding jobs
        :rtype: list

def _handle_successor_multitargets(self, job, successor, all_successors):
        """
        Generate new jobs for all possible successor targets when there are more than one possible concrete value for
        successor.ip

        :param VFGJob job: The VFGJob instance.
        :param SimState successor: The succeeding state.
        :param list all_successors: All succeeding states from the same VFGJob.
        :return: A list of new succeeding jobs
        :rtype: list
        """

        new_jobs = [ ]

        # Currently we assume a legit jumping target cannot have more than 256 concrete values
        # TODO: make it a setting on VFG
        MAX_NUMBER_OF_CONCRETE_VALUES = 256

        all_possible_ips = successor.solver.eval_upto(successor.ip, MAX_NUMBER_OF_CONCRETE_VALUES + 1)

        if len(all_possible_ips) > MAX_NUMBER_OF_CONCRETE_VALUES:
            l.warning("IP can be concretized to more than %d values, which means it might be corrupted.",
                      MAX_NUMBER_OF_CONCRETE_VALUES)
            return [ ]

        # Call this function to generate a successor for each possible IP
        for ip in all_possible_ips:
            concrete_successor = successor.copy()
            concrete_successor.ip = ip

            concrete_jobs = self._handle_successor(job, concrete_successor, all_successors)

            if job.is_call_jump:  # TODO: take care of syscalls
                for new_job in concrete_jobs:
                    # TODO: correctly fill the return address. The return address can be found from the
                    # TODO: fakeret successor in the `successors` list
                    function_analysis_task = FunctionAnalysis(new_job.addr, None)
                    # log the new job
                    function_analysis_task.jobs.append(new_job)
                    # put it onto the stack
                    self._task_stack.append(function_analysis_task)
                    # log it in the call_task
                    job.call_task.register_function_analysis(function_analysis_task)

            new_jobs.extend(concrete_jobs)

        return new_jobs