Example #1
0
static void
mi_on_normal_stop (struct bpstats *bs, int print_frame)
{
    /* Since this can be called when CLI command is executing,
       using cli interpreter, be sure to use MI uiout for output,
       not the current one.  */
    struct ui_out *mi_uiout = interp_ui_out (top_level_interpreter ());

    if (print_frame)
    {
        int core;

        if (current_uiout != mi_uiout)
        {
            /* The normal_stop function has printed frame information
               into CLI uiout, or some other non-MI uiout.  There's no
               way we can extract proper fields from random uiout
               object, so we print the frame again.  In practice, this
               can only happen when running a CLI command in MI.  */
            struct ui_out *saved_uiout = current_uiout;
            struct target_waitstatus last;
            ptid_t last_ptid;

            current_uiout = mi_uiout;

            get_last_target_status (&last_ptid, &last);
            bpstat_print (bs, last.kind);

            print_stack_frame (get_selected_frame (NULL), 0, SRC_AND_LOC, 1);
            current_uiout = saved_uiout;
        }

        ui_out_field_int (mi_uiout, "thread-id",
                          pid_to_thread_id (inferior_ptid));
        if (non_stop)
        {
            struct cleanup *back_to = make_cleanup_ui_out_list_begin_end
                                      (mi_uiout, "stopped-threads");

            ui_out_field_int (mi_uiout, NULL,
                              pid_to_thread_id (inferior_ptid));
            do_cleanups (back_to);
        }
        else
            ui_out_field_string (mi_uiout, "stopped-threads", "all");

        core = target_core_of_thread (inferior_ptid);
        if (core != -1)
            ui_out_field_int (mi_uiout, "core", core);
    }

    fputs_unfiltered ("*stopped", raw_stdout);
    mi_out_put (mi_uiout, raw_stdout);
    mi_out_rewind (mi_uiout);
    mi_print_timing_maybe ();
    fputs_unfiltered ("\n", raw_stdout);
    gdb_flush (raw_stdout);
}
Example #2
0
/* Generic prepare_to_proceed().  This one should be suitable for most
   targets that support threads. */
