Exemple #1
0
static td_err_e
enable_thread_event (int event, CORE_ADDR *bp)
{
  td_notify_t notify;
  td_err_e err;
  struct thread_db_info *info;

  info = get_thread_db_info (GET_PID (inferior_ptid));

  /* Access an lwp we know is stopped.  */
  info->proc_handle.ptid = inferior_ptid;

  /* Get the breakpoint address for thread EVENT.  */
  err = info->td_ta_event_addr_p (info->thread_agent, event, &notify);
  if (err != TD_OK)
    return err;

  /* Set up the breakpoint.  */
  gdb_assert (exec_bfd);
  (*bp) = (gdbarch_convert_from_func_ptr_addr
	   (target_gdbarch,
	    /* Do proper sign extension for the target.  */
	    (bfd_get_sign_extend_vma (exec_bfd) > 0
	     ? (CORE_ADDR) (intptr_t) notify.u.bptaddr
	     : (CORE_ADDR) (uintptr_t) notify.u.bptaddr),
	    &current_target));
  create_thread_event_breakpoint (target_gdbarch, *bp);

  return TD_OK;
}
Exemple #2
0
/* Attach to lwp PTID, doing whatever else is required to have this
   LWP under the debugger's control --- e.g., enabling event
   reporting.  Returns true on success.  */
int
thread_db_attach_lwp (ptid_t ptid)
{
  td_thrhandle_t th;
  td_thrinfo_t ti;
  td_err_e err;
  struct thread_db_info *info;

  info = get_thread_db_info (GET_PID (ptid));

  if (info == NULL)
    return 0;

  /* This ptid comes from linux-nat.c, which should always fill in the
     LWP.  */
  gdb_assert (GET_LWP (ptid) != 0);

  /* Access an lwp we know is stopped.  */
  info->proc_handle.ptid = ptid;

  /* If we have only looked at the first thread before libpthread was
     initialized, we may not know its thread ID yet.  Make sure we do
     before we add another thread to the list.  */
  if (!have_threads (ptid))
    thread_db_find_new_threads_1 (ptid);

  err = info->td_ta_map_lwp2thr_p (info->thread_agent, GET_LWP (ptid), &th);
  if (err != TD_OK)
    /* Cannot find user-level thread.  */
    return 0;

  err = info->td_thr_get_info_p (&th, &ti);
  if (err != TD_OK)
    {
      warning (_("Cannot get thread info: %s"), thread_db_err_str (err));
      return 0;
    }

  attach_thread (ptid, &th, &ti);
  return 1;
}
Exemple #3
0
static ptid_t
thread_from_lwp (ptid_t ptid)
{
  td_thrhandle_t th;
  td_err_e err;
  ptid_t thread_ptid;
  struct thread_db_info *info;
  struct thread_get_info_inout io = {0};

  /* This ptid comes from linux-nat.c, which should always fill in the
     LWP.  */
  gdb_assert (GET_LWP (ptid) != 0);

  info = get_thread_db_info (GET_PID (ptid));

  /* Access an lwp we know is stopped.  */
  info->proc_handle.ptid = ptid;
  err = info->td_ta_map_lwp2thr_p (info->thread_agent, GET_LWP (ptid), &th);
  if (err != TD_OK)
    error (_("Cannot find user-level thread for LWP %ld: %s"),
	   GET_LWP (ptid), thread_db_err_str (err));

  /* Fetch the thread info.  If we get back TD_THR_ZOMBIE, then the
     event thread has already died.  If another gdb interface has called
     thread_alive() previously, the thread won't be found on the thread list
     anymore.  In that case, we don't want to process this ptid anymore
     to avoid the possibility of later treating it as a newly
     discovered thread id that we should add to the list.  Thus,
     we return a -1 ptid which is also how the thread list marks a
     dead thread.  */
  io.thread_db_info = info;
  io.thread_info = NULL;
  if (thread_get_info_callback (&th, &io) == TD_THR_ZOMBIE
      && io.thread_info == NULL)
    return minus_one_ptid;

  gdb_assert (ptid_get_tid (ptid) == 0);
  return ptid;
}
Exemple #4
0
static void
enable_thread_event_reporting (void)
{
  td_thr_events_t events;
  td_err_e err;
#ifdef HAVE_GNU_LIBC_VERSION_H
  const char *libc_version;
  int libc_major, libc_minor;
#endif
  struct thread_db_info *info;

  info = get_thread_db_info (GET_PID (inferior_ptid));

  /* We cannot use the thread event reporting facility if these
     functions aren't available.  */
  if (info->td_ta_event_addr_p == NULL
      || info->td_ta_set_event_p == NULL
      || info->td_ta_event_getmsg_p == NULL
      || info->td_thr_event_enable_p == NULL)
    return;

  /* Set the process wide mask saying which events we're interested in.  */
  td_event_emptyset (&events);
  td_event_addset (&events, TD_CREATE);

#ifdef HAVE_GNU_LIBC_VERSION_H
  /* The event reporting facility is broken for TD_DEATH events in
     glibc 2.1.3, so don't enable it if we have glibc but a lower
     version.  */
  libc_version = gnu_get_libc_version ();
  if (sscanf (libc_version, "%d.%d", &libc_major, &libc_minor) == 2
      && (libc_major > 2 || (libc_major == 2 && libc_minor > 1)))
#endif
    td_event_addset (&events, TD_DEATH);

  err = info->td_ta_set_event_p (info->thread_agent, &events);
  if (err != TD_OK)
    {
      warning (_("Unable to set global thread event mask: %s"),
	       thread_db_err_str (err));
      return;
    }

  /* Delete previous thread event breakpoints, if any.  */
  remove_thread_event_breakpoints ();
  info->td_create_bp_addr = 0;
  info->td_death_bp_addr = 0;

  /* Set up the thread creation event.  */
  err = enable_thread_event (TD_CREATE, &info->td_create_bp_addr);
  if (err != TD_OK)
    {
      warning (_("Unable to get location for thread creation breakpoint: %s"),
	       thread_db_err_str (err));
      return;
    }

  /* Set up the thread death event.  */
  err = enable_thread_event (TD_DEATH, &info->td_death_bp_addr);
  if (err != TD_OK)
    {
      warning (_("Unable to get location for thread death breakpoint: %s"),
	       thread_db_err_str (err));
      return;
    }
}