Пример #1
0
static void
nbsd_update_thread_list (struct target_ops *ops)
{
  int retval;
  ptid_t ptid;

  if (nbsd_thread_active == 0)
	  return;

  if (ptid_equal (inferior_ptid, minus_one_ptid))
    {
      printf_filtered ("No process.\n");
      return;
    }

  if (target_has_execution)
    {
      struct ptrace_lwpinfo pl;
      pl.pl_lwpid = 0;
      retval = ptrace (PT_LWPINFO, ptid_get_pid(inferior_ptid), (void *)&pl, sizeof(pl));
      while ((retval != -1) && pl.pl_lwpid != 0)
	{
	  ptid = ptid_build (ptid_get_pid (main_ptid), pl.pl_lwpid, 0);
	  if (!in_thread_list (ptid))
	    add_thread (ptid);
	  retval = ptrace (PT_LWPINFO, ptid_get_pid(inferior_ptid), (void *)&pl, sizeof(pl));
	}
    }
}
Пример #2
0
static void
attach_thread (ptid_t ptid, const td_thrhandle_t *th_p,
               const td_thrinfo_t *ti_p, int verbose)
{
  td_err_e err;

  /* Add the thread to GDB's thread list.  */
  if (!in_thread_list (ptid)) {
    add_thread (ptid);
    if (verbose)
      printf_unfiltered ("[New %s]\n", target_pid_to_str (ptid));
  }

  if (ti_p->ti_state == TD_THR_UNKNOWN || ti_p->ti_state == TD_THR_ZOMBIE)
    return;                     /* A zombie thread -- do not attach.  */

  if (! IS_THREAD(ptid))
    return;
  if (fbsd_thread_core != 0)
    return;
  /* Enable thread event reporting for this thread. */
  err = td_thr_event_enable_p (th_p, 1);
  if (err != TD_OK)
    error ("Cannot enable thread event reporting for %s: %s",
           target_pid_to_str (ptid), thread_db_err_str (err));
}
Пример #3
0
static void
obsd_update_thread_list (struct target_ops *ops)
{
  pid_t pid = ptid_get_pid (inferior_ptid);
  struct ptrace_thread_state pts;

  prune_threads ();

  if (ptrace (PT_GET_THREAD_FIRST, pid, (caddr_t)&pts, sizeof pts) == -1)
    perror_with_name (("ptrace"));

  while (pts.pts_tid != -1)
    {
      ptid_t ptid = ptid_build (pid, pts.pts_tid, 0);

      if (!in_thread_list (ptid))
	{
	  if (ptid_get_lwp (inferior_ptid) == 0)
	    thread_change_ptid (inferior_ptid, ptid);
	  else
	    add_thread (ptid);
	}

      if (ptrace (PT_GET_THREAD_NEXT, pid, (caddr_t)&pts, sizeof pts) == -1)
	perror_with_name (("ptrace"));
    }
}
Пример #4
0
static void
fbsd_add_threads (pid_t pid)
{
  struct cleanup *cleanup;
  lwpid_t *lwps;
  int i, nlwps;

  gdb_assert (!in_thread_list (pid_to_ptid (pid)));
  nlwps = ptrace (PT_GETNUMLWPS, pid, NULL, 0);
  if (nlwps == -1)
    perror_with_name (("ptrace"));

  lwps = XCNEWVEC (lwpid_t, nlwps);
  cleanup = make_cleanup (xfree, lwps);

  nlwps = ptrace (PT_GETLWPLIST, pid, (caddr_t) lwps, nlwps);
  if (nlwps == -1)
    perror_with_name (("ptrace"));

  for (i = 0; i < nlwps; i++)
    {
      ptid_t ptid = ptid_build (pid, lwps[i], 0);

      if (!in_thread_list (ptid))
	{
#ifdef PT_LWP_EVENTS
	  struct ptrace_lwpinfo pl;

	  /* Don't add exited threads.  Note that this is only called
	     when attaching to a multi-threaded process.  */
	  if (ptrace (PT_LWPINFO, lwps[i], (caddr_t) &pl, sizeof pl) == -1)
	    perror_with_name (("ptrace"));
	  if (pl.pl_flags & PL_FLAG_EXITED)
	    continue;
#endif
	  if (debug_fbsd_lwp)
	    fprintf_unfiltered (gdb_stdlog,
				"FLWP: adding thread for LWP %u\n",
				lwps[i]);
	  add_thread (ptid);
	}
    }
  do_cleanups (cleanup);
}
Пример #5
0
static ptid_t
sol_thread_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
{
  ptid_t rtnval;
  ptid_t save_ptid;
  struct cleanup *old_chain;

  save_ptid = inferior_ptid;
  old_chain = save_inferior_ptid ();

  inferior_ptid = thread_to_lwp (inferior_ptid, PIDGET (main_ph.ptid));
  if (PIDGET (inferior_ptid) == -1)
    inferior_ptid = procfs_first_available ();

  if (PIDGET (ptid) != -1)
    {
      ptid_t save_ptid = ptid;

      ptid = thread_to_lwp (ptid, -2);
      if (PIDGET (ptid) == -2)		/* Inactive thread */
	error ("This version of Solaris can't start inactive threads.");
      if (info_verbose && PIDGET (ptid) == -1)
	warning ("Specified thread %ld seems to have terminated",
		 GET_THREAD (save_ptid));
    }

  rtnval = procfs_ops.to_wait (ptid, ourstatus);

  if (ourstatus->kind != TARGET_WAITKIND_EXITED)
    {
      /* Map the LWP of interest back to the appropriate thread ID */
      rtnval = lwp_to_thread (rtnval);
      if (PIDGET (rtnval) == -1)
	rtnval = save_ptid;

      /* See if we have a new thread */
      if (is_thread (rtnval)
	  && !ptid_equal (rtnval, save_ptid)
	  && !in_thread_list (rtnval))
	{
	  printf_filtered ("[New %s]\n", target_pid_to_str (rtnval));
	  add_thread (rtnval);
	}
    }

  /* During process initialization, we may get here without the thread package
     being initialized, since that can only happen after we've found the shared
     libs.  */

  do_cleanups (old_chain);

  return rtnval;
}
Пример #6
0
static void
check_event (ptid_t ptid)
{
  struct regcache *regcache = get_thread_regcache (ptid);
  struct gdbarch *gdbarch = get_regcache_arch (regcache);
  td_event_msg_t msg;
  td_thrinfo_t ti;
  td_err_e err;
  CORE_ADDR stop_pc;
  int loop = 0;

  /* Bail out early if we're not at a thread event breakpoint.  */
  stop_pc = regcache_read_pc (regcache)
	    - gdbarch_decr_pc_after_break (gdbarch);
  if (stop_pc != td_create_bp_addr && stop_pc != td_death_bp_addr)
    return;
  loop = 1;

  do
    {
      err = td_ta_event_getmsg_p (thread_agent, &msg);
      if (err != TD_OK)
        {
	  if (err == TD_NOMSG)
	    return;
          error ("Cannot get thread event message: %s",
		 thread_db_err_str (err));
        }
      err = td_thr_get_info_p ((void *)(uintptr_t)msg.th_p, &ti);
      if (err != TD_OK)
        error ("Cannot get thread info: %s", thread_db_err_str (err));
      ptid = BUILD_THREAD (ti.ti_tid, GET_PID (ptid));
      switch (msg.event)
        {
        case TD_CREATE:
          /* We may already know about this thread, for instance when the
             user has issued the `info threads' command before the SIGTRAP
             for hitting the thread creation breakpoint was reported.  */
          attach_thread (ptid, (void *)(uintptr_t)msg.th_p, &ti, 1);
          break;
       case TD_DEATH:
         if (!in_thread_list (ptid))
           error ("Spurious thread death event.");
         detach_thread (ptid, 1);
         break;
       default:
          error ("Spurious thread event.");
       }
    }
  while (loop);
}
Пример #7
0
static void
get_current_thread ()
{
  td_thrhandle_t th;
  td_thrinfo_t ti;
  long lwp;
  ptid_t tmp, ptid;

  lwp = get_current_lwp (proc_handle.pid);
  tmp = BUILD_LWP (lwp, proc_handle.pid);
  ptid = thread_from_lwp (tmp, &th, &ti);
  if (!in_thread_list (ptid))
    {
      attach_thread (ptid, &th, &ti, 1);
    }
  inferior_ptid = ptid;
}
Пример #8
0
static int
sol_find_new_threads_callback (const td_thrhandle_t *th, void *ignored)
{
  td_err_e retval;
  td_thrinfo_t ti;
  ptid_t ptid;

  if ((retval = p_td_thr_get_info (th, &ti)) != TD_OK)
    {
      return -1;
    }
  ptid = BUILD_THREAD (ti.ti_tid, PIDGET (inferior_ptid));
  if (!in_thread_list (ptid))
    add_thread (ptid);

  return 0;
}
Пример #9
0
static ptid_t
fbsd_thread_wait (struct target_ops *ops,
		  ptid_t ptid, struct target_waitstatus *ourstatus, int options)
{
  struct target_ops *beneath = find_target_beneath (ops);
  ptid_t ret;
  long lwp;
  CORE_ADDR stop_pc;
  td_thrhandle_t th;
  td_thrinfo_t ti;

  ret = beneath->to_wait (beneath, ptid, ourstatus, options);
  if (GET_PID(ret) >= 0 && ourstatus->kind == TARGET_WAITKIND_STOPPED)
    {
      lwp = get_current_lwp (GET_PID(ret));
      ret = thread_from_lwp (BUILD_LWP(lwp, GET_PID(ret)),
         &th, &ti);
      if (!in_thread_list(ret)) {
        /*
         * We have to enable event reporting for initial thread
         * which was not mapped before.
	 */
        attach_thread(ret, &th, &ti, 1);
      }
      if (ourstatus->value.sig == TARGET_SIGNAL_TRAP)
        check_event(ret);
      /* this is a hack, if an event won't cause gdb to stop, for example,
         SIGALRM, gdb resumes the process immediatly without setting
         inferior_ptid to the new thread returned here, this is a bug
         because inferior_ptid may already not exist there, and passing
         a non-existing thread to fbsd_thread_resume causes error. However,
         if the exiting thread is the currently selected thread,
         then that is handled later in handle_inferior_event(), and we must
         not delete the currently selected thread. 
      */
      if (!fbsd_thread_alive (ops, inferior_ptid) && !ptid_equal(inferior_ptid, ret))
        {
          delete_thread (inferior_ptid);
          inferior_ptid = ret;
        }
    }

  return (ret);
}
Пример #10
0
static void
sol_thread_create_inferior (char *exec_file, char *allargs, char **env)
{
  procfs_ops.to_create_inferior (exec_file, allargs, env);

  if (sol_thread_active && !ptid_equal (inferior_ptid, null_ptid))
    {
      main_ph.ptid = inferior_ptid;	/* Save for xfer_memory */

      push_target (&sol_thread_ops);

      inferior_ptid = lwp_to_thread (inferior_ptid);
      if (PIDGET (inferior_ptid) == -1)
	inferior_ptid = main_ph.ptid;

      if (!in_thread_list (inferior_ptid))
	add_thread (inferior_ptid);
    }
}
Пример #11
0
static ptid_t
nbsd_thread_wait (struct target_ops *ops, ptid_t ptid,
  struct target_waitstatus *ourstatus, int options)
{
  ptid_t rtnval;
  struct target_ops *beneath = find_target_beneath (ops);