int
generic_prepare_to_proceed (int select_it)
{
  ptid_t wait_ptid;
  struct target_waitstatus wait_status;

  /* Get the last target status returned by target_wait().  */
  get_last_target_status (&wait_ptid, &wait_status);

  /* Make sure we were stopped either at a breakpoint, or because
     of a Ctrl-C.  */
  if (wait_status.kind != TARGET_WAITKIND_STOPPED
      || (wait_status.value.sig != TARGET_SIGNAL_TRAP &&
          wait_status.value.sig != TARGET_SIGNAL_INT))
    {
      return 0;
    }

  if (!ptid_equal (wait_ptid, minus_one_ptid)
      && !ptid_equal (inferior_ptid, wait_ptid))
    {
      /* Switched over from WAIT_PID.  */
      CORE_ADDR wait_pc = read_pc_pid (wait_ptid);

      if (wait_pc != read_pc ())
	{
	  if (select_it)
	    {
	      /* Switch back to WAIT_PID thread.  */
	      inferior_ptid = wait_ptid;

	      /* FIXME: This stuff came from switch_to_thread() in
		 thread.c (which should probably be a public function).  */
	      flush_cached_frames ();
	      registers_changed ();
	      stop_pc = wait_pc;
	      select_frame (get_current_frame ());
	    }
          /* We return 1 to indicate that there is a breakpoint here,
             so we need to step over it before continuing to avoid
             hitting it straight away. */
          if (breakpoint_here_p (wait_pc))
            {
	      return 1;
            }
	}
    }
  return 0;
  
}
static int
inf_ptrace_follow_fork (struct target_ops *ops, int follow_child)
{
  pid_t pid, fpid;
  ptrace_state_t pe;

  /* FIXME: kettenis/20050720: This stuff should really be passed as
     an argument by our caller.  */
  {
    ptid_t ptid;
    struct target_waitstatus status;

    get_last_target_status (&ptid, &status);
    gdb_assert (status.kind == TARGET_WAITKIND_FORKED);

    pid = ptid_get_pid (ptid);
  }

  if (ptrace (PT_GET_PROCESS_STATE, pid,
	       (PTRACE_TYPE_ARG3)&pe, sizeof pe) == -1)
    perror_with_name (("ptrace"));

  gdb_assert (pe.pe_report_event == PTRACE_FORK);
  fpid = pe.pe_other_pid;

  if (follow_child)
    {
      inferior_ptid = pid_to_ptid (fpid);
      detach_breakpoints (pid);

      /* Reset breakpoints in the child as appropriate.  */
      follow_inferior_reset_breakpoints ();

      if (ptrace (PT_DETACH, pid, (PTRACE_TYPE_ARG3)1, 0) == -1)
	perror_with_name (("ptrace"));
    }
  else
    {
      inferior_ptid = pid_to_ptid (pid);
      detach_breakpoints (fpid);

      if (ptrace (PT_DETACH, fpid, (PTRACE_TYPE_ARG3)1, 0) == -1)
	perror_with_name (("ptrace"));
    }

  return 0;
}
Example #4
0
static enum print_stop_action
signal_catchpoint_print_it (bpstat bs)
{
  struct breakpoint *b = bs->breakpoint_at;
  ptid_t ptid;
  struct target_waitstatus last;
  const char *signal_name;

  get_last_target_status (&ptid, &last);

  signal_name = signal_to_name_or_int (last.value.sig);

  annotate_catchpoint (b->number);

  printf_filtered (_("\nCatchpoint %d (signal %s), "), b->number, signal_name);

  return PRINT_SRC_AND_LOC;
}
Example #5
0
static void
mi_on_normal_stop (struct bpstats *bs, int print_frame)
{
  /* Since this can be called when CLI command is executing,
     using cli interpreter, be sure to use MI uiout for output,
     not the current one.  */
  struct ui_out *mi_uiout = interp_ui_out (top_level_interpreter ());

  if (print_frame)
    {
      int core;

      if (current_uiout != mi_uiout)
	{
	  /* The normal_stop function has printed frame information
	     into CLI uiout, or some other non-MI uiout.  There's no
	     way we can extract proper fields from random uiout
	     object, so we print the frame again.  In practice, this
	     can only happen when running a CLI command in MI.  */
	  struct ui_out *saved_uiout = current_uiout;
	  struct target_waitstatus last;
	  ptid_t last_ptid;

	  current_uiout = mi_uiout;

	  get_last_target_status (&last_ptid, &last);
	  print_stop_event (&last);

	  current_uiout = saved_uiout;
	}
      /* Otherwise, frame information has already been printed by
	 normal_stop.  */
      else
	{
	  /* Breakpoint hits should always be mirrored to the console.
	     Deciding what to mirror to the console wrt to breakpoints
	     and random stops gets messy real fast.  E.g., say "s"
	     trips on a breakpoint.  We'd clearly want to mirror the
	     event to the console in this case.  But what about more
	     complicated cases like "s&; thread n; s&", and one of
	     those steps spawning a new thread, and that thread
	     hitting a breakpoint?  It's impossible in general to
	     track whether the thread had any relation to the commands
	     that had been executed.  So we just simplify and always
	     mirror breakpoints and random events to the console.

	     Also, CLI execution commands (-interpreter-exec console
	     "next", for example) in async mode have the opposite
	     issue as described in the "then" branch above --
	     normal_stop has already printed frame information to MI
	     uiout, but nothing has printed the same information to
	     the CLI channel.  We should print the source line to the
	     console when stepping or other similar commands, iff the
	     step was started by a console command (but not if it was
	     started with -exec-step or similar).  */
	  struct thread_info *tp = inferior_thread ();

	  if ((!tp->control.stop_step
		  && !tp->control.proceed_to_finish)
	      || (tp->control.command_interp != NULL
		  && tp->control.command_interp != top_level_interpreter ()))
	    {
	      struct mi_interp *mi = top_level_interpreter_data ();
	      struct target_waitstatus last;
	      ptid_t last_ptid;
	      struct cleanup *old_chain;

	      /* Set the current uiout to CLI uiout temporarily.  */
	      old_chain = make_cleanup (restore_current_uiout_cleanup,
					current_uiout);
	      current_uiout = mi->cli_uiout;

	      get_last_target_status (&last_ptid, &last);
	      print_stop_event (&last);

	      do_cleanups (old_chain);
	    }
	}

      ui_out_field_int (mi_uiout, "thread-id",
			pid_to_thread_id (inferior_ptid));
      if (non_stop)
	{
	  struct cleanup *back_to = make_cleanup_ui_out_list_begin_end 
	    (mi_uiout, "stopped-threads");

	  ui_out_field_int (mi_uiout, NULL,
			    pid_to_thread_id (inferior_ptid));
	  do_cleanups (back_to);
	}
      else
	ui_out_field_string (mi_uiout, "stopped-threads", "all");

      core = target_core_of_thread (inferior_ptid);
      if (core != -1)
	ui_out_field_int (mi_uiout, "core", core);
    }
  
  fputs_unfiltered ("*stopped", raw_stdout);
  mi_out_put (mi_uiout, raw_stdout);
  mi_out_rewind (mi_uiout);
  mi_print_timing_maybe ();
  fputs_unfiltered ("\n", raw_stdout);
  gdb_flush (raw_stdout);
}
int
child_follow_fork (int follow_child)
{
  ptid_t last_ptid;
  struct target_waitstatus last_status;
  int has_vforked;
  int parent_pid, child_pid;

  get_last_target_status (&last_ptid, &last_status);
  has_vforked = (last_status.kind == TARGET_WAITKIND_VFORKED);
  parent_pid = ptid_get_pid (last_ptid);
  child_pid = last_status.value.related_pid;

  /* At this point, if we are vforking, breakpoints were already
     detached from the child in child_wait; and the child has already
     called execve().  If we are forking, both the parent and child
     have breakpoints inserted.  */

  if (! follow_child)
    {
      if (! has_vforked)
	{
	  detach_breakpoints (child_pid);
#ifdef SOLIB_REMOVE_INFERIOR_HOOK
	  SOLIB_REMOVE_INFERIOR_HOOK (child_pid);
#endif
	}

      /* Detach from the child. */
      printf_unfiltered ("Detaching after fork from %s\n",
			 target_pid_to_str (pid_to_ptid (child_pid)));
      hppa_require_detach (child_pid, 0);

      /* The parent and child of a vfork share the same address space.
	 Also, on some targets the order in which vfork and exec events
	 are received for parent in child requires some delicate handling
	 of the events.

	 For instance, on ptrace-based HPUX we receive the child's vfork
	 event first, at which time the parent has been suspended by the
	 OS and is essentially untouchable until the child's exit or second
	 exec event arrives.  At that time, the parent's vfork event is
	 delivered to us, and that's when we see and decide how to follow
	 the vfork.  But to get to that point, we must continue the child
	 until it execs or exits.  To do that smoothly, all breakpoints
	 must be removed from the child, in case there are any set between
	 the vfork() and exec() calls.  But removing them from the child
	 also removes them from the parent, due to the shared-address-space
	 nature of a vfork'd parent and child.  On HPUX, therefore, we must
	 take care to restore the bp's to the parent before we continue it.
	 Else, it's likely that we may not stop in the expected place.  (The
	 worst scenario is when the user tries to step over a vfork() call;
	 the step-resume bp must be restored for the step to properly stop
	 in the parent after the call completes!)

	 Sequence of events, as reported to gdb from HPUX:

	 Parent        Child           Action for gdb to take
	 -------------------------------------------------------
	 1                VFORK               Continue child
	 2                EXEC
	 3                EXEC or EXIT
	 4  VFORK

	 Now that the child has safely exec'd or exited, we must restore
	 the parent's breakpoints before we continue it.  Else, we may
	 cause it run past expected stopping points.  */

      if (has_vforked)
	reattach_breakpoints (parent_pid);
    }
  else
    {
      /* Needed to keep the breakpoint lists in sync.  */
      if (! has_vforked)
	detach_breakpoints (child_pid);

      /* Before detaching from the parent, remove all breakpoints from it. */
      remove_breakpoints ();

      /* Also reset the solib inferior hook from the parent. */
#ifdef SOLIB_REMOVE_INFERIOR_HOOK
      SOLIB_REMOVE_INFERIOR_HOOK (PIDGET (inferior_ptid));
#endif

      /* Detach from the parent. */
      target_detach (NULL, 1);

      /* Attach to the child. */
      printf_unfiltered ("Attaching after fork to %s\n",
			 target_pid_to_str (pid_to_ptid (child_pid)));
      hppa_require_attach (child_pid);
      inferior_ptid = pid_to_ptid (child_pid);

      /* If we vforked, then we've also execed by now.  The exec will be
	 reported momentarily.  follow_exec () will handle breakpoints, so
	 we don't have to..  */
      if (!has_vforked)
	follow_inferior_reset_breakpoints ();
    }

  if (has_vforked)
    {
      /* If we followed the parent, don't try to follow the child's exec.  */
      if (saved_vfork_state != STATE_GOT_PARENT
	  && saved_vfork_state != STATE_FAKE_EXEC)
	fprintf_unfiltered (gdb_stdout,
			    "hppa: post follow vfork: confused state\n");

      if (! follow_child || saved_vfork_state == STATE_GOT_PARENT)
	saved_vfork_state = STATE_NONE;
      else
	return 1;
    }
  return 0;
}