static void
gdbsim_kill (void)
{
  if (sr_get_debug ())
    printf_filtered ("gdbsim_kill\n");

  /* There is no need to `kill' running simulator - the simulator is
     not running.  Mourning it is enough.  */
  target_mourn_inferior ();
}
Example #2
0
static void
gdbsim_kill (struct target_ops *ops)
{
  if (remote_debug)
    printf_filtered ("gdbsim_kill\n");

  /* There is no need to `kill' running simulator - the simulator is
     not running.  Mourning it is enough.  */
  target_mourn_inferior ();
}
static void
inf_ptrace_kill (void)
{
  pid_t pid = ptid_get_pid (inferior_ptid);
  int status;

  if (pid == 0)
    return;

  ptrace (PT_KILL, pid, (PTRACE_TYPE_ARG3)0, 0);
  waitpid (pid, &status, 0);

  target_mourn_inferior ();
}
Example #4
0
void
inf_ptrace_target::kill ()
{
  pid_t pid = inferior_ptid.pid ();
  int status;

  if (pid == 0)
    return;

  ptrace (PT_KILL, pid, (PTRACE_TYPE_ARG3)0, 0);
  waitpid (pid, &status, 0);

  target_mourn_inferior (inferior_ptid);
}
Example #5
0
static void
inf_ptrace_kill (struct target_ops *ops)
{
  pid_t pid = ptid_get_pid (inferior_ptid);
  int status;

  if (pid == FAKE_PROCESS_ID)
    return;

  ptrace (PT_KILL, pid, (PTRACE_TYPE_ARG3)0, 0);
  waitpid (pid, &status, 0);

  target_mourn_inferior ();
}
Example #6
0
static void
haiku_child_kill_inferior (void)
{
	status_t err;
	thread_id teamID = ptid_get_pid(inferior_ptid);

	TRACE(("haiku_child_kill_inferior()\n"));

	err = kill_team(teamID);
	if (err != B_OK) {
		printf_unfiltered ("Failed to kill team %ld: %s\n", teamID,
			strerror(err));
		return;
	}

	target_mourn_inferior();
}
void
kill_inferior (void)
{
  int status;
  int pid =  PIDGET (inferior_ptid);

  if (pid == 0)
    return;

  /* This once used to call "kill" to kill the inferior just in case
     the inferior was still running.  As others have noted in the past
     (kingdon) there shouldn't be any way to get here if the inferior
     is still running -- else there's a major problem elsewere in gdb
     and it needs to be fixed.

     The kill call causes problems under hpux10, so it's been removed;
     if this causes problems we'll deal with them as they arise.  */
  ptrace (PT_KILL, pid, (PTRACE_TYPE_ARG3) 0, 0);
  wait (&status);
  target_mourn_inferior ();
}
Example #8
0
void
startup_inferior (int ntraps)
{
  int pending_execs = ntraps;
  int terminal_initted = 0;
  ptid_t resume_ptid;

  if (target_supports_multi_process ())
    resume_ptid = pid_to_ptid (ptid_get_pid (inferior_ptid));
  else
    resume_ptid = minus_one_ptid;

  /* The process was started by the fork that created it, but it will
     have stopped one instruction after execing the shell.  Here we
     must get it up to actual execution of the real program.  */

  if (exec_wrapper)
    pending_execs++;

  while (1)
    {
      enum target_signal resume_signal = TARGET_SIGNAL_0;
      ptid_t event_ptid;

      struct target_waitstatus ws;
      memset (&ws, 0, sizeof (ws));
      event_ptid = target_wait (resume_ptid, &ws, 0);

      if (ws.kind == TARGET_WAITKIND_IGNORE)
	/* The inferior didn't really stop, keep waiting.  */
	continue;

      switch (ws.kind)
	{
	  case TARGET_WAITKIND_SPURIOUS:
	  case TARGET_WAITKIND_LOADED:
	  case TARGET_WAITKIND_FORKED:
	  case TARGET_WAITKIND_VFORKED:
	  case TARGET_WAITKIND_SYSCALL_ENTRY:
	  case TARGET_WAITKIND_SYSCALL_RETURN:
	    /* Ignore gracefully during startup of the inferior.  */
	    switch_to_thread (event_ptid);
	    break;

	  case TARGET_WAITKIND_SIGNALLED:
	    target_terminal_ours ();
	    target_mourn_inferior ();
	    error (_("During startup program terminated with signal %s, %s."),
		   target_signal_to_name (ws.value.sig),
		   target_signal_to_string (ws.value.sig));
	    return;

	  case TARGET_WAITKIND_EXITED:
	    target_terminal_ours ();
	    target_mourn_inferior ();
	    if (ws.value.integer)
	      error (_("During startup program exited with code %d."),
		     ws.value.integer);
	    else
	      error (_("During startup program exited normally."));
	    return;

	  case TARGET_WAITKIND_EXECD:
	    /* Handle EXEC signals as if they were SIGTRAP signals.  */
	    xfree (ws.value.execd_pathname);
	    resume_signal = TARGET_SIGNAL_TRAP;
	    switch_to_thread (event_ptid);
	    break;

	  case TARGET_WAITKIND_STOPPED:
	    resume_signal = ws.value.sig;
	    switch_to_thread (event_ptid);
	    break;
	}

      if (resume_signal != TARGET_SIGNAL_TRAP)
	{
	  /* Let shell child handle its own signals in its own way.  */
	  target_resume (resume_ptid, 0, resume_signal);
	}
      else
	{
	  /* We handle SIGTRAP, however; it means child did an exec.  */
	  if (!terminal_initted)
	    {
	      /* Now that the child has exec'd we know it has already
	         set its process group.  On POSIX systems, tcsetpgrp
	         will fail with EPERM if we try it before the child's
	         setpgid.  */

	      /* Set up the "saved terminal modes" of the inferior
	         based on what modes we are starting it with.  */
	      target_terminal_init ();

	      /* Install inferior's terminal modes.  */
	      target_terminal_inferior ();

	      terminal_initted = 1;
	    }

	  if (--pending_execs == 0)
	    break;

	  /* Just make it go on.  */
	  target_resume (resume_ptid, 0, TARGET_SIGNAL_0);
	}
    }

  /* Mark all threads non-executing.  */
  set_executing (resume_ptid, 0);
}
Example #9
0
/* An inferior Unix process CHILD_PID has been created by a call to
   fork() (or variants like vfork).  It is presently stopped, and waiting
   to be resumed.  clone_and_follow_inferior will fork the debugger,
   and that clone will "follow" (attach to) CHILD_PID.  The original copy
   of the debugger will not touch CHILD_PID again.

   Also, the original debugger will set FOLLOWED_CHILD FALSE, while the
   clone will set it TRUE.
 */
