Exemplo n.º 1
0
static int
find_one_thread (ptid_t ptid)
{
  td_thrhandle_t th;
  td_thrinfo_t ti;
  td_err_e err;
  struct thread_info *inferior;
  struct lwp_info *lwp;
  struct thread_db *thread_db = current_process ()->priv->thread_db;
  int lwpid = ptid_get_lwp (ptid);

  inferior = (struct thread_info *) find_inferior_id (&all_threads, ptid);
  lwp = get_thread_lwp (inferior);
  if (lwp->thread_known)
    return 1;

  /* Get information about this thread.  */
  err = thread_db->td_ta_map_lwp2thr_p (thread_db->thread_agent, lwpid, &th);
  if (err != TD_OK)
    error ("Cannot get thread handle for LWP %d: %s",
	   lwpid, thread_db_err_str (err));

  err = thread_db->td_thr_get_info_p (&th, &ti);
  if (err != TD_OK)
    error ("Cannot get thread info for LWP %d: %s",
	   lwpid, thread_db_err_str (err));

  if (debug_threads)
    debug_printf ("Found thread %ld (LWP %d)\n",
		  ti.ti_tid, ti.ti_lid);

  if (lwpid != ti.ti_lid)
    {
      warning ("PID mismatch!  Expected %ld, got %ld",
	       (long) lwpid, (long) ti.ti_lid);
      return 0;
    }

  if (thread_db_use_events)
    {
      err = thread_db->td_thr_event_enable_p (&th, 1);
      if (err != TD_OK)
	error ("Cannot enable thread event reporting for %d: %s",
	       ti.ti_lid, thread_db_err_str (err));
    }

  /* If the new thread ID is zero, a final thread ID will be available
     later.  Do not enable thread debugging yet.  */
  if (ti.ti_tid == 0)
    return 0;

  lwp->thread_known = 1;
  lwp->th = th;

  return 1;
}
Exemplo n.º 2
0
static void
check_for_thread_db (void)
{
  td_err_e err;

  if (td_ta_new_p == NULL)
    return;

  /* Don't try to attach to a dead target if there is no core file. */
  if (!target_has_execution && core_bfd == NULL)
    return;

  /* Nothing to do.  The thread library was already detected and the
     target vector was already activated.  */
  if (fbsd_thread_active)
    return;

  /* Now, initialize libthread_db.  This needs to be done after the
     shared libraries are located because it needs information from
     the user's thread library.  */

  err = td_init_p ();
  if (err != TD_OK)
    {
      warning ("Cannot initialize libthread_db: %s", thread_db_err_str (err));
      return;
    }

  /* Initialize the structure that identifies the child process.  Note
     that at this point there is no guarantee that we actually have a
     child process.  */
  proc_handle.pid = GET_PID (inferior_ptid);
  
  /* Now attempt to open a connection to the thread library.  */
  err = td_ta_new_p (&proc_handle, &thread_agent);
  switch (err)
    {
    case TD_NOLIBTHREAD:
      /* No thread library was detected.  */
      break;

    case TD_OK:
      /* The thread library was detected.  Activate the thread_db target.  */
      push_target(&fbsd_thread_ops);
      fbsd_thread_present = 1;
      fbsd_thread_activate();
	  
      break;

    default:
      warning ("Cannot initialize thread debugging library: %s",
               thread_db_err_str (err));
      break;
    }
}
Exemplo n.º 3
0
CORE_ADDR
fbsd_thread_get_local_address(ptid_t ptid, struct objfile *objfile,
                              CORE_ADDR offset)
{
  td_thrhandle_t th;
  void *address;
  CORE_ADDR lm;
  void *lm2;
  int ret, is_library = (objfile->flags & OBJF_SHARED);

  if (IS_THREAD (ptid))
    {
      if (!td_thr_tls_get_addr_p)
        error ("Cannot find thread-local interface in thread_db library.");

      /* Get the address of the link map for this objfile. */
      lm = svr4_fetch_objfile_link_map (objfile);

      /* Couldn't find link map. Bail out. */
      if (!lm)
        {
          if (is_library)
            error ("Cannot find shared library `%s' link_map in dynamic"
                   " linker's module list", objfile->name);
          else
            error ("Cannot find executable file `%s' link_map in dynamic"
                   " linker's module list", objfile->name);
        }

      ret = td_ta_map_id2thr_p (thread_agent, GET_THREAD(ptid), &th);

      /* get the address of the variable. */
      store_typed_address(&lm2, builtin_type_void_data_ptr, lm);
      ret = td_thr_tls_get_addr_p (&th, lm2, offset, &address);

      if (ret != TD_OK)
        {
          if (is_library)
            error ("Cannot find thread-local storage for thread %ld, "
                   "shared library %s:\n%s",
                   (long) GET_THREAD (ptid),
                   objfile->name, thread_db_err_str (ret));
          else
            error ("Cannot find thread-local storage for thread %ld, "
                   "executable file %s:\n%s",
                   (long) GET_THREAD (ptid),
                   objfile->name, thread_db_err_str (ret));
        }

      /* Cast assuming host == target. */
      return extract_typed_address(&address, builtin_type_void_data_ptr);
    }
  return (0);
}
Exemplo n.º 4
0
static int
thread_db_enable_reporting ()
{
  td_thr_events_t events;
  td_notify_t notify;
  td_err_e err;

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

#if 0
  /* This is reported to be broken in glibc 2.1.3.  A different approach
     will be necessary to support that.  */
  td_event_addset (&events, TD_DEATH);
#endif

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

  /* Get address for thread creation breakpoint.  */
  err = td_ta_event_addr (thread_agent, TD_CREATE, &notify);
  if (err != TD_OK)
    {
      warning ("Unable to get location for thread creation breakpoint: %s",
	       thread_db_err_str (err));
      return 0;
    }
  set_breakpoint_at ((CORE_ADDR) (unsigned long) notify.u.bptaddr,
		     thread_db_create_event);

#if 0
  /* Don't concern ourselves with reported thread deaths, only
     with actual thread deaths (via wait).  */

  /* Get address for thread death breakpoint.  */
  err = td_ta_event_addr (thread_agent, TD_DEATH, &notify);
  if (err != TD_OK)
    {
      warning ("Unable to get location for thread death breakpoint: %s",
	       thread_db_err_str (err));
      return;
    }
  set_breakpoint_at ((CORE_ADDR) (unsigned long) notify.u.bptaddr,
		     thread_db_death_event);
#endif

  return 1;
}
Exemplo n.º 5
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);
}
Exemplo n.º 6
0
static void
fbsd_thread_fetch_registers (struct target_ops *ops,
			     struct regcache *regcache, int regnum)
{
  prgregset_t gregset;
  prfpregset_t fpregset;
  td_thrhandle_t th;
  td_err_e err;
#ifdef PT_GETXMMREGS
  char xmmregs[512];
#endif