  rtnval = beneath->to_wait (beneath, ptid, ourstatus, options);

  nbsd_thread_unsuspend();

  if (nbsd_thread_active && (ourstatus->kind != TARGET_WAITKIND_EXITED))
    {
      rtnval = find_active_thread ();
      if (ptid_equal (rtnval, minus_one_ptid))
	error ("No active thread!\n");
      if (!in_thread_list (rtnval))
	add_thread (rtnval);
    }

  return rtnval;
}
Пример #12
0
static ptid_t
fbsd_thread_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
{
  ptid_t ret;
  long lwp;
  CORE_ADDR stop_pc;
  td_thrhandle_t th;
  td_thrinfo_t ti;

  ret = child_ops.to_wait (ptid, ourstatus);
  if (GET_PID(ret) >= 0 && ourstatus->kind == TARGET_WAITKIND_STOPPED)
    {
      lwp = get_current_lwp (GET_PID(ret));
      ret = thread_from_lwp (BUILD_LWP(lwp, GET_PID(ret)),
         &th, &ti);
      if (!in_thread_list(ret)) {
        /*
         * We have to enable event reporting for initial thread
         * which was not mapped before.
	 */
        attach_thread(ret, &th, &ti, 1);
      }
      if (ourstatus->value.sig == TARGET_SIGNAL_TRAP)
        check_event(ret);
      /* this is a hack, if an event won't cause gdb to stop, for example,
         SIGARLM, gdb resumes the process immediatly without setting
         inferior_ptid to the new thread returned here, this is a bug
         because inferior_ptid may already not exist there, and passing
         a none existing thread to fbsd_thread_resume causes error. */
      if (!fbsd_thread_alive (inferior_ptid))
        {
          delete_thread (inferior_ptid);
          inferior_ptid = ret;
        }
    }

  return (ret);
}
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;
    }
}
Пример #14
0
static ptid_t
obsd_wait (struct target_ops *ops,
	   ptid_t ptid, struct target_waitstatus *ourstatus, int options)
{
  pid_t pid;
  int status, save_errno;

  do
    {
      set_sigint_trap ();

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

      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 = GDB_SIGNAL_UNKNOWN;
	  return inferior_ptid;
	}

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

  ptid = pid_to_ptid (pid);

  if (WIFSTOPPED (status))
    {
      ptrace_state_t pe;
      pid_t fpid;

      if (ptrace (PT_GET_PROCESS_STATE, pid, (caddr_t)&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 = pid_to_ptid (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,
		      (caddr_t)&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 = pid_to_ptid (pe.pe_other_pid);
	      return pid_to_ptid (fpid);
	    }

	  return pid_to_ptid (pid);
	}

      ptid = ptid_build (pid, pe.pe_tid, 0);
      if (!in_thread_list (ptid))
	{
	  if (ptid_get_lwp (inferior_ptid) == 0)
	    thread_change_ptid (inferior_ptid, ptid);
	  else
	    add_thread (ptid);
	}
    }

  store_waitstatus (ourstatus, status);
  return ptid;
}