void
clone_and_follow_inferior (int child_pid, int *followed_child)
{
  int debugger_pid;
  int status;
  char pid_spelling[100];	/* Arbitrary but sufficient length. */

  /* This semaphore is used to coordinate the two debuggers' handoff
     of CHILD_PID.  The original debugger will detach from CHILD_PID,
     and then the clone debugger will attach to it.  (It must be done
     this way because on some targets, only one process at a time can
     trace another.  Thus, the original debugger must relinquish its
     tracing rights before the clone can pick them up.)
   */
#define SEM_TALK (1)
#define SEM_LISTEN (0)
  int handoff_semaphore[2];	/* Original "talks" to [1], clone "listens" to [0] */
  int talk_value = 99;
  int listen_value;

  /* Set debug_fork then attach to the child while it sleeps, to debug. */
  static int debug_fork = 0;

  /* It is generally good practice to flush any possible pending stdio
     output prior to doing a fork, to avoid the possibility of both the
     parent and child flushing the same data after the fork. */

  gdb_flush (gdb_stdout);
  gdb_flush (gdb_stderr);

  /* Open the semaphore pipes.
   */
  status = pipe (handoff_semaphore);
  if (status < 0)
    error ("error getting pipe for handoff semaphore");

  /* Clone the debugger.  Note that the apparent call to vfork()
     below *might* actually be a call to fork() due to the fact that
     autoconf will ``#define vfork fork'' on certain platforms.  */
  if (debug_fork)
    debugger_pid = fork ();
  else
    debugger_pid = vfork ();

  if (debugger_pid < 0)
    perror_with_name ("fork");

  /* Are we the original debugger?  If so, we must relinquish all claims
     to CHILD_PID. */
  if (debugger_pid != 0)
    {
      char signal_spelling[100];	/* Arbitrary but sufficient length */

      /* Detach from CHILD_PID.  Deliver a "stop" signal when we do, though,
         so that it remains stopped until the clone debugger can attach
         to it.
       */
      detach_breakpoints (child_pid);

      sprintf (signal_spelling, "%d", target_signal_to_host (TARGET_SIGNAL_STOP));
      target_require_detach (child_pid, signal_spelling, 1);

      /* Notify the clone debugger that it should attach to CHILD_PID. */
      write (handoff_semaphore[SEM_TALK], &talk_value, sizeof (talk_value));

      *followed_child = 0;
    }

  /* We're the child. */
  else
    {
      if (debug_fork)
	sleep (debug_fork);

      /* The child (i.e., the cloned debugger) must now attach to
         CHILD_PID.  inferior_ptid is presently set to the parent process
         of the fork, while CHILD_PID should be the child process of the
         fork.

         Wait until the original debugger relinquishes control of CHILD_PID,
         though.
       */
      read (handoff_semaphore[SEM_LISTEN], &listen_value, sizeof (listen_value));

      /* Note that we DON'T want to actually detach from inferior_ptid,
         because that would allow it to run free.  The original
         debugger wants to retain control of the process.  So, we
         just reset inferior_ptid to CHILD_PID, and then ensure that all
         breakpoints are really set in CHILD_PID.
       */
      target_mourn_inferior ();

      /* Ask the tty subsystem to switch to the one we specified earlier
         (or to share the current terminal, if none was specified).  */

      new_tty ();

      dont_repeat ();
      sprintf (pid_spelling, "%d", child_pid);
      target_require_attach (pid_spelling, 1);

      /* Perform any necessary cleanup, after attachment.  (This form
         of attaching can behave differently on some targets than the
         standard method, where a process formerly not under debugger
         control was suddenly attached to..)
       */
      target_post_follow_inferior_by_clone ();

      *followed_child = 1;
    }

  /* Discard the handoff sempahore. */
  (void) close (handoff_semaphore[SEM_LISTEN]);
  (void) close (handoff_semaphore[SEM_TALK]);
}