  if (!IS_THREAD (inferior_ptid))
    {
      fbsd_lwp_fetch_registers (ops, regcache, regnum);
      return;
    }

  err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (inferior_ptid), &th);
  if (err != TD_OK)
    error ("Cannot find thread %d: Thread ID=%ld, %s",
           pid_to_thread_id (inferior_ptid),           
           GET_THREAD (inferior_ptid), thread_db_err_str (err));

  err = td_thr_getgregs_p (&th, gregset);
  if (err != TD_OK)
    error ("Cannot fetch general-purpose registers for thread %d: Thread ID=%ld, %s",
           pid_to_thread_id (inferior_ptid),
           GET_THREAD (inferior_ptid), thread_db_err_str (err));
#ifdef PT_GETXMMREGS
  err = td_thr_getxmmregs_p (&th, xmmregs);
  if (err == TD_OK)
    {
      i387_supply_fxsave (regcache, -1, xmmregs);
    }
  else
    {
#endif
      err = td_thr_getfpregs_p (&th, &fpregset);
      if (err != TD_OK)
	error ("Cannot get floating-point registers for thread %d: Thread ID=%ld, %s",
	       pid_to_thread_id (inferior_ptid),
	       GET_THREAD (inferior_ptid), thread_db_err_str (err));
      supply_fpregset (regcache, &fpregset);
#ifdef PT_GETXMMREGS
    }
