Esempio n. 1
0
static ptid_t
child_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
{
  int save_errno;
  int status;
  char *execd_pathname = NULL;
  int exit_status;
  int syscall_id;
  enum target_waitkind kind;
  int pid;

  do
    {
      set_sigint_trap ();	/* Causes SIGINT to be passed on to the
				   attached process. */
      set_sigio_trap ();

      pid = wait (&status);

      save_errno = errno;

      clear_sigio_trap ();

      clear_sigint_trap ();

      if (pid == -1)
	{
	  if (save_errno == EINTR)
	    continue;

	  fprintf_unfiltered (gdb_stderr, "Child process unexpectedly missing: %s.\n",
			      safe_strerror (save_errno));

	  /* Claim it exited with unknown signal.  */
	  ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
	  ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
	  return pid_to_ptid (-1);
	}

      /* Did it exit?
       */
      if (target_has_exited (pid, status, &exit_status))
	{
	  /* ??rehrauer: For now, ignore this. */
	  continue;
	}

      if (!target_thread_alive (pid_to_ptid (pid)))
	{
	  ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
	  return pid_to_ptid (pid);
	}
      } while (pid != PIDGET (inferior_ptid)); /* Some other child died or stopped */

  store_waitstatus (ourstatus, status);
  return pid_to_ptid (pid);
}
static ptid_t
rs6000_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
{
  pid_t pid;
  int status, save_errno;

  do
    {
      set_sigint_trap ();
      set_sigio_trap ();

      do
	{
	  pid = waitpid (ptid_get_pid (ptid), &status, 0);
	  save_errno = errno;
	}
      while (pid == -1 && errno == EINTR);

      clear_sigio_trap ();
      clear_sigint_trap ();

      if (pid == -1)
	{
	  fprintf_unfiltered (gdb_stderr,
			      _("Child process unexpectedly missing: %s.\n"),
			      safe_strerror (save_errno));

	  /* Claim it exited with unknown signal.  */
	  ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
	  ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
	  return minus_one_ptid;
	}

      /* Ignore terminated detached child processes.  */
      if (!WIFSTOPPED (status) && pid != ptid_get_pid (inferior_ptid))
	pid = -1;
    }
  while (pid == -1);

  /* AIX has a couple of strange returns from wait().  */

  /* stop after load" status.  */
  if (status == 0x57c)
    ourstatus->kind = TARGET_WAITKIND_LOADED;
  /* signal 0. I have no idea why wait(2) returns with this status word.  */
  else if (status == 0x7f)
    ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
  /* A normal waitstatus.  Let the usual macros deal with it.  */
  else
    store_waitstatus (ourstatus, status);

  return pid_to_ptid (pid);
}
ptid_t
child_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
{
  int save_errno;
  int thread;
  union wait status;
  int pid;

  while (1)
    {
      int sig;

      set_sigint_trap ();	/* Causes SIGINT to be passed on to the
				   attached process. */
      pid = wait (&status);

      save_errno = errno;

      clear_sigint_trap ();

      if (pid == -1)
	{
	  if (save_errno == EINTR)
	    continue;
	  fprintf_unfiltered (gdb_stderr, "Child process unexpectedly missing: %s.\n",
			      safe_strerror (save_errno));
	  /* Claim it exited with unknown signal.  */
	  ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
	  ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
	  return -1;
	}

      if (pid != PIDGET (inferior_ptid))	/* Some other process?!? */
	continue;

      thread = status.w_tid;	/* Get thread id from status */

      /* Initial thread value can only be acquired via wait, so we have to
         resort to this hack.  */

      if (TIDGET (inferior_ptid) == 0 && thread != 0)
	{
	  inferior_ptid = MERGEPID (PIDGET (inferior_ptid), thread);
	  add_thread (inferior_ptid);
	}

      ptid = BUILDPID (pid, thread);

      /* We've become a single threaded process again.  */
      if (thread == 0)
	inferior_ptid = ptid;

      /* Check for thread creation.  */
      if (WIFSTOPPED (status)
	  && WSTOPSIG (status) == SIGTRAP
	  && !in_thread_list (ptid))
	{
	  int realsig;

	  realsig = ptrace (PTRACE_GETTRACESIG, PIDGET (ptid),
	                    (PTRACE_ARG3_TYPE) 0, 0);

	  if (realsig == SIGNEWTHREAD)
	    {
	      /* It's a new thread notification.  We don't want to much with
	         realsig -- the code in wait_for_inferior expects SIGTRAP. */
	      ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
	      ourstatus->value.sig = TARGET_SIGNAL_0;
	      return ptid;
	    }
	  else
	    error ("Signal for unknown thread was not SIGNEWTHREAD");
	}

      /* Check for thread termination.  */
      else if (WIFSTOPPED (status)
	       && WSTOPSIG (status) == SIGTRAP
	       && in_thread_list (ptid))
	{
	  int realsig;

	  realsig = ptrace (PTRACE_GETTRACESIG, PIDGET (ptid),
	                    (PTRACE_ARG3_TYPE) 0, 0);

	  if (realsig == SIGTHREADEXIT)
	    {
	      ptrace (PTRACE_CONT, PIDGET (ptid), (PTRACE_ARG3_TYPE) 0, 0);
	      continue;
	    }
	}

#ifdef SPARC
      /* SPARC Lynx uses an byte reversed wait status; we must use the
         host macros to access it.  These lines just a copy of
         store_waitstatus.  We can't use CHILD_SPECIAL_WAITSTATUS
         because target.c can't include the Lynx <sys/wait.h>.  */
      if (WIFEXITED (status))
	{
	  ourstatus->kind = TARGET_WAITKIND_EXITED;
	  ourstatus->value.integer = WEXITSTATUS (status);
	}
      else if (!WIFSTOPPED (status))
	{
	  ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
	  ourstatus->value.sig =
	    target_signal_from_host (WTERMSIG (status));
	}
      else
	{
	  ourstatus->kind = TARGET_WAITKIND_STOPPED;
	  ourstatus->value.sig =
	    target_signal_from_host (WSTOPSIG (status));
	}
#else
      store_waitstatus (ourstatus, status.w_status);
#endif

      return ptid;
    }
}
Esempio n. 4
0
static ptid_t
inf_ptrace_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
{
  pid_t pid;
  int status, save_errno;

  do
    {
      set_sigint_trap ();
      set_sigio_trap ();

      do
	{
	  pid = waitpid (ptid_get_pid (ptid), &status, 0);
	  save_errno = errno;
	}
      while (pid == -1 && errno == EINTR);

      clear_sigio_trap ();
      clear_sigint_trap ();

      if (pid == -1)
	{
	  fprintf_unfiltered (gdb_stderr,
			      _("Child process unexpectedly missing: %s.\n"),
			      safe_strerror (save_errno));

	  /* Claim it exited with unknown signal.  */
	  ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
	  ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
	  return minus_one_ptid;
	}

      /* Ignore terminated detached child processes.  */
      if (!WIFSTOPPED (status) && pid != ptid_get_pid (inferior_ptid))
	pid = -1;
    }
  while (pid == -1);

#ifdef PT_GET_PROCESS_STATE
  if (WIFSTOPPED (status))
    {
      ptrace_state_t pe;
      pid_t fpid;

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

      switch (pe.pe_report_event)
	{
	case PTRACE_FORK:
	  ourstatus->kind = TARGET_WAITKIND_FORKED;
	  ourstatus->value.related_pid = pe.pe_other_pid;

	  /* Make sure the other end of the fork is stopped too.  */
	  fpid = waitpid (pe.pe_other_pid, &status, 0);
	  if (fpid == -1)
	    perror_with_name (("waitpid"));

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

	  gdb_assert (pe.pe_report_event == PTRACE_FORK);
	  gdb_assert (pe.pe_other_pid == pid);
	  if (fpid == ptid_get_pid (inferior_ptid))
	    {
	      ourstatus->value.related_pid = pe.pe_other_pid;
	      return pid_to_ptid (fpid);
	    }

	  return pid_to_ptid (pid);
	}
    }
#endif

  store_waitstatus (ourstatus, status);
  return pid_to_ptid (pid);
}
ptid_t
child_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
{
  int save_errno;
  int status;
  char *execd_pathname = NULL;
  int exit_status;
  int related_pid;
  int syscall_id;
  enum target_waitkind kind;
  int pid;

  if (saved_vfork_state == STATE_FAKE_EXEC)
    {
      saved_vfork_state = STATE_NONE;
      ourstatus->kind = TARGET_WAITKIND_EXECD;
      ourstatus->value.execd_pathname = saved_child_execd_pathname;
      return inferior_ptid;
    }

  do
    {
      set_sigint_trap ();	/* Causes SIGINT to be passed on to the
				   attached process. */
      set_sigio_trap ();

      pid = ptrace_wait (inferior_ptid, &status);

      save_errno = errno;

      clear_sigio_trap ();

      clear_sigint_trap ();

      if (pid == -1)
	{
	  if (save_errno == EINTR)
	    continue;

	  fprintf_unfiltered (gdb_stderr, "Child process unexpectedly missing: %s.\n",
			      safe_strerror (save_errno));

	  /* Claim it exited with unknown signal.  */
	  ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
	  ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
	  return pid_to_ptid (-1);
	}

      /* Did it exit?
       */
      if (target_has_exited (pid, status, &exit_status))
	{
	  /* ??rehrauer: For now, ignore this. */
	  continue;
	}

      if (!target_thread_alive (pid_to_ptid (pid)))
	{
	  ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
	  return pid_to_ptid (pid);
	}

      if (hpux_has_forked (pid, &related_pid))
	{
	  /* Ignore the parent's fork event.  */
	  if (pid == PIDGET (inferior_ptid))
	    {
	      ourstatus->kind = TARGET_WAITKIND_IGNORE;
	      return inferior_ptid;
	    }

	  /* If this is the child's fork event, report that the
	     process has forked.  */
	  if (related_pid == PIDGET (inferior_ptid))
	    {
	      ourstatus->kind = TARGET_WAITKIND_FORKED;
	      ourstatus->value.related_pid = pid;
	      return inferior_ptid;
	    }
	}

      if (hpux_has_vforked (pid, &related_pid))
	{
	  if (pid == PIDGET (inferior_ptid))
	    {
	      if (saved_vfork_state == STATE_GOT_CHILD)
		saved_vfork_state = STATE_GOT_PARENT;
	      else if (saved_vfork_state == STATE_GOT_EXEC)
		saved_vfork_state = STATE_FAKE_EXEC;
	      else
		fprintf_unfiltered (gdb_stdout,
				    "hppah: parent vfork: confused\n");
	    }
	  else if (related_pid == PIDGET (inferior_ptid))
	    {
	      if (saved_vfork_state == STATE_NONE)
		saved_vfork_state = STATE_GOT_CHILD;
	      else
		fprintf_unfiltered (gdb_stdout,
				    "hppah: child vfork: confused\n");
	    }
	  else
	    fprintf_unfiltered (gdb_stdout,
				"hppah: unknown vfork: confused\n");

	  if (saved_vfork_state == STATE_GOT_CHILD)
	    {
	      child_post_startup_inferior (pid_to_ptid (pid));
	      detach_breakpoints (pid);
#ifdef SOLIB_REMOVE_INFERIOR_HOOK
	      SOLIB_REMOVE_INFERIOR_HOOK (pid);
#endif
	      child_resume (pid_to_ptid (pid), 0, TARGET_SIGNAL_0);
	      ourstatus->kind = TARGET_WAITKIND_IGNORE;
	      return pid_to_ptid (related_pid);
	    }
	  else if (saved_vfork_state == STATE_FAKE_EXEC)
	    {
	      ourstatus->kind = TARGET_WAITKIND_VFORKED;
	      ourstatus->value.related_pid = related_pid;
	      return pid_to_ptid (pid);
	    }
	  else
	    {
	      /* We saw the parent's vfork, but we haven't seen the exec yet.
		 Wait for it, for simplicity's sake.  It should be pending.  */
	      saved_vfork_pid = related_pid;
	      ourstatus->kind = TARGET_WAITKIND_IGNORE;
	      return pid_to_ptid (pid);
	    }
	}

      if (hpux_has_execd (pid, &execd_pathname))
	{
	  /* On HP-UX, events associated with a vforking inferior come in
	     threes: a vfork event for the child (always first), followed
	     a vfork event for the parent and an exec event for the child.
	     The latter two can come in either order.  Make sure we get
	     both.  */
	  if (saved_vfork_state != STATE_NONE)
	    {
	      if (saved_vfork_state == STATE_GOT_CHILD)
		{
		  saved_vfork_state = STATE_GOT_EXEC;
		  /* On HP/UX with ptrace, the child must be resumed before
		     the parent vfork event is delivered.  A single-step
		     suffices.  */
		  if (RESUME_EXECD_VFORKING_CHILD_TO_GET_PARENT_VFORK ())
		    target_resume (pid_to_ptid (pid), 1, TARGET_SIGNAL_0);
		  ourstatus->kind = TARGET_WAITKIND_IGNORE;
		}
	      else if (saved_vfork_state == STATE_GOT_PARENT)
		{
		  saved_vfork_state = STATE_FAKE_EXEC;
		  ourstatus->kind = TARGET_WAITKIND_VFORKED;
		  ourstatus->value.related_pid = saved_vfork_pid;
		}
	      else
		fprintf_unfiltered (gdb_stdout,
				    "hppa: exec: unexpected state\n");

	      saved_child_execd_pathname = execd_pathname;

	      return inferior_ptid;
	    }
	  
	  /* Are we ignoring initial exec events?  (This is likely because
	     we're in the process of starting up the inferior, and another
	     (older) mechanism handles those.)  If so, we'll report this
	     as a regular stop, not an exec.
	   */
	  if (inferior_ignoring_startup_exec_events)
	    {
	      inferior_ignoring_startup_exec_events--;
	    }
	  else
	    {
	      ourstatus->kind = TARGET_WAITKIND_EXECD;
	      ourstatus->value.execd_pathname = execd_pathname;
	      return pid_to_ptid (pid);
	    }
	}

      /* All we must do with these is communicate their occurrence
         to wait_for_inferior...
       */
      if (hpux_has_syscall_event (pid, &kind, &syscall_id))
	{
	  ourstatus->kind = kind;
	  ourstatus->value.syscall_id = syscall_id;
	  return pid_to_ptid (pid);
	}

      /*##  } while (pid != PIDGET (inferior_ptid)); ## *//* Some other child died or stopped */
/* hack for thread testing */
    }
  while ((pid != PIDGET (inferior_ptid)) && not_same_real_pid);
/*## */

  store_waitstatus (ourstatus, status);
  return pid_to_ptid (pid);
}
Esempio n. 6
0
static ptid_t
child_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
{
  int save_errno;
  int status;
  char *execd_pathname = NULL;
  int exit_status;
  int related_pid;
  int syscall_id;
  enum target_waitkind kind;
  int pid;

  do
    {
      set_sigint_trap ();	/* Causes SIGINT to be passed on to the
				   attached process. */
      set_sigio_trap ();

      pid = ptrace_wait (inferior_ptid, &status);

      save_errno = errno;

      clear_sigio_trap ();

      clear_sigint_trap ();

      if (pid == -1)
	{
	  if (save_errno == EINTR)
	    continue;

	  fprintf_unfiltered (gdb_stderr, "Child process unexpectedly missing: %s.\n",
			      safe_strerror (save_errno));

	  /* Claim it exited with unknown signal.  */
	  ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
	  ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
	  return pid_to_ptid (-1);
	}

      /* Did it exit?
       */
      if (target_has_exited (pid, status, &exit_status))
	{
	  /* ??rehrauer: For now, ignore this. */
	  continue;
	}

      if (!target_thread_alive (pid_to_ptid (pid)))
	{
	  ourstatus->kind = TARGET_WAITKIND_SPURIOUS;
	  return pid_to_ptid (pid);
	}

      if (target_has_forked (pid, &related_pid)
	  && ((pid == PIDGET (inferior_ptid)) 
	      || (related_pid == PIDGET (inferior_ptid))))
	{
	  ourstatus->kind = TARGET_WAITKIND_FORKED;
	  ourstatus->value.related_pid = related_pid;
	  return pid_to_ptid (pid);
	}

      if (target_has_vforked (pid, &related_pid)
	  && ((pid == PIDGET (inferior_ptid))
	      || (related_pid == PIDGET (inferior_ptid))))
	{
	  ourstatus->kind = TARGET_WAITKIND_VFORKED;
	  ourstatus->value.related_pid = related_pid;
	  return pid_to_ptid (pid);
	}

      if (target_has_execd (pid, &execd_pathname))
	{
	  /* Are we ignoring initial exec events?  (This is likely because
	     we're in the process of starting up the inferior, and another
	     (older) mechanism handles those.)  If so, we'll report this
	     as a regular stop, not an exec.
	   */
	  if (inferior_ignoring_startup_exec_events)
	    {
	      inferior_ignoring_startup_exec_events--;
	    }
	  else
	    {
	      ourstatus->kind = TARGET_WAITKIND_EXECD;
	      ourstatus->value.execd_pathname = execd_pathname;
	      return pid_to_ptid (pid);
	    }
	}

      /* All we must do with these is communicate their occurrence
         to wait_for_inferior...
       */
      if (target_has_syscall_event (pid, &kind, &syscall_id))
	{
	  ourstatus->kind = kind;
	  ourstatus->value.syscall_id = syscall_id;
	  return pid_to_ptid (pid);
	}

      /*##  } while (pid != PIDGET (inferior_ptid)); ## *//* Some other child died or stopped */
/* hack for thread testing */
    }
  while ((pid != PIDGET (inferior_ptid)) && not_same_real_pid);
/*## */

  store_waitstatus (ourstatus, status);
  return pid_to_ptid (pid);
}