예제 #1
0
static struct sim_inferior_data *
get_sim_inferior_data (struct inferior *inf, int sim_instance_needed)
{
  SIM_DESC sim_desc = NULL;
  struct sim_inferior_data *sim_data
    = (struct sim_inferior_data *) inferior_data (inf, sim_inferior_data_key);

  /* Try to allocate a new sim instance, if needed.  We do this ahead of
     a potential allocation of a sim_inferior_data struct in order to
     avoid needlessly allocating that struct in the event that the sim
     instance allocation fails.  */
  if (sim_instance_needed == SIM_INSTANCE_NEEDED
      && (sim_data == NULL || sim_data->gdbsim_desc == NULL))
    {
      struct inferior *idup;
      sim_desc = sim_open (SIM_OPEN_DEBUG, &gdb_callback, exec_bfd, sim_argv);
      if (sim_desc == NULL)
	error (_("Unable to create simulator instance for inferior %d."),
	       inf->num);

      idup = iterate_over_inferiors (check_for_duplicate_sim_descriptor,
				     sim_desc);
      if (idup != NULL)
	{
	  /* We don't close the descriptor due to the fact that it's
	     shared with some other inferior.  If we were to close it,
	     that might needlessly muck up the other inferior.  Of
	     course, it's possible that the damage has already been
	     done...  Note that it *will* ultimately be closed during
	     cleanup of the other inferior.  */
	  sim_desc = NULL;
	  error (
 _("Inferior %d and inferior %d would have identical simulator state.\n"
   "(This simulator does not support the running of more than one inferior.)"),
		 inf->num, idup->num);
	}
    }

  if (sim_data == NULL)
    {
      sim_data = XCNEW(struct sim_inferior_data);
      set_inferior_data (inf, sim_inferior_data_key, sim_data);

      /* Allocate a ptid for this inferior.  */
      sim_data->remote_sim_ptid = ptid_build (next_pid, 0, next_pid);
      next_pid++;

      /* Initialize the other instance variables.  */
      sim_data->program_loaded = 0;
      sim_data->gdbsim_desc = sim_desc;
      sim_data->resume_siggnal = GDB_SIGNAL_0;
      sim_data->resume_step = 0;
    }
예제 #2
0
/* Implementation of gdb.inferiors () -> (gdb.Inferior, ...).
   Returns a tuple of all inferiors.  */
PyObject *
gdbpy_inferiors (PyObject *unused, PyObject *unused2)
{
    int i = 0;
    PyObject *list, *inferior;
    struct inferior *inf;

    list = PyList_New (0);
    if (!list)
        return NULL;

    iterate_over_inferiors (build_inferior_list, list);

    return PyList_AsTuple (list);
}
예제 #3
0
/* Implementation of gdb.inferiors () -> (gdb.Inferior, ...).
   Returns a tuple of all inferiors.  */
PyObject *
gdbpy_inferiors (PyObject *unused, PyObject *unused2)
{
  PyObject *list, *tuple;

  list = PyList_New (0);
  if (!list)
    return NULL;

  if (iterate_over_inferiors (build_inferior_list, list))
    {
      Py_DECREF (list);
      return NULL;
    }

  tuple = PyList_AsTuple (list);
  Py_DECREF (list);

  return tuple;
}
예제 #4
0
static void *
mi_interpreter_init (int top_level)
{
  struct mi_interp *mi = XMALLOC (struct mi_interp);

  /* HACK: We need to force stdout/stderr to point at the console.  This avoids
     any potential side effects caused by legacy code that is still
     using the TUI / fputs_unfiltered_hook.  So we set up output channels for
     this now, and swap them in when we are run. */

  raw_stdout = stdio_fileopen (stdout);

  /* Create MI channels */
  mi->out = mi_console_file_new (raw_stdout, "~", '"');
  mi->err = mi_console_file_new (raw_stdout, "&", '"');
  mi->log = mi->err;
  mi->targ = mi_console_file_new (raw_stdout, "@", '"');
  mi->event_channel = mi_console_file_new (raw_stdout, "=", 0);

  if (top_level)
    {
      observer_attach_new_thread (mi_new_thread);
      observer_attach_thread_exit (mi_thread_exit);
      observer_attach_inferior_added (mi_inferior_added);
      observer_attach_inferior_appeared (mi_inferior_appeared);
      observer_attach_inferior_exit (mi_inferior_exit);
      observer_attach_inferior_removed (mi_inferior_removed);
      observer_attach_normal_stop (mi_on_normal_stop);
      observer_attach_target_resumed (mi_on_resume);
      observer_attach_solib_loaded (mi_solib_loaded);
      observer_attach_solib_unloaded (mi_solib_unloaded);
      observer_attach_about_to_proceed (mi_about_to_proceed);

      /* The initial inferior is created before this function is called, so we
	 need to report it explicitly.  Use iteration in case future version
	 of GDB creates more than one inferior up-front.  */
      iterate_over_inferiors (report_initial_inferior, mi);
    }

  return mi;
}
예제 #5
0
static void
mi_on_resume (ptid_t ptid)
{
  struct thread_info *tp = NULL;

  if (ptid_equal (ptid, minus_one_ptid) || ptid_is_pid (ptid))
    tp = inferior_thread ();
  else
    tp = find_thread_ptid (ptid);

  /* Suppress output while calling an inferior function.  */
  if (tp->control.in_infcall)
    return;

  /* To cater for older frontends, emit ^running, but do it only once
     per each command.  We do it here, since at this point we know
     that the target was successfully resumed, and in non-async mode,
     we won't return back to MI interpreter code until the target
     is done running, so delaying the output of "^running" until then
     will make it impossible for frontend to know what's going on.

     In future (MI3), we'll be outputting "^done" here.  */
  if (!running_result_record_printed && mi_proceeded)
    {
      fprintf_unfiltered (raw_stdout, "%s^running\n",
			  current_token ? current_token : "");
    }

  if (ptid_get_pid (ptid) == -1)
    fprintf_unfiltered (raw_stdout, "*running,thread-id=\"all\"\n");
  else if (ptid_is_pid (ptid))
    {
      int count = 0;

      /* Backwards compatibility.  If there's only one inferior,
	 output "all", otherwise, output each resumed thread
	 individually.  */
      iterate_over_inferiors (mi_inferior_count, &count);

      if (count == 1)
	fprintf_unfiltered (raw_stdout, "*running,thread-id=\"all\"\n");
      else
	iterate_over_threads (mi_output_running_pid, &ptid);
    }
  else
    {
      struct thread_info *ti = find_thread_ptid (ptid);

      gdb_assert (ti);
      fprintf_unfiltered (raw_stdout, "*running,thread-id=\"%d\"\n", ti->num);
    }

  if (!running_result_record_printed && mi_proceeded)
    {
      running_result_record_printed = 1;
      /* This is what gdb used to do historically -- printing prompt even if
	 it cannot actually accept any input.  This will be surely removed
	 for MI3, and may be removed even earlier.  SYNC_EXECUTION is
	 checked here because we only need to emit a prompt if a
	 synchronous command was issued when the target is async.  */
      if (!target_is_async_p () || sync_execution)
	fputs_unfiltered ("(gdb) \n", raw_stdout);
    }
  gdb_flush (raw_stdout);
}
예제 #6
0
static void *
mi_interpreter_init (struct interp *interp, int top_level)
{
  struct mi_interp *mi = XNEW (struct mi_interp);
  const char *name;
  int mi_version;

  /* Assign the output channel created at startup to its own global,
     so that we can create a console channel that encapsulates and
     prefixes all gdb_output-type bits coming from the rest of the
     debugger.  */

  raw_stdout = gdb_stdout;

  /* Create MI console channels, each with a different prefix so they
     can be distinguished.  */
  mi->out = mi_console_file_new (raw_stdout, "~", '"');
  mi->err = mi_console_file_new (raw_stdout, "&", '"');
  mi->log = mi->err;
  mi->targ = mi_console_file_new (raw_stdout, "@", '"');
  mi->event_channel = mi_console_file_new (raw_stdout, "=", 0);

  name = interp_name (interp);
  /* INTERP_MI selects the most recent released version.  "mi2" was
     released as part of GDB 6.0.  */
  if (strcmp (name, INTERP_MI) == 0)
    mi_version = 2;
  else if (strcmp (name, INTERP_MI1) == 0)
    mi_version = 1;
  else if (strcmp (name, INTERP_MI2) == 0)
    mi_version = 2;
  else if (strcmp (name, INTERP_MI3) == 0)
    mi_version = 3;
  else
    gdb_assert_not_reached ("unhandled MI version");

  mi->mi_uiout = mi_out_new (mi_version);
  mi->cli_uiout = cli_out_new (mi->out);

  /* There are installed even if MI is not the top level interpreter.
     The callbacks themselves decide whether to be skipped.  */
  observer_attach_signal_received (mi_on_signal_received);
  observer_attach_end_stepping_range (mi_on_end_stepping_range);
  observer_attach_signal_exited (mi_on_signal_exited);
  observer_attach_exited (mi_on_exited);
  observer_attach_no_history (mi_on_no_history);

  if (top_level)
    {
      observer_attach_new_thread (mi_new_thread);
      observer_attach_thread_exit (mi_thread_exit);
      observer_attach_inferior_added (mi_inferior_added);
      observer_attach_inferior_appeared (mi_inferior_appeared);
      observer_attach_inferior_exit (mi_inferior_exit);
      observer_attach_inferior_removed (mi_inferior_removed);
      observer_attach_record_changed (mi_record_changed);
      observer_attach_normal_stop (mi_on_normal_stop);
      observer_attach_target_resumed (mi_on_resume);
      observer_attach_solib_loaded (mi_solib_loaded);
      observer_attach_solib_unloaded (mi_solib_unloaded);
      observer_attach_about_to_proceed (mi_about_to_proceed);
      observer_attach_traceframe_changed (mi_traceframe_changed);
      observer_attach_tsv_created (mi_tsv_created);
      observer_attach_tsv_deleted (mi_tsv_deleted);
      observer_attach_tsv_modified (mi_tsv_modified);
      observer_attach_breakpoint_created (mi_breakpoint_created);
      observer_attach_breakpoint_deleted (mi_breakpoint_deleted);
      observer_attach_breakpoint_modified (mi_breakpoint_modified);
      observer_attach_command_param_changed (mi_command_param_changed);
      observer_attach_memory_changed (mi_memory_changed);
      observer_attach_sync_execution_done (mi_on_sync_execution_done);

      /* The initial inferior is created before this function is
	 called, so we need to report it explicitly.  Use iteration in
	 case future version of GDB creates more than one inferior
	 up-front.  */
      iterate_over_inferiors (report_initial_inferior, mi);
    }

  return mi;
}