#endif

  supply_gregset (regcache, gregset);
}
Exemplo n.º 7
0
static void
enable_thread_event_reporting (void)
{
  td_thr_events_t events;
  td_notify_t notify;
  td_err_e err;

  /* We cannot use the thread event reporting facility if these
     functions aren't available.  */
  if (td_ta_event_addr_p == NULL || td_ta_set_event_p == NULL
      || td_ta_event_getmsg_p == NULL || 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);
  td_event_addset (&events, TD_DEATH);

  err = td_ta_set_event_p (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 ();
  td_create_bp_addr = 0;
  td_death_bp_addr = 0;

  /* Set up the thread creation event.  */
  err = enable_thread_event (thread_agent, TD_CREATE, &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 (thread_agent, TD_DEATH, &td_death_bp_addr);
  if (err != TD_OK)
    {
      warning ("Unable to get location for thread death breakpoint: %s",
	       thread_db_err_str (err));
      return;
    }
}
Exemplo n.º 8
0
static int
thread_db_create_event (CORE_ADDR where)
{
  td_event_msg_t msg;
  td_err_e err;
  struct lwp_info *lwp;
  struct thread_db *thread_db = current_process ()->priv->thread_db;

  gdb_assert (thread_db->td_ta_event_getmsg_p != NULL);

  if (debug_threads)
    debug_printf ("Thread creation event.\n");

  /* FIXME: This assumes we don't get another event.
     In the LinuxThreads implementation, this is safe,
     because all events come from the manager thread
     (except for its own creation, of course).  */
  err = thread_db->td_ta_event_getmsg_p (thread_db->thread_agent, &msg);
  if (err != TD_OK)
    fprintf (stderr, "thread getmsg err: %s\n",
	     thread_db_err_str (err));

  /* If we do not know about the main thread yet, this would be a good time to
     find it.  We need to do this to pick up the main thread before any newly
     created threads.  */
  lwp = get_thread_lwp (current_thread);
  if (lwp->thread_known == 0)
    find_one_thread (current_thread->entry.id);

  /* msg.event == TD_EVENT_CREATE */

  find_new_threads_callback (msg.th_p, NULL);

  return 0;
}
Exemplo n.º 9
0
CORE_ADDR
fbsd_thread_get_local_address(struct target_ops *ops,
			      ptid_t ptid,
			      CORE_ADDR lm,
                              CORE_ADDR offset)
{
  td_thrhandle_t th;
  void *address;
  int ret;

  if (IS_THREAD (ptid))
    {
      if (!td_thr_tls_get_addr_p)
        error ("Cannot find thread-local interface in thread_db library.");

      ret = td_ta_map_id2thr_p (thread_agent, GET_THREAD(ptid), &th);

      /* get the address of the variable. */
      ret = td_thr_tls_get_addr_p (&th, (void *)lm, offset, &address);

      if (ret != TD_OK)
        {
            error ("Cannot find thread-local storage for thread %ld\n%s",
                   (long) GET_THREAD (ptid), thread_db_err_str (ret));
        }

      /* Cast assuming host == target. */
      return extract_data_ptr (&address);
    }
  return (0);
}
Exemplo n.º 10
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));
}
Exemplo n.º 11
0
static void
thread_db_create_event (CORE_ADDR where)
{
  td_event_msg_t msg;
  td_err_e err;
  struct inferior_linux_data *tdata;

  if (debug_threads)
    fprintf (stderr, "Thread creation event.\n");

  tdata = inferior_target_data (current_inferior);

  /* FIXME: This assumes we don't get another event.
     In the LinuxThreads implementation, this is safe,
     because all events come from the manager thread
     (except for its own creation, of course).  */
  err = td_ta_event_getmsg (thread_agent, &msg);
  if (err != TD_OK)
    fprintf (stderr, "thread getmsg err: %s\n",
	     thread_db_err_str (err));

  /* msg.event == TD_EVENT_CREATE */

  find_new_threads_callback (msg.th_p, NULL);
}
Exemplo n.º 12
0
static int
resume_thread_callback (const td_thrhandle_t *th_p, void *data)
{
  int err = td_thr_dbresume_p (th_p);
  if (err != 0)
	fprintf_filtered(gdb_stderr, "%s %s\n", __func__, thread_db_err_str (err));
  return (err);
}
Exemplo n.º 13
0
static char *
fbsd_thread_pid_to_str (ptid_t ptid)
{
  static char buf[64 + MAXCOMLEN];

  if (IS_THREAD (ptid))
    {
      td_thrhandle_t th;
      td_thrinfo_t ti;
      td_err_e err;

      err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (ptid), &th);
      if (err != TD_OK)
        error ("Cannot find thread, Thread ID=%ld, %s",
                GET_THREAD (ptid), thread_db_err_str (err));

      err = td_thr_get_info_p (&th, &ti);
      if (err != TD_OK)
        error ("Cannot get thread info, Thread ID=%ld, %s",
               GET_THREAD (ptid), thread_db_err_str (err));

      if (ti.ti_lid != 0)
        {
          snprintf (buf, sizeof (buf), "Thread %llx (LWP %d/%s)",
                    (unsigned long long)th.th_thread, ti.ti_lid,
                    fbsd_thread_get_name (ti.ti_lid));
        }
      else
        {
          snprintf (buf, sizeof (buf), "Thread %llx (%s)",
		    (unsigned long long)th.th_thread,
		    thread_db_state_str (ti.ti_state));
        }

      return buf;
    }
  else if (IS_LWP (ptid))
    {
      snprintf (buf, sizeof (buf), "LWP %d", (int) GET_LWP (ptid));
      return buf;
    }
  return normal_pid_to_str (ptid);
}
Exemplo n.º 14
0
static int
thread_db_load (void)
{
  void *handle;
  td_err_e err;

  handle = dlopen (LIBTHREAD_DB_SO, RTLD_NOW);
  if (handle == NULL)
      return 0;

#define resolve(X)			\
 if (!(X##_p = dlsym (handle, #X)))	\
   return 0;

  resolve(td_init);
  resolve(td_ta_new);
  resolve(td_ta_delete);
  resolve(td_ta_map_id2thr);
  resolve(td_ta_map_lwp2thr);
  resolve(td_ta_thr_iter);
  resolve(td_thr_get_info);
#ifdef PT_GETXMMREGS
  resolve(td_thr_getxmmregs);
#endif
  resolve(td_thr_getfpregs);
  resolve(td_thr_getgregs);
#ifdef PT_GETXMMREGS
  resolve(td_thr_setxmmregs);
#endif
  resolve(td_thr_setfpregs);
  resolve(td_thr_setgregs);
  resolve(td_thr_sstep);
  resolve(td_ta_tsd_iter);
  resolve(td_thr_dbsuspend);
  resolve(td_thr_dbresume);
  resolve(td_thr_tls_get_addr);

  /* Initialize the library.  */
  err = td_init_p ();
  if (err != TD_OK)
    {
      warning ("Cannot initialize libthread_db: %s", thread_db_err_str (err));
      return 0;
    }

  /* These are not essential.  */
  td_ta_event_addr_p = dlsym (handle, "td_ta_event_addr");
  td_ta_set_event_p = dlsym (handle, "td_ta_set_event");
  td_ta_event_getmsg_p = dlsym (handle, "td_ta_event_getmsg");
  td_thr_event_enable_p = dlsym (handle, "td_thr_event_enable");
  td_thr_tls_get_addr_p = dlsym (handle, "td_thr_tls_get_addr");
  
  return 1;
}
Exemplo n.º 15
0
static void
maybe_attach_thread (const td_thrhandle_t *th_p, td_thrinfo_t *ti_p)
{
  td_err_e err;
  struct thread_info *inferior;
  struct process_info *process;

  /* If we are attaching to our first thread, things are a little
     different.  */
  if (all_threads.head == all_threads.tail)
    {
      inferior = (struct thread_info *) all_threads.head;
      process = get_thread_process (inferior);
      if (process->thread_known == 0)
	{
	  /* Switch to indexing the threads list by TID.  */
	  change_inferior_id (&all_threads, ti_p->ti_tid);
	  goto found;
	}
    }
  
  inferior = (struct thread_info *) find_inferior_id (&all_threads,
						      ti_p->ti_tid);
  if (inferior != NULL)
    return;

  if (debug_threads)
    fprintf (stderr, "Attaching to thread %ld (LWP %d)\n",
	     ti_p->ti_tid, ti_p->ti_lid);
  linux_attach_lwp (ti_p->ti_lid, ti_p->ti_tid);
  inferior = (struct thread_info *) find_inferior_id (&all_threads,
						      ti_p->ti_tid);
  if (inferior == NULL)
    {
      warning ("Could not attach to thread %ld (LWP %d)\n",
	       ti_p->ti_tid, ti_p->ti_lid);
      return;
    }

  process = inferior_target_data (inferior);

found:
  new_thread_notify (ti_p->ti_tid);

  process->tid = ti_p->ti_tid;
  process->lwpid = ti_p->ti_lid;

  process->thread_known = 1;
  process->th = *th_p;
  err = td_thr_event_enable (th_p, 1);
  if (err != TD_OK)
    error ("Cannot enable thread event reporting for %d: %s",
           ti_p->ti_lid, thread_db_err_str (err));
}
Exemplo n.º 16
0
static int
thread_db_enable_reporting (void)
{
  td_thr_events_t events;
  td_notify_t notify;
  td_err_e err;
  struct thread_db *thread_db = current_process ()->priv->thread_db;

  if (thread_db->td_ta_set_event_p == NULL
      || thread_db->td_ta_event_addr_p == NULL
      || thread_db->td_ta_event_getmsg_p == NULL)
    /* This libthread_db is missing required support.  */
    return 0;

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

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

  /* Get address for thread creation breakpoint.  */
  err = thread_db->td_ta_event_addr_p (thread_db->thread_agent, TD_CREATE,
				       &notify);
  if (err != TD_OK)
    {
      warning ("Unable to get location for thread creation breakpoint: %s",
	       thread_db_err_str (err));
      return 0;
    }
  thread_db->td_create_bp
    = set_breakpoint_at ((CORE_ADDR) (unsigned long) notify.u.bptaddr,
			 thread_db_create_event);

  return 1;
}
Exemplo n.º 17
0
static void
fbsd_thread_find_new_threads (struct target_ops *ops)
{
  td_err_e err;

  /* Iterate over all user-space threads to discover new threads. */
  err = td_ta_thr_iter_p (thread_agent, find_new_threads_callback, NULL,
          TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
          TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
  if (err != TD_OK)
    error ("Cannot find new threads: %s", thread_db_err_str (err));
}
Exemplo n.º 18
0
static int
find_new_threads_callback (const td_thrhandle_t *th_p, void *data)
{
  td_thrinfo_t ti;
  td_err_e err;

  err = td_thr_get_info (th_p, &ti);
  if (err != TD_OK)
    error ("Cannot get thread info: %s", thread_db_err_str (err));

  /* Check for zombies.  */
  if (ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE)
    return 0;

  maybe_attach_thread (th_p, &ti);

  return 0;
}
Exemplo n.º 19
0
int
thread_db_init ()
{
  int err;

  /* FIXME drow/2004-10-16: This is the "overall process ID", which
     GNU/Linux calls tgid, "thread group ID".  When we support
     attaching to threads, the original thread may not be the correct
     thread.  We would have to get the process ID from /proc for NPTL.
     For LinuxThreads we could do something similar: follow the chain
     of parent processes until we find the highest one we're attached
     to, and use its tgid.

     This isn't the only place in gdbserver that assumes that the first
     process in the list is the thread group leader.  */
  proc_handle.pid = ((struct inferior_list_entry *)current_inferior)->id;

  /* Allow new symbol lookups.  */
  all_symbols_looked_up = 0;

  err = td_ta_new (&proc_handle, &thread_agent);
  switch (err)
    {
    case TD_NOLIBTHREAD:
      /* No thread library was detected.  */
      return 0;

    case TD_OK:
      /* The thread library was detected.  */

      if (thread_db_enable_reporting () == 0)
	return 0;
      thread_db_find_new_threads ();
      thread_db_look_up_symbols ();
      all_symbols_looked_up = 1;
      return 1;

    default:
      warning ("error initializing thread_db library: %s",
	       thread_db_err_str (err));
    }

  return 0;
}
Exemplo n.º 20
0
static int
find_new_threads_callback (const td_thrhandle_t *th_p, void *data)
{
  td_thrinfo_t ti;
  td_err_e err;
  ptid_t ptid;

  err = td_thr_get_info_p (th_p, &ti);
  if (err != TD_OK)
    error ("Cannot get thread info: %s", thread_db_err_str (err));

  /* Ignore zombie */
  if (ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE)
    return 0;

  ptid = BUILD_THREAD (ti.ti_tid, proc_handle.pid);
  attach_thread (ptid, th_p, &ti, 1);
  return 0;
}
Exemplo n.º 21
0
static int
thread_db_load_search (void)
{
  td_err_e err;
  struct thread_db *tdb;
  struct process_info *proc = current_process ();

  gdb_assert (proc->priv->thread_db == NULL);

  tdb = XCNEW (struct thread_db);
  proc->priv->thread_db = tdb;

  tdb->td_ta_new_p = &td_ta_new;

  /* Attempt to open a connection to the thread library.  */
  err = tdb->td_ta_new_p (&tdb->proc_handle, &tdb->thread_agent);
  if (err != TD_OK)
    {
      if (debug_threads)
	debug_printf ("td_ta_new(): %s\n", thread_db_err_str (err));
      free (tdb);
      proc->priv->thread_db = NULL;
      return 0;
    }

  tdb->td_ta_map_lwp2thr_p = &td_ta_map_lwp2thr;
  tdb->td_thr_get_info_p = &td_thr_get_info;
  tdb->td_ta_thr_iter_p = &td_ta_thr_iter;
  tdb->td_symbol_list_p = &td_symbol_list;

  /* This is required only when thread_db_use_events is on.  */
  tdb->td_thr_event_enable_p = &td_thr_event_enable;

  /* These are not essential.  */
  tdb->td_ta_event_addr_p = &td_ta_event_addr;
  tdb->td_ta_set_event_p = &td_ta_set_event;
  tdb->td_ta_event_getmsg_p = &td_ta_event_getmsg;
  tdb->td_thr_tls_get_addr_p = &td_thr_tls_get_addr;
  tdb->td_thr_tlsbase_p = &td_thr_tlsbase;

  return 1;
}
Exemplo n.º 22
0
static void
thread_db_find_new_threads (void)
{
  td_err_e err;
  ptid_t ptid = current_ptid;
  struct thread_db *thread_db = current_process ()->priv->thread_db;
  int loop, iteration;

  /* This function is only called when we first initialize thread_db.
     First locate the initial thread.  If it is not ready for
     debugging yet, then stop.  */
  if (find_one_thread (ptid) == 0)
    return;

  /* Require 4 successive iterations which do not find any new threads.
     The 4 is a heuristic: there is an inherent race here, and I have
     seen that 2 iterations in a row are not always sufficient to
     "capture" all threads.  */
  for (loop = 0, iteration = 0; loop < 4; ++loop, ++iteration)
    {
      int new_thread_count = 0;

      /* Iterate over all user-space threads to discover new threads.  */
      err = thread_db->td_ta_thr_iter_p (thread_db->thread_agent,
					 find_new_threads_callback,
					 &new_thread_count,
					 TD_THR_ANY_STATE,
					 TD_THR_LOWEST_PRIORITY,
					 TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
      if (debug_threads)
	debug_printf ("Found %d threads in iteration %d.\n",
		      new_thread_count, iteration);

      if (new_thread_count != 0)
	{
	  /* Found new threads.  Restart iteration from beginning.  */
	  loop = -1;
	}
    }
  if (err != TD_OK)
    error ("Cannot find new threads: %s", thread_db_err_str (err));
}
Exemplo n.º 23
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;
}
Exemplo n.º 24
0
static void
fbsd_core_open (char *filename, int from_tty)
{
  int err;

  fbsd_thread_core = 1;

  orig_core_ops.to_open (filename, from_tty);

  if (fbsd_thread_present)
    {
      err = td_ta_new_p (&proc_handle, &thread_agent);
      if (err == TD_OK)
        {
          proc_handle.pid = elf_tdata (core_bfd)->core_pid;
          fbsd_thread_activate ();
        }
      else
        error ("fbsd_core_open: td_ta_new: %s", thread_db_err_str (err));
    }
}
Exemplo n.º 25
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;
}
Exemplo n.º 26
0
/* Convert LWP to user-level thread id. */
static ptid_t
thread_from_lwp (ptid_t ptid, td_thrhandle_t *th, td_thrinfo_t *ti)
{
  td_err_e err;
 
  gdb_assert (IS_LWP (ptid));

  if (fbsd_thread_active)
    {
      err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), th);
      if (err == TD_OK)
        {
          err = td_thr_get_info_p (th, ti);
          if (err != TD_OK)
            error ("Cannot get thread info: %s", thread_db_err_str (err));
          return BUILD_THREAD (ti->ti_tid, GET_PID (ptid));
        }
    }

  /* the LWP is not mapped to user thread */  
  return BUILD_LWP (GET_LWP (ptid), GET_PID (ptid));
}
Exemplo n.º 27
0
static int
thread_get_info_callback (const td_thrhandle_t *thp, void *argp)
{
  td_thrinfo_t ti;
  td_err_e err;
  ptid_t thread_ptid;
  struct thread_get_info_inout *inout;
  struct thread_db_info *info;

  inout = argp;
  info = inout->thread_db_info;

  err = info->td_thr_get_info_p (thp, &ti);
  if (err != TD_OK)
    error (_("thread_get_info_callback: cannot get thread info: %s"),
	   thread_db_err_str (err));

  /* Fill the cache.  */
  thread_ptid = ptid_build (info->pid, ti.ti_lid, 0);
  inout->thread_info = find_thread_ptid (thread_ptid);

  /* In the case of a zombie thread, don't continue.  We don't want to
     attach to it thinking it is a new thread.  */
  if (ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE)
    return TD_THR_ZOMBIE;

  if (inout->thread_info == NULL)
    {
      /* New thread.  Attach to it now (why wait?).  */
      if (!have_threads (thread_ptid))
 	thread_db_find_new_threads_1 (thread_ptid);
      else
	attach_thread (thread_ptid, thp, &ti);
      inout->thread_info = find_thread_ptid (thread_ptid);
      gdb_assert (inout->thread_info != NULL);
    }

  return 0;
}
Exemplo n.º 28
0
static int
attach_thread (const td_thrhandle_t *th_p, td_thrinfo_t *ti_p)
{
  struct process_info *proc = current_process ();
  int pid = pid_of (proc);
  ptid_t ptid = ptid_build (pid, ti_p->ti_lid, 0);
  struct lwp_info *lwp;
  int err;

  if (debug_threads)
    debug_printf ("Attaching to thread %ld (LWP %d)\n",
		  ti_p->ti_tid, ti_p->ti_lid);
  err = linux_attach_lwp (ptid);
  if (err != 0)
    {
      warning ("Could not attach to thread %ld (LWP %d): %s\n",
	       ti_p->ti_tid, ti_p->ti_lid,
	       linux_ptrace_attach_fail_reason_string (ptid, err));
      return 0;
    }

  lwp = find_lwp_pid (ptid);
  gdb_assert (lwp != NULL);
  lwp->thread_known = 1;
  lwp->th = *th_p;

  if (thread_db_use_events)
    {
      td_err_e err;
      struct thread_db *thread_db = proc->priv->thread_db;

      err = thread_db->td_thr_event_enable_p (th_p, 1);
      if (err != TD_OK)
	error ("Cannot enable thread event reporting for %d: %s",
	       ti_p->ti_lid, thread_db_err_str (err));
    }

  return 1;
}
Exemplo n.º 29
0
static int
find_new_threads_callback (const td_thrhandle_t *th_p, void *data)
{
  td_thrinfo_t ti;
  td_err_e err;
  struct thread_db *thread_db = current_process ()->priv->thread_db;

  err = thread_db->td_thr_get_info_p (th_p, &ti);
  if (err != TD_OK)
    error ("Cannot get thread info: %s", thread_db_err_str (err));

  if (ti.ti_lid == -1)
    {
      /* A thread with kernel thread ID -1 is either a thread that
	 exited and was joined, or a thread that is being created but
	 hasn't started yet, and that is reusing the tcb/stack of a
	 thread that previously exited and was joined.  (glibc marks
	 terminated and joined threads with kernel thread ID -1.  See
	 glibc PR17707.  */
      if (debug_threads)
	debug_printf ("thread_db: skipping exited and "
		      "joined thread (0x%lx)\n",
		      (unsigned long) ti.ti_tid);
      return 0;
    }

  /* Check for zombies.  */
  if (ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE)
    return 0;

  if (!maybe_attach_thread (th_p, &ti, (int *) data))
    {
      /* Terminate iteration early: we might be looking at stale data in
	 the inferior.  The thread_db_find_new_threads will retry.  */
      return 1;
    }

  return 0;
}
Exemplo n.º 30
0
static void
fbsd_thread_store_registers (int regno)
{
  prgregset_t gregset;
  prfpregset_t fpregset;
  td_thrhandle_t th;
  td_err_e err;
#ifdef PT_GETXMMREGS
  char xmmregs[512];
#endif

  if (!IS_THREAD (inferior_ptid))
    {
      fbsd_lwp_store_registers (regno);
      return;
    }

  err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (inferior_ptid), &th);
  if (err != TD_OK)
    error ("Cannot find thread %d: Thread ID=%ld, %s",
           pid_to_thread_id (inferior_ptid),
           GET_THREAD (inferior_ptid),
           thread_db_err_str (err));

  if (regno != -1)
    {
      char old_value[MAX_REGISTER_SIZE];

      regcache_collect (regno, old_value);
      err = td_thr_getgregs_p (&th, gregset);
      if (err != TD_OK)
        error ("%s: td_thr_getgregs %s", __func__, thread_db_err_str (err));
#ifdef PT_GETXMMREGS
      err = td_thr_getxmmregs_p (&th, xmmregs);
      if (err != TD_OK)
        {
#endif
          err = td_thr_getfpregs_p (&th, &fpregset);
          if (err != TD_OK)
            error ("%s: td_thr_getfpgregs %s", __func__, thread_db_err_str (err));
#ifdef PT_GETXMMREGS
        }
#endif
      supply_register (regno, old_value);
    }

  fill_gregset (gregset, regno);
  err = td_thr_setgregs_p (&th, gregset);
  if (err != TD_OK)
    error ("Cannot store general-purpose registers for thread %d: Thread ID=%d, %s",
           pid_to_thread_id (inferior_ptid), GET_THREAD (inferior_ptid),
           thread_db_err_str (err));

#ifdef PT_GETXMMREGS
  i387_fill_fxsave (xmmregs, regno);
  err = td_thr_setxmmregs_p (&th, xmmregs);
  if (err == TD_OK)
    return;
#endif

  fill_fpregset (&fpregset, regno);
  err = td_thr_setfpregs_p (&th, &fpregset);
  if (err != TD_OK)
    error ("Cannot store floating-point registers for thread %d: Thread ID=%d, %s",
           pid_to_thread_id (inferior_ptid), GET_THREAD (inferior_ptid),
           thread_db_err_str (err));
}