198944Sobrien/* libthread_db assisted debugging support, generic parts.
298944Sobrien
3130803Smarcel   Copyright 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
4130803Smarcel
598944Sobrien   This file is part of GDB.
698944Sobrien
798944Sobrien   This program is free software; you can redistribute it and/or modify
898944Sobrien   it under the terms of the GNU General Public License as published by
998944Sobrien   the Free Software Foundation; either version 2 of the License, or
1098944Sobrien   (at your option) any later version.
1198944Sobrien
1298944Sobrien   This program is distributed in the hope that it will be useful,
1398944Sobrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
1498944Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1598944Sobrien   GNU General Public License for more details.
1698944Sobrien
1798944Sobrien   You should have received a copy of the GNU General Public License
1898944Sobrien   along with this program; if not, write to the Free Software
1998944Sobrien   Foundation, Inc., 59 Temple Place - Suite 330,
2098944Sobrien   Boston, MA 02111-1307, USA.  */
2198944Sobrien
2298944Sobrien#include "defs.h"
2398944Sobrien
2498944Sobrien#include "gdb_assert.h"
2598944Sobrien#include <dlfcn.h>
2698944Sobrien#include "gdb_proc_service.h"
2798944Sobrien#include "gdb_thread_db.h"
2898944Sobrien
2998944Sobrien#include "bfd.h"
3098944Sobrien#include "gdbthread.h"
3198944Sobrien#include "inferior.h"
3298944Sobrien#include "symfile.h"
3398944Sobrien#include "objfiles.h"
3498944Sobrien#include "target.h"
3598944Sobrien#include "regcache.h"
36130803Smarcel#include "solib-svr4.h"
3798944Sobrien
3898944Sobrien#ifndef LIBTHREAD_DB_SO
3998944Sobrien#define LIBTHREAD_DB_SO "libthread_db.so.1"
4098944Sobrien#endif
4198944Sobrien
4298944Sobrien/* If we're running on GNU/Linux, we must explicitly attach to any new
4398944Sobrien   threads.  */
4498944Sobrien
4598944Sobrien/* FIXME: There is certainly some room for improvements:
4698944Sobrien   - Cache LWP ids.
4798944Sobrien   - Bypass libthread_db when fetching or storing registers for
4898944Sobrien   threads bound to a LWP.  */
4998944Sobrien
5098944Sobrien/* This module's target vector.  */
5198944Sobrienstatic struct target_ops thread_db_ops;
5298944Sobrien
5398944Sobrien/* The target vector that we call for things this module can't handle.  */
5498944Sobrienstatic struct target_ops *target_beneath;
5598944Sobrien
5698944Sobrien/* Pointer to the next function on the objfile event chain.  */
57130803Smarcelstatic void (*target_new_objfile_chain) (struct objfile * objfile);
5898944Sobrien
5998944Sobrien/* Non-zero if we're using this module's target vector.  */
6098944Sobrienstatic int using_thread_db;
6198944Sobrien
6298944Sobrien/* Non-zero if we have to keep this module's target vector active
6398944Sobrien   across re-runs.  */
6498944Sobrienstatic int keep_thread_db;
6598944Sobrien
6698944Sobrien/* Non-zero if we have determined the signals used by the threads
6798944Sobrien   library.  */
6898944Sobrienstatic int thread_signals;
6998944Sobrienstatic sigset_t thread_stop_set;
7098944Sobrienstatic sigset_t thread_print_set;
7198944Sobrien
7298944Sobrien/* Structure that identifies the child process for the
7398944Sobrien   <proc_service.h> interface.  */
7498944Sobrienstatic struct ps_prochandle proc_handle;
7598944Sobrien
7698944Sobrien/* Connection to the libthread_db library.  */
7798944Sobrienstatic td_thragent_t *thread_agent;
7898944Sobrien
7998944Sobrien/* Pointers to the libthread_db functions.  */
8098944Sobrien
8198944Sobrienstatic td_err_e (*td_init_p) (void);
8298944Sobrien
83130803Smarcelstatic td_err_e (*td_ta_new_p) (struct ps_prochandle * ps,
84130803Smarcel				td_thragent_t **ta);
8598944Sobrienstatic td_err_e (*td_ta_map_id2thr_p) (const td_thragent_t *ta, thread_t pt,
8698944Sobrien				       td_thrhandle_t *__th);
87130803Smarcelstatic td_err_e (*td_ta_map_lwp2thr_p) (const td_thragent_t *ta,
88130803Smarcel					lwpid_t lwpid, td_thrhandle_t *th);
8998944Sobrienstatic td_err_e (*td_ta_thr_iter_p) (const td_thragent_t *ta,
90130803Smarcel				     td_thr_iter_f *callback, void *cbdata_p,
91130803Smarcel				     td_thr_state_e state, int ti_pri,
92130803Smarcel				     sigset_t *ti_sigmask_p,
9398944Sobrien				     unsigned int ti_user_flags);
9498944Sobrienstatic td_err_e (*td_ta_event_addr_p) (const td_thragent_t *ta,
9598944Sobrien				       td_event_e event, td_notify_t *ptr);
9698944Sobrienstatic td_err_e (*td_ta_set_event_p) (const td_thragent_t *ta,
9798944Sobrien				      td_thr_events_t *event);
9898944Sobrienstatic td_err_e (*td_ta_event_getmsg_p) (const td_thragent_t *ta,
9998944Sobrien					 td_event_msg_t *msg);
10098944Sobrien
10198944Sobrienstatic td_err_e (*td_thr_validate_p) (const td_thrhandle_t *th);
10298944Sobrienstatic td_err_e (*td_thr_get_info_p) (const td_thrhandle_t *th,
10398944Sobrien				      td_thrinfo_t *infop);
10498944Sobrienstatic td_err_e (*td_thr_getfpregs_p) (const td_thrhandle_t *th,
10598944Sobrien				       gdb_prfpregset_t *regset);
10698944Sobrienstatic td_err_e (*td_thr_getgregs_p) (const td_thrhandle_t *th,
10798944Sobrien				      prgregset_t gregs);
10898944Sobrienstatic td_err_e (*td_thr_setfpregs_p) (const td_thrhandle_t *th,
10998944Sobrien				       const gdb_prfpregset_t *fpregs);
11098944Sobrienstatic td_err_e (*td_thr_setgregs_p) (const td_thrhandle_t *th,
11198944Sobrien				      prgregset_t gregs);
112130803Smarcelstatic td_err_e (*td_thr_event_enable_p) (const td_thrhandle_t *th,
113130803Smarcel					  int event);
11498944Sobrien
115130803Smarcelstatic td_err_e (*td_thr_tls_get_addr_p) (const td_thrhandle_t *th,
116130803Smarcel					  void *map_address,
117130803Smarcel					  size_t offset, void **address);
118130803Smarcel
11998944Sobrien/* Location of the thread creation event breakpoint.  The code at this
12098944Sobrien   location in the child process will be called by the pthread library
12198944Sobrien   whenever a new thread is created.  By setting a special breakpoint
12298944Sobrien   at this location, GDB can detect when a new thread is created.  We
12398944Sobrien   obtain this location via the td_ta_event_addr call.  */
12498944Sobrienstatic CORE_ADDR td_create_bp_addr;
12598944Sobrien
12698944Sobrien/* Location of the thread death event breakpoint.  */
12798944Sobrienstatic CORE_ADDR td_death_bp_addr;
12898944Sobrien
12998944Sobrien/* Prototypes for local functions.  */
13098944Sobrienstatic void thread_db_find_new_threads (void);
131130803Smarcelstatic void attach_thread (ptid_t ptid, const td_thrhandle_t *th_p,
132130803Smarcel			   const td_thrinfo_t *ti_p, int verbose);
13398944Sobrien
13498944Sobrien
13598944Sobrien/* Building process ids.  */
13698944Sobrien
13798944Sobrien#define GET_PID(ptid)		ptid_get_pid (ptid)
13898944Sobrien#define GET_LWP(ptid)		ptid_get_lwp (ptid)
13998944Sobrien#define GET_THREAD(ptid)	ptid_get_tid (ptid)
14098944Sobrien
14198944Sobrien#define is_lwp(ptid)		(GET_LWP (ptid) != 0)
14298944Sobrien#define is_thread(ptid)		(GET_THREAD (ptid) != 0)
14398944Sobrien
14498944Sobrien#define BUILD_LWP(lwp, pid)	ptid_build (pid, lwp, 0)
14598944Sobrien#define BUILD_THREAD(tid, pid)	ptid_build (pid, 0, tid)
14698944Sobrien
14798944Sobrien
148130803Smarcel/* Use "struct private_thread_info" to cache thread state.  This is
149130803Smarcel   a substantial optimization.  */
150130803Smarcel
15198944Sobrienstruct private_thread_info
15298944Sobrien{
153130803Smarcel  /* Cached thread state.  */
154130803Smarcel  unsigned int th_valid:1;
155130803Smarcel  unsigned int ti_valid:1;
156130803Smarcel
157130803Smarcel  td_thrhandle_t th;
158130803Smarcel  td_thrinfo_t ti;
15998944Sobrien};
16098944Sobrien
16198944Sobrien
16298944Sobrienstatic char *
16398944Sobrienthread_db_err_str (td_err_e err)
16498944Sobrien{
16598944Sobrien  static char buf[64];
16698944Sobrien
16798944Sobrien  switch (err)
16898944Sobrien    {
16998944Sobrien    case TD_OK:
17098944Sobrien      return "generic 'call succeeded'";
17198944Sobrien    case TD_ERR:
17298944Sobrien      return "generic error";
17398944Sobrien    case TD_NOTHR:
17498944Sobrien      return "no thread to satisfy query";
17598944Sobrien    case TD_NOSV:
17698944Sobrien      return "no sync handle to satisfy query";
17798944Sobrien    case TD_NOLWP:
17898944Sobrien      return "no LWP to satisfy query";
17998944Sobrien    case TD_BADPH:
18098944Sobrien      return "invalid process handle";
18198944Sobrien    case TD_BADTH:
18298944Sobrien      return "invalid thread handle";
18398944Sobrien    case TD_BADSH:
18498944Sobrien      return "invalid synchronization handle";
18598944Sobrien    case TD_BADTA:
18698944Sobrien      return "invalid thread agent";
18798944Sobrien    case TD_BADKEY:
18898944Sobrien      return "invalid key";
18998944Sobrien    case TD_NOMSG:
19098944Sobrien      return "no event message for getmsg";
19198944Sobrien    case TD_NOFPREGS:
19298944Sobrien      return "FPU register set not available";
19398944Sobrien    case TD_NOLIBTHREAD:
19498944Sobrien      return "application not linked with libthread";
19598944Sobrien    case TD_NOEVENT:
19698944Sobrien      return "requested event is not supported";
19798944Sobrien    case TD_NOCAPAB:
19898944Sobrien      return "capability not available";
19998944Sobrien    case TD_DBERR:
20098944Sobrien      return "debugger service failed";
20198944Sobrien    case TD_NOAPLIC:
20298944Sobrien      return "operation not applicable to";
20398944Sobrien    case TD_NOTSD:
20498944Sobrien      return "no thread-specific data for this thread";
20598944Sobrien    case TD_MALLOC:
20698944Sobrien      return "malloc failed";
20798944Sobrien    case TD_PARTIALREG:
20898944Sobrien      return "only part of register set was written/read";
20998944Sobrien    case TD_NOXREGS:
21098944Sobrien      return "X register set not available for this thread";
21198944Sobrien    default:
21298944Sobrien      snprintf (buf, sizeof (buf), "unknown thread_db error '%d'", err);
21398944Sobrien      return buf;
21498944Sobrien    }
21598944Sobrien}
21698944Sobrien
21798944Sobrienstatic char *
21898944Sobrienthread_db_state_str (td_thr_state_e state)
21998944Sobrien{
22098944Sobrien  static char buf[64];
22198944Sobrien
22298944Sobrien  switch (state)
22398944Sobrien    {
22498944Sobrien    case TD_THR_STOPPED:
22598944Sobrien      return "stopped by debugger";
22698944Sobrien    case TD_THR_RUN:
22798944Sobrien      return "runnable";
22898944Sobrien    case TD_THR_ACTIVE:
22998944Sobrien      return "active";
23098944Sobrien    case TD_THR_ZOMBIE:
23198944Sobrien      return "zombie";
23298944Sobrien    case TD_THR_SLEEP:
23398944Sobrien      return "sleeping";
23498944Sobrien    case TD_THR_STOPPED_ASLEEP:
23598944Sobrien      return "stopped by debugger AND blocked";
23698944Sobrien    default:
23798944Sobrien      snprintf (buf, sizeof (buf), "unknown thread_db state %d", state);
23898944Sobrien      return buf;
23998944Sobrien    }
24098944Sobrien}
24198944Sobrien
242130803Smarcel/* A callback function for td_ta_thr_iter, which we use to map all
243130803Smarcel   threads to LWPs.
24498944Sobrien
245130803Smarcel   THP is a handle to the current thread; if INFOP is not NULL, the
246130803Smarcel   struct thread_info associated with this thread is returned in
247130803Smarcel   *INFOP.  */
248130803Smarcel
249130803Smarcelstatic int
250130803Smarcelthread_get_info_callback (const td_thrhandle_t *thp, void *infop)
251130803Smarcel{
252130803Smarcel  td_thrinfo_t ti;
253130803Smarcel  td_err_e err;
254130803Smarcel  struct thread_info *thread_info;
255130803Smarcel  ptid_t thread_ptid;
256130803Smarcel
257130803Smarcel  err = td_thr_get_info_p (thp, &ti);
258130803Smarcel  if (err != TD_OK)
259130803Smarcel    error ("thread_get_info_callback: cannot get thread info: %s",
260130803Smarcel	   thread_db_err_str (err));
261130803Smarcel
262130803Smarcel  /* Fill the cache.  */
263130803Smarcel  thread_ptid = BUILD_THREAD (ti.ti_tid, GET_PID (inferior_ptid));
264130803Smarcel  thread_info = find_thread_pid (thread_ptid);
265130803Smarcel
266130803Smarcel  if (thread_info == NULL)
267130803Smarcel    {
268130803Smarcel      /* New thread.  Attach to it now (why wait?).  */
269130803Smarcel      attach_thread (thread_ptid, thp, &ti, 1);
270130803Smarcel      thread_info = find_thread_pid (thread_ptid);
271130803Smarcel      gdb_assert (thread_info != NULL);
272130803Smarcel    }
273130803Smarcel
274130803Smarcel  memcpy (&thread_info->private->th, thp, sizeof (*thp));
275130803Smarcel  thread_info->private->th_valid = 1;
276130803Smarcel  memcpy (&thread_info->private->ti, &ti, sizeof (ti));
277130803Smarcel  thread_info->private->ti_valid = 1;
278130803Smarcel
279130803Smarcel  if (infop != NULL)
280130803Smarcel    *(struct thread_info **) infop = thread_info;
281130803Smarcel
282130803Smarcel  return 0;
283130803Smarcel}
284130803Smarcel
285130803Smarcel/* Accessor functions for the thread_db information, with caching.  */
286130803Smarcel
287130803Smarcelstatic void
288130803Smarcelthread_db_map_id2thr (struct thread_info *thread_info, int fatal)
289130803Smarcel{
290130803Smarcel  td_err_e err;
291130803Smarcel
292130803Smarcel  if (thread_info->private->th_valid)
293130803Smarcel    return;
294130803Smarcel
295130803Smarcel  err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (thread_info->ptid),
296130803Smarcel			    &thread_info->private->th);
297130803Smarcel  if (err != TD_OK)
298130803Smarcel    {
299130803Smarcel      if (fatal)
300130803Smarcel	error ("Cannot find thread %ld: %s",
301130803Smarcel	       (long) GET_THREAD (thread_info->ptid),
302130803Smarcel	       thread_db_err_str (err));
303130803Smarcel    }
304130803Smarcel  else
305130803Smarcel    thread_info->private->th_valid = 1;
306130803Smarcel}
307130803Smarcel
308130803Smarcelstatic td_thrinfo_t *
309130803Smarcelthread_db_get_info (struct thread_info *thread_info)
310130803Smarcel{
311130803Smarcel  td_err_e err;
312130803Smarcel
313130803Smarcel  if (thread_info->private->ti_valid)
314130803Smarcel    return &thread_info->private->ti;
315130803Smarcel
316130803Smarcel  if (!thread_info->private->th_valid)
317130803Smarcel    thread_db_map_id2thr (thread_info, 1);
318130803Smarcel
319130803Smarcel  err =
320130803Smarcel    td_thr_get_info_p (&thread_info->private->th, &thread_info->private->ti);
321130803Smarcel  if (err != TD_OK)
322130803Smarcel    error ("thread_db_get_info: cannot get thread info: %s",
323130803Smarcel	   thread_db_err_str (err));
324130803Smarcel
325130803Smarcel  thread_info->private->ti_valid = 1;
326130803Smarcel  return &thread_info->private->ti;
327130803Smarcel}
328130803Smarcel
32998944Sobrien/* Convert between user-level thread ids and LWP ids.  */
33098944Sobrien
33198944Sobrienstatic ptid_t
33298944Sobrienthread_from_lwp (ptid_t ptid)
33398944Sobrien{
33498944Sobrien  td_thrhandle_t th;
33598944Sobrien  td_err_e err;
336130803Smarcel  struct thread_info *thread_info;
337130803Smarcel  ptid_t thread_ptid;
33898944Sobrien
33998944Sobrien  if (GET_LWP (ptid) == 0)
34098944Sobrien    ptid = BUILD_LWP (GET_PID (ptid), GET_PID (ptid));
34198944Sobrien
34298944Sobrien  gdb_assert (is_lwp (ptid));
34398944Sobrien
34498944Sobrien  err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), &th);
34598944Sobrien  if (err != TD_OK)
346130803Smarcel    error ("Cannot find user-level thread for LWP %ld: %s",
34798944Sobrien	   GET_LWP (ptid), thread_db_err_str (err));
34898944Sobrien
349130803Smarcel  thread_info = NULL;
350130803Smarcel  thread_get_info_callback (&th, &thread_info);
351130803Smarcel  gdb_assert (thread_info && thread_info->private->ti_valid);
35298944Sobrien
353130803Smarcel  return BUILD_THREAD (thread_info->private->ti.ti_tid, GET_PID (ptid));
35498944Sobrien}
35598944Sobrien
35698944Sobrienstatic ptid_t
35798944Sobrienlwp_from_thread (ptid_t ptid)
35898944Sobrien{
359130803Smarcel  struct thread_info *thread_info;
360130803Smarcel  ptid_t thread_ptid;
36198944Sobrien
36298944Sobrien  if (!is_thread (ptid))
36398944Sobrien    return ptid;
36498944Sobrien
365130803Smarcel  thread_info = find_thread_pid (ptid);
366130803Smarcel  thread_db_get_info (thread_info);
36798944Sobrien
368130803Smarcel  return BUILD_LWP (thread_info->private->ti.ti_lid, GET_PID (ptid));
36998944Sobrien}
37098944Sobrien
37198944Sobrien
37298944Sobrienvoid
37398944Sobrienthread_db_init (struct target_ops *target)
37498944Sobrien{
37598944Sobrien  target_beneath = target;
37698944Sobrien}
37798944Sobrien
378130803Smarcelstatic void *
379130803Smarcelverbose_dlsym (void *handle, const char *name)
380130803Smarcel{
381130803Smarcel  void *sym = dlsym (handle, name);
382130803Smarcel  if (sym == NULL)
383130803Smarcel    warning ("Symbol \"%s\" not found in libthread_db: %s", name, dlerror ());
384130803Smarcel  return sym;
385130803Smarcel}
386130803Smarcel
38798944Sobrienstatic int
38898944Sobrienthread_db_load (void)
38998944Sobrien{
39098944Sobrien  void *handle;
39198944Sobrien  td_err_e err;
39298944Sobrien
39398944Sobrien  handle = dlopen (LIBTHREAD_DB_SO, RTLD_NOW);
39498944Sobrien  if (handle == NULL)
395130803Smarcel    {
396130803Smarcel      fprintf_filtered (gdb_stderr, "\n\ndlopen failed on '%s' - %s\n",
397130803Smarcel			LIBTHREAD_DB_SO, dlerror ());
398130803Smarcel      fprintf_filtered (gdb_stderr,
399130803Smarcel			"GDB will not be able to debug pthreads.\n\n");
400130803Smarcel      return 0;
401130803Smarcel    }
40298944Sobrien
40398944Sobrien  /* Initialize pointers to the dynamic library functions we will use.
40498944Sobrien     Essential functions first.  */
40598944Sobrien
406130803Smarcel  td_init_p = verbose_dlsym (handle, "td_init");
40798944Sobrien  if (td_init_p == NULL)
40898944Sobrien    return 0;
40998944Sobrien
410130803Smarcel  td_ta_new_p = verbose_dlsym (handle, "td_ta_new");
41198944Sobrien  if (td_ta_new_p == NULL)
41298944Sobrien    return 0;
41398944Sobrien
414130803Smarcel  td_ta_map_id2thr_p = verbose_dlsym (handle, "td_ta_map_id2thr");
41598944Sobrien  if (td_ta_map_id2thr_p == NULL)
41698944Sobrien    return 0;
41798944Sobrien
418130803Smarcel  td_ta_map_lwp2thr_p = verbose_dlsym (handle, "td_ta_map_lwp2thr");
41998944Sobrien  if (td_ta_map_lwp2thr_p == NULL)
42098944Sobrien    return 0;
42198944Sobrien
422130803Smarcel  td_ta_thr_iter_p = verbose_dlsym (handle, "td_ta_thr_iter");
42398944Sobrien  if (td_ta_thr_iter_p == NULL)
42498944Sobrien    return 0;
42598944Sobrien
426130803Smarcel  td_thr_validate_p = verbose_dlsym (handle, "td_thr_validate");
42798944Sobrien  if (td_thr_validate_p == NULL)
42898944Sobrien    return 0;
42998944Sobrien
430130803Smarcel  td_thr_get_info_p = verbose_dlsym (handle, "td_thr_get_info");
43198944Sobrien  if (td_thr_get_info_p == NULL)
43298944Sobrien    return 0;
43398944Sobrien
434130803Smarcel  td_thr_getfpregs_p = verbose_dlsym (handle, "td_thr_getfpregs");
43598944Sobrien  if (td_thr_getfpregs_p == NULL)
43698944Sobrien    return 0;
43798944Sobrien
438130803Smarcel  td_thr_getgregs_p = verbose_dlsym (handle, "td_thr_getgregs");
43998944Sobrien  if (td_thr_getgregs_p == NULL)
44098944Sobrien    return 0;
44198944Sobrien
442130803Smarcel  td_thr_setfpregs_p = verbose_dlsym (handle, "td_thr_setfpregs");
44398944Sobrien  if (td_thr_setfpregs_p == NULL)
44498944Sobrien    return 0;
44598944Sobrien
446130803Smarcel  td_thr_setgregs_p = verbose_dlsym (handle, "td_thr_setgregs");
44798944Sobrien  if (td_thr_setgregs_p == NULL)
44898944Sobrien    return 0;
44998944Sobrien
45098944Sobrien  /* Initialize the library.  */
45198944Sobrien  err = td_init_p ();
45298944Sobrien  if (err != TD_OK)
45398944Sobrien    {
45498944Sobrien      warning ("Cannot initialize libthread_db: %s", thread_db_err_str (err));
45598944Sobrien      return 0;
45698944Sobrien    }
45798944Sobrien
45898944Sobrien  /* These are not essential.  */
45998944Sobrien  td_ta_event_addr_p = dlsym (handle, "td_ta_event_addr");
46098944Sobrien  td_ta_set_event_p = dlsym (handle, "td_ta_set_event");
46198944Sobrien  td_ta_event_getmsg_p = dlsym (handle, "td_ta_event_getmsg");
46298944Sobrien  td_thr_event_enable_p = dlsym (handle, "td_thr_event_enable");
463130803Smarcel  td_thr_tls_get_addr_p = dlsym (handle, "td_thr_tls_get_addr");
46498944Sobrien
46598944Sobrien  return 1;
46698944Sobrien}
46798944Sobrien
468130803Smarcelstatic td_err_e
469130803Smarcelenable_thread_event (td_thragent_t *thread_agent, int event, CORE_ADDR *bp)
470130803Smarcel{
471130803Smarcel  td_notify_t notify;
472130803Smarcel  td_err_e err;
473130803Smarcel
474130803Smarcel  /* Get the breakpoint address for thread EVENT.  */
475130803Smarcel  err = td_ta_event_addr_p (thread_agent, event, &notify);
476130803Smarcel  if (err != TD_OK)
477130803Smarcel    return err;
478130803Smarcel
479130803Smarcel  /* Set up the breakpoint.  */
480130803Smarcel  (*bp) = gdbarch_convert_from_func_ptr_addr (current_gdbarch,
481130803Smarcel					      (CORE_ADDR) notify.u.bptaddr,
482130803Smarcel					      &current_target);
483130803Smarcel  create_thread_event_breakpoint ((*bp));
484130803Smarcel
485130803Smarcel  return TD_OK;
486130803Smarcel}
487130803Smarcel
48898944Sobrienstatic void
48998944Sobrienenable_thread_event_reporting (void)
49098944Sobrien{
49198944Sobrien  td_thr_events_t events;
49298944Sobrien  td_notify_t notify;
49398944Sobrien  td_err_e err;
49498944Sobrien
49598944Sobrien  /* We cannot use the thread event reporting facility if these
49698944Sobrien     functions aren't available.  */
49798944Sobrien  if (td_ta_event_addr_p == NULL || td_ta_set_event_p == NULL
49898944Sobrien      || td_ta_event_getmsg_p == NULL || td_thr_event_enable_p == NULL)
49998944Sobrien    return;
50098944Sobrien
50198944Sobrien  /* Set the process wide mask saying which events we're interested in.  */
50298944Sobrien  td_event_emptyset (&events);
50398944Sobrien  td_event_addset (&events, TD_CREATE);
50498944Sobrien#if 0
50598944Sobrien  /* FIXME: kettenis/2000-04-23: The event reporting facility is
50698944Sobrien     broken for TD_DEATH events in glibc 2.1.3, so don't enable it for
50798944Sobrien     now.  */
50898944Sobrien  td_event_addset (&events, TD_DEATH);
50998944Sobrien#endif
51098944Sobrien
51198944Sobrien  err = td_ta_set_event_p (thread_agent, &events);
51298944Sobrien  if (err != TD_OK)
51398944Sobrien    {
51498944Sobrien      warning ("Unable to set global thread event mask: %s",
51598944Sobrien	       thread_db_err_str (err));
51698944Sobrien      return;
51798944Sobrien    }
51898944Sobrien
51998944Sobrien  /* Delete previous thread event breakpoints, if any.  */
52098944Sobrien  remove_thread_event_breakpoints ();
521130803Smarcel  td_create_bp_addr = 0;
522130803Smarcel  td_death_bp_addr = 0;
52398944Sobrien
524130803Smarcel  /* Set up the thread creation event.  */
525130803Smarcel  err = enable_thread_event (thread_agent, TD_CREATE, &td_create_bp_addr);
52698944Sobrien  if (err != TD_OK)
52798944Sobrien    {
52898944Sobrien      warning ("Unable to get location for thread creation breakpoint: %s",
52998944Sobrien	       thread_db_err_str (err));
53098944Sobrien      return;
53198944Sobrien    }
53298944Sobrien
533130803Smarcel  /* Set up the thread death event.  */
534130803Smarcel  err = enable_thread_event (thread_agent, TD_DEATH, &td_death_bp_addr);
53598944Sobrien  if (err != TD_OK)
53698944Sobrien    {
53798944Sobrien      warning ("Unable to get location for thread death breakpoint: %s",
53898944Sobrien	       thread_db_err_str (err));
53998944Sobrien      return;
54098944Sobrien    }
54198944Sobrien}
54298944Sobrien
54398944Sobrienstatic void
54498944Sobriendisable_thread_event_reporting (void)
54598944Sobrien{
54698944Sobrien  td_thr_events_t events;
54798944Sobrien
54898944Sobrien  /* Set the process wide mask saying we aren't interested in any
54998944Sobrien     events anymore.  */
55098944Sobrien  td_event_emptyset (&events);
55198944Sobrien  td_ta_set_event_p (thread_agent, &events);
55298944Sobrien
55398944Sobrien  /* Delete thread event breakpoints, if any.  */
55498944Sobrien  remove_thread_event_breakpoints ();
55598944Sobrien  td_create_bp_addr = 0;
55698944Sobrien  td_death_bp_addr = 0;
55798944Sobrien}
55898944Sobrien
55998944Sobrienstatic void
56098944Sobriencheck_thread_signals (void)
56198944Sobrien{
56298944Sobrien#ifdef GET_THREAD_SIGNALS
56398944Sobrien  if (!thread_signals)
56498944Sobrien    {
56598944Sobrien      sigset_t mask;
56698944Sobrien      int i;
56798944Sobrien
56898944Sobrien      GET_THREAD_SIGNALS (&mask);
56998944Sobrien      sigemptyset (&thread_stop_set);
57098944Sobrien      sigemptyset (&thread_print_set);
57198944Sobrien
57298944Sobrien      for (i = 1; i < NSIG; i++)
57398944Sobrien	{
57498944Sobrien	  if (sigismember (&mask, i))
57598944Sobrien	    {
57698944Sobrien	      if (signal_stop_update (target_signal_from_host (i), 0))
57798944Sobrien		sigaddset (&thread_stop_set, i);
57898944Sobrien	      if (signal_print_update (target_signal_from_host (i), 0))
57998944Sobrien		sigaddset (&thread_print_set, i);
58098944Sobrien	      thread_signals = 1;
58198944Sobrien	    }
58298944Sobrien	}
58398944Sobrien    }
58498944Sobrien#endif
58598944Sobrien}
58698944Sobrien
58798944Sobrienstatic void
58898944Sobrienthread_db_new_objfile (struct objfile *objfile)
58998944Sobrien{
59098944Sobrien  td_err_e err;
59198944Sobrien
592130803Smarcel  /* First time through, report that libthread_db was successfuly
593130803Smarcel     loaded.  Can't print this in in thread_db_load as, at that stage,
594130803Smarcel     the interpreter and it's console haven't started.  The real
595130803Smarcel     problem here is that libthread_db is loaded too early - it should
596130803Smarcel     only be loaded when there is a program to debug.  */
597130803Smarcel  {
598130803Smarcel    static int dejavu;
599130803Smarcel    if (!dejavu)
600130803Smarcel      {
601130803Smarcel	Dl_info info;
602130803Smarcel	const char *library = NULL;
603130803Smarcel	/* Try dladdr.  */
604130803Smarcel	if (dladdr ((*td_ta_new_p), &info) != 0)
605130803Smarcel	  library = info.dli_fname;
606130803Smarcel	/* Try dlinfo?  */
607130803Smarcel	if (library == NULL)
608130803Smarcel	  /* Paranoid - don't let a NULL path slip through.  */
609130803Smarcel	  library = LIBTHREAD_DB_SO;
610130803Smarcel	printf_unfiltered ("Using host libthread_db library \"%s\".\n",
611130803Smarcel			   library);
612130803Smarcel	dejavu = 1;
613130803Smarcel      }
614130803Smarcel  }
615130803Smarcel
61698944Sobrien  /* Don't attempt to use thread_db on targets which can not run
61798944Sobrien     (core files).  */
61898944Sobrien  if (objfile == NULL || !target_has_execution)
61998944Sobrien    {
62098944Sobrien      /* All symbols have been discarded.  If the thread_db target is
62198944Sobrien         active, deactivate it now.  */
62298944Sobrien      if (using_thread_db)
62398944Sobrien	{
62498944Sobrien	  gdb_assert (proc_handle.pid == 0);
62598944Sobrien	  unpush_target (&thread_db_ops);
62698944Sobrien	  using_thread_db = 0;
62798944Sobrien	}
62898944Sobrien
62998944Sobrien      keep_thread_db = 0;
63098944Sobrien
63198944Sobrien      goto quit;
63298944Sobrien    }
63398944Sobrien
63498944Sobrien  if (using_thread_db)
63598944Sobrien    /* Nothing to do.  The thread library was already detected and the
63698944Sobrien       target vector was already activated.  */
63798944Sobrien    goto quit;
63898944Sobrien
63998944Sobrien  /* Initialize the structure that identifies the child process.  Note
64098944Sobrien     that at this point there is no guarantee that we actually have a
64198944Sobrien     child process.  */
64298944Sobrien  proc_handle.pid = GET_PID (inferior_ptid);
64398944Sobrien
64498944Sobrien  /* Now attempt to open a connection to the thread library.  */
64598944Sobrien  err = td_ta_new_p (&proc_handle, &thread_agent);
64698944Sobrien  switch (err)
64798944Sobrien    {
64898944Sobrien    case TD_NOLIBTHREAD:
64998944Sobrien      /* No thread library was detected.  */
65098944Sobrien      break;
65198944Sobrien
65298944Sobrien    case TD_OK:
653130803Smarcel      printf_unfiltered ("[Thread debugging using libthread_db enabled]\n");
654130803Smarcel
65598944Sobrien      /* The thread library was detected.  Activate the thread_db target.  */
65698944Sobrien      push_target (&thread_db_ops);
65798944Sobrien      using_thread_db = 1;
65898944Sobrien
65998944Sobrien      /* If the thread library was detected in the main symbol file
66098944Sobrien         itself, we assume that the program was statically linked
66198944Sobrien         against the thread library and well have to keep this
66298944Sobrien         module's target vector activated until forever...  Well, at
66398944Sobrien         least until all symbols have been discarded anyway (see
66498944Sobrien         above).  */
66598944Sobrien      if (objfile == symfile_objfile)
66698944Sobrien	{
66798944Sobrien	  gdb_assert (proc_handle.pid == 0);
66898944Sobrien	  keep_thread_db = 1;
66998944Sobrien	}
67098944Sobrien
67198944Sobrien      /* We can only poke around if there actually is a child process.
67298944Sobrien         If there is no child process alive, postpone the steps below
67398944Sobrien         until one has been created.  */
67498944Sobrien      if (proc_handle.pid != 0)
67598944Sobrien	{
67698944Sobrien	  enable_thread_event_reporting ();
67798944Sobrien	  thread_db_find_new_threads ();
67898944Sobrien	}
67998944Sobrien      break;
68098944Sobrien
68198944Sobrien    default:
68298944Sobrien      warning ("Cannot initialize thread debugging library: %s",
68398944Sobrien	       thread_db_err_str (err));
68498944Sobrien      break;
68598944Sobrien    }
68698944Sobrien
687130803Smarcelquit:
68898944Sobrien  if (target_new_objfile_chain)
68998944Sobrien    target_new_objfile_chain (objfile);
69098944Sobrien}
69198944Sobrien
69298944Sobrienstatic void
69398944Sobrienattach_thread (ptid_t ptid, const td_thrhandle_t *th_p,
69498944Sobrien	       const td_thrinfo_t *ti_p, int verbose)
69598944Sobrien{
69698944Sobrien  struct thread_info *tp;
69798944Sobrien  td_err_e err;
69898944Sobrien
69998944Sobrien  check_thread_signals ();
70098944Sobrien
70198944Sobrien  /* Add the thread to GDB's thread list.  */
70298944Sobrien  tp = add_thread (ptid);
70398944Sobrien  tp->private = xmalloc (sizeof (struct private_thread_info));
704130803Smarcel  memset (tp->private, 0, sizeof (struct private_thread_info));
70598944Sobrien
706130803Smarcel  if (verbose)
707130803Smarcel    printf_unfiltered ("[New %s]\n", target_pid_to_str (ptid));
708130803Smarcel
70998944Sobrien  if (ti_p->ti_state == TD_THR_UNKNOWN || ti_p->ti_state == TD_THR_ZOMBIE)
71098944Sobrien    return;			/* A zombie thread -- do not attach.  */
71198944Sobrien
71298944Sobrien  /* Under GNU/Linux, we have to attach to each and every thread.  */
71398944Sobrien#ifdef ATTACH_LWP
71498944Sobrien  ATTACH_LWP (BUILD_LWP (ti_p->ti_lid, GET_PID (ptid)), 0);
71598944Sobrien#endif
71698944Sobrien
71798944Sobrien  /* Enable thread event reporting for this thread.  */
71898944Sobrien  err = td_thr_event_enable_p (th_p, 1);
71998944Sobrien  if (err != TD_OK)
72098944Sobrien    error ("Cannot enable thread event reporting for %s: %s",
72198944Sobrien	   target_pid_to_str (ptid), thread_db_err_str (err));
72298944Sobrien}
72398944Sobrien
72498944Sobrienstatic void
72598944Sobrienthread_db_attach (char *args, int from_tty)
72698944Sobrien{
72798944Sobrien  target_beneath->to_attach (args, from_tty);
72898944Sobrien
72998944Sobrien  /* Destroy thread info; it's no longer valid.  */
73098944Sobrien  init_thread_list ();
73198944Sobrien
73298944Sobrien  /* The child process is now the actual multi-threaded
73398944Sobrien     program.  Snatch its process ID...  */
73498944Sobrien  proc_handle.pid = GET_PID (inferior_ptid);
73598944Sobrien
73698944Sobrien  /* ...and perform the remaining initialization steps.  */
73798944Sobrien  enable_thread_event_reporting ();
738130803Smarcel  thread_db_find_new_threads ();
73998944Sobrien}
74098944Sobrien
74198944Sobrienstatic void
74298944Sobriendetach_thread (ptid_t ptid, int verbose)
74398944Sobrien{
74498944Sobrien  if (verbose)
74598944Sobrien    printf_unfiltered ("[%s exited]\n", target_pid_to_str (ptid));
74698944Sobrien}
74798944Sobrien
74898944Sobrienstatic void
74998944Sobrienthread_db_detach (char *args, int from_tty)
75098944Sobrien{
75198944Sobrien  disable_thread_event_reporting ();
75298944Sobrien
75398944Sobrien  /* There's no need to save & restore inferior_ptid here, since the
75498944Sobrien     inferior is supposed to be survive this function call.  */
75598944Sobrien  inferior_ptid = lwp_from_thread (inferior_ptid);
75698944Sobrien
75798944Sobrien  /* Forget about the child's process ID.  We shouldn't need it
75898944Sobrien     anymore.  */
75998944Sobrien  proc_handle.pid = 0;
76098944Sobrien
76198944Sobrien  target_beneath->to_detach (args, from_tty);
76298944Sobrien}
76398944Sobrien
764130803Smarcelstatic int
765130803Smarcelclear_lwpid_callback (struct thread_info *thread, void *dummy)
766130803Smarcel{
767130803Smarcel  /* If we know that our thread implementation is 1-to-1, we could save
768130803Smarcel     a certain amount of information; it's not clear how much, so we
769130803Smarcel     are always conservative.  */
770130803Smarcel
771130803Smarcel  thread->private->th_valid = 0;
772130803Smarcel  thread->private->ti_valid = 0;
773130803Smarcel
774130803Smarcel  return 0;
775130803Smarcel}
776130803Smarcel
77798944Sobrienstatic void
77898944Sobrienthread_db_resume (ptid_t ptid, int step, enum target_signal signo)
77998944Sobrien{
78098944Sobrien  struct cleanup *old_chain = save_inferior_ptid ();
78198944Sobrien
78298944Sobrien  if (GET_PID (ptid) == -1)
78398944Sobrien    inferior_ptid = lwp_from_thread (inferior_ptid);
78498944Sobrien  else if (is_thread (ptid))
78598944Sobrien    ptid = lwp_from_thread (ptid);
78698944Sobrien
787130803Smarcel  /* Clear cached data which may not be valid after the resume.  */
788130803Smarcel  iterate_over_threads (clear_lwpid_callback, NULL);
789130803Smarcel
79098944Sobrien  target_beneath->to_resume (ptid, step, signo);
79198944Sobrien
79298944Sobrien  do_cleanups (old_chain);
79398944Sobrien}
79498944Sobrien
79598944Sobrien/* Check if PID is currently stopped at the location of a thread event
79698944Sobrien   breakpoint location.  If it is, read the event message and act upon
79798944Sobrien   the event.  */
79898944Sobrien
79998944Sobrienstatic void
80098944Sobriencheck_event (ptid_t ptid)
80198944Sobrien{
80298944Sobrien  td_event_msg_t msg;
80398944Sobrien  td_thrinfo_t ti;
80498944Sobrien  td_err_e err;
80598944Sobrien  CORE_ADDR stop_pc;
806130803Smarcel  int loop = 0;
80798944Sobrien
80898944Sobrien  /* Bail out early if we're not at a thread event breakpoint.  */
80998944Sobrien  stop_pc = read_pc_pid (ptid) - DECR_PC_AFTER_BREAK;
81098944Sobrien  if (stop_pc != td_create_bp_addr && stop_pc != td_death_bp_addr)
81198944Sobrien    return;
81298944Sobrien
813130803Smarcel  /* If we are at a create breakpoint, we do not know what new lwp
814130803Smarcel     was created and cannot specifically locate the event message for it.
815130803Smarcel     We have to call td_ta_event_getmsg() to get
816130803Smarcel     the latest message.  Since we have no way of correlating whether
817130803Smarcel     the event message we get back corresponds to our breakpoint, we must
818130803Smarcel     loop and read all event messages, processing them appropriately.
819130803Smarcel     This guarantees we will process the correct message before continuing
820130803Smarcel     from the breakpoint.
821130803Smarcel
822130803Smarcel     Currently, death events are not enabled.  If they are enabled,
823130803Smarcel     the death event can use the td_thr_event_getmsg() interface to
824130803Smarcel     get the message specifically for that lwp and avoid looping
825130803Smarcel     below.  */
826130803Smarcel
827130803Smarcel  loop = 1;
828130803Smarcel
829130803Smarcel  do
83098944Sobrien    {
831130803Smarcel      err = td_ta_event_getmsg_p (thread_agent, &msg);
832130803Smarcel      if (err != TD_OK)
833130803Smarcel	{
834130803Smarcel	  if (err == TD_NOMSG)
835130803Smarcel	    return;
83698944Sobrien
837130803Smarcel	  error ("Cannot get thread event message: %s",
838130803Smarcel		 thread_db_err_str (err));
839130803Smarcel	}
84098944Sobrien
841130803Smarcel      err = td_thr_get_info_p (msg.th_p, &ti);
842130803Smarcel      if (err != TD_OK)
843130803Smarcel	error ("Cannot get thread info: %s", thread_db_err_str (err));
84498944Sobrien
845130803Smarcel      ptid = BUILD_THREAD (ti.ti_tid, GET_PID (ptid));
84698944Sobrien
847130803Smarcel      switch (msg.event)
848130803Smarcel	{
849130803Smarcel	case TD_CREATE:
85098944Sobrien
851130803Smarcel	  /* We may already know about this thread, for instance when the
852130803Smarcel	     user has issued the `info threads' command before the SIGTRAP
853130803Smarcel	     for hitting the thread creation breakpoint was reported.  */
854130803Smarcel	  if (!in_thread_list (ptid))
855130803Smarcel	    attach_thread (ptid, msg.th_p, &ti, 1);
85698944Sobrien
857130803Smarcel	  break;
85898944Sobrien
859130803Smarcel	case TD_DEATH:
86098944Sobrien
861130803Smarcel	  if (!in_thread_list (ptid))
862130803Smarcel	    error ("Spurious thread death event.");
86398944Sobrien
864130803Smarcel	  detach_thread (ptid, 1);
86598944Sobrien
866130803Smarcel	  break;
86798944Sobrien
868130803Smarcel	default:
869130803Smarcel	  error ("Spurious thread event.");
870130803Smarcel	}
87198944Sobrien    }
872130803Smarcel  while (loop);
87398944Sobrien}
87498944Sobrien
87598944Sobrienstatic ptid_t
87698944Sobrienthread_db_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
87798944Sobrien{
87898944Sobrien  extern ptid_t trap_ptid;
87998944Sobrien
88098944Sobrien  if (GET_PID (ptid) != -1 && is_thread (ptid))
88198944Sobrien    ptid = lwp_from_thread (ptid);
88298944Sobrien
88398944Sobrien  ptid = target_beneath->to_wait (ptid, ourstatus);
88498944Sobrien
88598944Sobrien  if (proc_handle.pid == 0)
88698944Sobrien    /* The current child process isn't the actual multi-threaded
88798944Sobrien       program yet, so don't try to do any special thread-specific
88898944Sobrien       post-processing and bail out early.  */
88998944Sobrien    return ptid;
89098944Sobrien
89198944Sobrien  if (ourstatus->kind == TARGET_WAITKIND_EXITED)
89298944Sobrien    return pid_to_ptid (-1);
89398944Sobrien
89498944Sobrien  if (ourstatus->kind == TARGET_WAITKIND_STOPPED
89598944Sobrien      && ourstatus->value.sig == TARGET_SIGNAL_TRAP)
89698944Sobrien    /* Check for a thread event.  */
89798944Sobrien    check_event (ptid);
89898944Sobrien
89998944Sobrien  if (!ptid_equal (trap_ptid, null_ptid))
90098944Sobrien    trap_ptid = thread_from_lwp (trap_ptid);
90198944Sobrien
90298944Sobrien  return thread_from_lwp (ptid);
90398944Sobrien}
90498944Sobrien
90598944Sobrienstatic int
90698944Sobrienthread_db_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
907130803Smarcel		       struct mem_attrib *attrib, struct target_ops *target)
90898944Sobrien{
90998944Sobrien  struct cleanup *old_chain = save_inferior_ptid ();
91098944Sobrien  int xfer;
91198944Sobrien
91298944Sobrien  if (is_thread (inferior_ptid))
91398944Sobrien    {
91498944Sobrien      /* FIXME: This seems to be necessary to make sure breakpoints
91598944Sobrien         are removed.  */
91698944Sobrien      if (!target_thread_alive (inferior_ptid))
91798944Sobrien	inferior_ptid = pid_to_ptid (GET_PID (inferior_ptid));
91898944Sobrien      else
91998944Sobrien	inferior_ptid = lwp_from_thread (inferior_ptid);
92098944Sobrien    }
92198944Sobrien
922130803Smarcel  xfer =
923130803Smarcel    target_beneath->to_xfer_memory (memaddr, myaddr, len, write, attrib,
924130803Smarcel				    target);
92598944Sobrien
92698944Sobrien  do_cleanups (old_chain);
92798944Sobrien  return xfer;
92898944Sobrien}
92998944Sobrien
93098944Sobrienstatic void
93198944Sobrienthread_db_fetch_registers (int regno)
93298944Sobrien{
933130803Smarcel  struct thread_info *thread_info;
93498944Sobrien  prgregset_t gregset;
93598944Sobrien  gdb_prfpregset_t fpregset;
93698944Sobrien  td_err_e err;
93798944Sobrien
93898944Sobrien  if (!is_thread (inferior_ptid))
93998944Sobrien    {
94098944Sobrien      /* Pass the request to the target beneath us.  */
94198944Sobrien      target_beneath->to_fetch_registers (regno);
94298944Sobrien      return;
94398944Sobrien    }
94498944Sobrien
945130803Smarcel  thread_info = find_thread_pid (inferior_ptid);
946130803Smarcel  thread_db_map_id2thr (thread_info, 1);
94798944Sobrien
948130803Smarcel  err = td_thr_getgregs_p (&thread_info->private->th, gregset);
94998944Sobrien  if (err != TD_OK)
95098944Sobrien    error ("Cannot fetch general-purpose registers for thread %ld: %s",
95198944Sobrien	   (long) GET_THREAD (inferior_ptid), thread_db_err_str (err));
95298944Sobrien
953130803Smarcel  err = td_thr_getfpregs_p (&thread_info->private->th, &fpregset);
95498944Sobrien  if (err != TD_OK)
95598944Sobrien    error ("Cannot get floating-point registers for thread %ld: %s",
95698944Sobrien	   (long) GET_THREAD (inferior_ptid), thread_db_err_str (err));
95798944Sobrien
95898944Sobrien  /* Note that we must call supply_gregset after calling the thread_db
95998944Sobrien     routines because the thread_db routines call ps_lgetgregs and
96098944Sobrien     friends which clobber GDB's register cache.  */
96198944Sobrien  supply_gregset ((gdb_gregset_t *) gregset);
96298944Sobrien  supply_fpregset (&fpregset);
96398944Sobrien}
96498944Sobrien
96598944Sobrienstatic void
96698944Sobrienthread_db_store_registers (int regno)
96798944Sobrien{
96898944Sobrien  prgregset_t gregset;
96998944Sobrien  gdb_prfpregset_t fpregset;
97098944Sobrien  td_err_e err;
971130803Smarcel  struct thread_info *thread_info;
97298944Sobrien
97398944Sobrien  if (!is_thread (inferior_ptid))
97498944Sobrien    {
97598944Sobrien      /* Pass the request to the target beneath us.  */
97698944Sobrien      target_beneath->to_store_registers (regno);
97798944Sobrien      return;
97898944Sobrien    }
97998944Sobrien
980130803Smarcel  thread_info = find_thread_pid (inferior_ptid);
981130803Smarcel  thread_db_map_id2thr (thread_info, 1);
98298944Sobrien
98398944Sobrien  if (regno != -1)
98498944Sobrien    {
985130803Smarcel      char raw[MAX_REGISTER_SIZE];
98698944Sobrien
987130803Smarcel      deprecated_read_register_gen (regno, raw);
98898944Sobrien      thread_db_fetch_registers (-1);
98998944Sobrien      supply_register (regno, raw);
99098944Sobrien    }
99198944Sobrien
99298944Sobrien  fill_gregset ((gdb_gregset_t *) gregset, -1);
99398944Sobrien  fill_fpregset (&fpregset, -1);
99498944Sobrien
995130803Smarcel  err = td_thr_setgregs_p (&thread_info->private->th, gregset);
99698944Sobrien  if (err != TD_OK)
99798944Sobrien    error ("Cannot store general-purpose registers for thread %ld: %s",
99898944Sobrien	   (long) GET_THREAD (inferior_ptid), thread_db_err_str (err));
999130803Smarcel  err = td_thr_setfpregs_p (&thread_info->private->th, &fpregset);
100098944Sobrien  if (err != TD_OK)
100198944Sobrien    error ("Cannot store floating-point registers  for thread %ld: %s",
100298944Sobrien	   (long) GET_THREAD (inferior_ptid), thread_db_err_str (err));
100398944Sobrien}
100498944Sobrien
100598944Sobrienstatic void
100698944Sobrienthread_db_kill (void)
100798944Sobrien{
100898944Sobrien  /* There's no need to save & restore inferior_ptid here, since the
100998944Sobrien     inferior isn't supposed to survive this function call.  */
101098944Sobrien  inferior_ptid = lwp_from_thread (inferior_ptid);
101198944Sobrien  target_beneath->to_kill ();
101298944Sobrien}
101398944Sobrien
101498944Sobrienstatic void
101598944Sobrienthread_db_create_inferior (char *exec_file, char *allargs, char **env)
101698944Sobrien{
101798944Sobrien  if (!keep_thread_db)
101898944Sobrien    {
101998944Sobrien      unpush_target (&thread_db_ops);
102098944Sobrien      using_thread_db = 0;
102198944Sobrien    }
102298944Sobrien
102398944Sobrien  target_beneath->to_create_inferior (exec_file, allargs, env);
102498944Sobrien}
102598944Sobrien
102698944Sobrienstatic void
102798944Sobrienthread_db_post_startup_inferior (ptid_t ptid)
102898944Sobrien{
102998944Sobrien  if (proc_handle.pid == 0)
103098944Sobrien    {
103198944Sobrien      /* The child process is now the actual multi-threaded
103298944Sobrien         program.  Snatch its process ID...  */
103398944Sobrien      proc_handle.pid = GET_PID (ptid);
103498944Sobrien
103598944Sobrien      /* ...and perform the remaining initialization steps.  */
103698944Sobrien      enable_thread_event_reporting ();
103798944Sobrien      thread_db_find_new_threads ();
103898944Sobrien    }
103998944Sobrien}
104098944Sobrien
104198944Sobrienstatic void
104298944Sobrienthread_db_mourn_inferior (void)
104398944Sobrien{
104498944Sobrien  remove_thread_event_breakpoints ();
104598944Sobrien
104698944Sobrien  /* Forget about the child's process ID.  We shouldn't need it
104798944Sobrien     anymore.  */
104898944Sobrien  proc_handle.pid = 0;
104998944Sobrien
105098944Sobrien  target_beneath->to_mourn_inferior ();
1051130803Smarcel
1052130803Smarcel  /* Detach thread_db target ops if not dealing with a statically
1053130803Smarcel     linked threaded program.  This allows a corefile to be debugged
1054130803Smarcel     after finishing debugging of a threaded program.  At present,
1055130803Smarcel     debugging a statically-linked threaded program is broken, but
1056130803Smarcel     the check is added below in the event that it is fixed in the
1057130803Smarcel     future.  */
1058130803Smarcel  if (!keep_thread_db)
1059130803Smarcel    {
1060130803Smarcel      unpush_target (&thread_db_ops);
1061130803Smarcel      using_thread_db = 0;
1062130803Smarcel    }
106398944Sobrien}
106498944Sobrien
106598944Sobrienstatic int
106698944Sobrienthread_db_thread_alive (ptid_t ptid)
106798944Sobrien{
106898944Sobrien  td_thrhandle_t th;
106998944Sobrien  td_err_e err;
107098944Sobrien
107198944Sobrien  if (is_thread (ptid))
107298944Sobrien    {
1073130803Smarcel      struct thread_info *thread_info;
1074130803Smarcel      thread_info = find_thread_pid (ptid);
107598944Sobrien
1076130803Smarcel      thread_db_map_id2thr (thread_info, 0);
1077130803Smarcel      if (!thread_info->private->th_valid)
107898944Sobrien	return 0;
107998944Sobrien
1080130803Smarcel      err = td_thr_validate_p (&thread_info->private->th);
108198944Sobrien      if (err != TD_OK)
108298944Sobrien	return 0;
108398944Sobrien
1084130803Smarcel      if (!thread_info->private->ti_valid)
1085130803Smarcel	{
1086130803Smarcel	  err =
1087130803Smarcel	    td_thr_get_info_p (&thread_info->private->th,
1088130803Smarcel			       &thread_info->private->ti);
1089130803Smarcel	  if (err != TD_OK)
1090130803Smarcel	    return 0;
1091130803Smarcel	  thread_info->private->ti_valid = 1;
1092130803Smarcel	}
1093130803Smarcel
1094130803Smarcel      if (thread_info->private->ti.ti_state == TD_THR_UNKNOWN
1095130803Smarcel	  || thread_info->private->ti.ti_state == TD_THR_ZOMBIE)
109698944Sobrien	return 0;		/* A zombie thread.  */
109798944Sobrien
109898944Sobrien      return 1;
109998944Sobrien    }
110098944Sobrien
110198944Sobrien  if (target_beneath->to_thread_alive)
110298944Sobrien    return target_beneath->to_thread_alive (ptid);
110398944Sobrien
110498944Sobrien  return 0;
110598944Sobrien}
110698944Sobrien
110798944Sobrienstatic int
110898944Sobrienfind_new_threads_callback (const td_thrhandle_t *th_p, void *data)
110998944Sobrien{
111098944Sobrien  td_thrinfo_t ti;
111198944Sobrien  td_err_e err;
111298944Sobrien  ptid_t ptid;
111398944Sobrien
111498944Sobrien  err = td_thr_get_info_p (th_p, &ti);
111598944Sobrien  if (err != TD_OK)
1116130803Smarcel    error ("find_new_threads_callback: cannot get thread info: %s",
1117130803Smarcel	   thread_db_err_str (err));
111898944Sobrien
111998944Sobrien  if (ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE)
112098944Sobrien    return 0;			/* A zombie -- ignore.  */
112198944Sobrien
112298944Sobrien  ptid = BUILD_THREAD (ti.ti_tid, GET_PID (inferior_ptid));
112398944Sobrien
112498944Sobrien  if (!in_thread_list (ptid))
112598944Sobrien    attach_thread (ptid, th_p, &ti, 1);
112698944Sobrien
112798944Sobrien  return 0;
112898944Sobrien}
112998944Sobrien
113098944Sobrienstatic void
113198944Sobrienthread_db_find_new_threads (void)
113298944Sobrien{
113398944Sobrien  td_err_e err;
113498944Sobrien
113598944Sobrien  /* Iterate over all user-space threads to discover new threads.  */
113698944Sobrien  err = td_ta_thr_iter_p (thread_agent, find_new_threads_callback, NULL,
113798944Sobrien			  TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
113898944Sobrien			  TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
113998944Sobrien  if (err != TD_OK)
114098944Sobrien    error ("Cannot find new threads: %s", thread_db_err_str (err));
114198944Sobrien}
114298944Sobrien
114398944Sobrienstatic char *
114498944Sobrienthread_db_pid_to_str (ptid_t ptid)
114598944Sobrien{
114698944Sobrien  if (is_thread (ptid))
114798944Sobrien    {
114898944Sobrien      static char buf[64];
1149130803Smarcel      td_thrinfo_t *ti_p;
115098944Sobrien      td_err_e err;
1151130803Smarcel      struct thread_info *thread_info;
115298944Sobrien
1153130803Smarcel      thread_info = find_thread_pid (ptid);
1154130803Smarcel      thread_db_map_id2thr (thread_info, 0);
1155130803Smarcel      if (!thread_info->private->th_valid)
1156130803Smarcel	{
1157130803Smarcel	  snprintf (buf, sizeof (buf), "Thread %ld (Missing)",
1158130803Smarcel		    GET_THREAD (ptid));
1159130803Smarcel	  return buf;
1160130803Smarcel	}
116198944Sobrien
1162130803Smarcel      ti_p = thread_db_get_info (thread_info);
116398944Sobrien
1164130803Smarcel      if (ti_p->ti_state == TD_THR_ACTIVE && ti_p->ti_lid != 0)
116598944Sobrien	{
116698944Sobrien	  snprintf (buf, sizeof (buf), "Thread %ld (LWP %d)",
1167130803Smarcel		    (long) ti_p->ti_tid, ti_p->ti_lid);
116898944Sobrien	}
116998944Sobrien      else
117098944Sobrien	{
117198944Sobrien	  snprintf (buf, sizeof (buf), "Thread %ld (%s)",
1172130803Smarcel		    (long) ti_p->ti_tid,
1173130803Smarcel		    thread_db_state_str (ti_p->ti_state));
117498944Sobrien	}
117598944Sobrien
117698944Sobrien      return buf;
117798944Sobrien    }
117898944Sobrien
117998944Sobrien  if (target_beneath->to_pid_to_str (ptid))
118098944Sobrien    return target_beneath->to_pid_to_str (ptid);
118198944Sobrien
118298944Sobrien  return normal_pid_to_str (ptid);
118398944Sobrien}
118498944Sobrien
1185130803Smarcel/* Get the address of the thread local variable in OBJFILE which is
1186130803Smarcel   stored at OFFSET within the thread local storage for thread PTID.  */
1187130803Smarcel
1188130803Smarcelstatic CORE_ADDR
1189130803Smarcelthread_db_get_thread_local_address (ptid_t ptid, struct objfile *objfile,
1190130803Smarcel				    CORE_ADDR offset)
1191130803Smarcel{
1192130803Smarcel  if (is_thread (ptid))
1193130803Smarcel    {
1194130803Smarcel      int objfile_is_library = (objfile->flags & OBJF_SHARED);
1195130803Smarcel      td_err_e err;
1196130803Smarcel      void *address;
1197130803Smarcel      CORE_ADDR lm;
1198130803Smarcel      struct thread_info *thread_info;
1199130803Smarcel
1200130803Smarcel      /* glibc doesn't provide the needed interface.  */
1201130803Smarcel      if (!td_thr_tls_get_addr_p)
1202130803Smarcel	error ("Cannot find thread-local variables in this thread library.");
1203130803Smarcel
1204130803Smarcel      /* Get the address of the link map for this objfile.  */
1205130803Smarcel      lm = svr4_fetch_objfile_link_map (objfile);
1206130803Smarcel
1207130803Smarcel      /* Whoops, we couldn't find one. Bail out.  */
1208130803Smarcel      if (!lm)
1209130803Smarcel	{
1210130803Smarcel	  if (objfile_is_library)
1211130803Smarcel	    error ("Cannot find shared library `%s' link_map in dynamic"
1212130803Smarcel		   " linker's module list", objfile->name);
1213130803Smarcel	  else
1214130803Smarcel	    error ("Cannot find executable file `%s' link_map in dynamic"
1215130803Smarcel		   " linker's module list", objfile->name);
1216130803Smarcel	}
1217130803Smarcel
1218130803Smarcel      /* Get info about the thread.  */
1219130803Smarcel      thread_info = find_thread_pid (ptid);
1220130803Smarcel      thread_db_map_id2thr (thread_info, 1);
1221130803Smarcel
1222130803Smarcel      /* Finally, get the address of the variable.  */
1223130803Smarcel      err = td_thr_tls_get_addr_p (&thread_info->private->th, (void *) lm,
1224130803Smarcel				   offset, &address);
1225130803Smarcel
1226130803Smarcel#ifdef THREAD_DB_HAS_TD_NOTALLOC
1227130803Smarcel      /* The memory hasn't been allocated, yet.  */
1228130803Smarcel      if (err == TD_NOTALLOC)
1229130803Smarcel	{
1230130803Smarcel	  /* Now, if libthread_db provided the initialization image's
1231130803Smarcel	     address, we *could* try to build a non-lvalue value from
1232130803Smarcel	     the initialization image.  */
1233130803Smarcel	  if (objfile_is_library)
1234130803Smarcel	    error ("The inferior has not yet allocated storage for"
1235130803Smarcel		   " thread-local variables in\n"
1236130803Smarcel		   "the shared library `%s'\n"
1237130803Smarcel		   "for the thread %ld",
1238130803Smarcel		   objfile->name, (long) GET_THREAD (ptid));
1239130803Smarcel	  else
1240130803Smarcel	    error ("The inferior has not yet allocated storage for"
1241130803Smarcel		   " thread-local variables in\n"
1242130803Smarcel		   "the executable `%s'\n"
1243130803Smarcel		   "for the thread %ld",
1244130803Smarcel		   objfile->name, (long) GET_THREAD (ptid));
1245130803Smarcel	}
1246130803Smarcel#endif
1247130803Smarcel
1248130803Smarcel      /* Something else went wrong.  */
1249130803Smarcel      if (err != TD_OK)
1250130803Smarcel	{
1251130803Smarcel	  if (objfile_is_library)
1252130803Smarcel	    error ("Cannot find thread-local storage for thread %ld, "
1253130803Smarcel		   "shared library %s:\n%s",
1254130803Smarcel		   (long) GET_THREAD (ptid),
1255130803Smarcel		   objfile->name, thread_db_err_str (err));
1256130803Smarcel	  else
1257130803Smarcel	    error ("Cannot find thread-local storage for thread %ld, "
1258130803Smarcel		   "executable file %s:\n%s",
1259130803Smarcel		   (long) GET_THREAD (ptid),
1260130803Smarcel		   objfile->name, thread_db_err_str (err));
1261130803Smarcel	}
1262130803Smarcel
1263130803Smarcel      /* Cast assuming host == target.  Joy.  */
1264130803Smarcel      return (CORE_ADDR) address;
1265130803Smarcel    }
1266130803Smarcel
1267130803Smarcel  if (target_beneath->to_get_thread_local_address)
1268130803Smarcel    return target_beneath->to_get_thread_local_address (ptid, objfile,
1269130803Smarcel							offset);
1270130803Smarcel
1271130803Smarcel  error ("Cannot find thread-local values on this target.");
1272130803Smarcel}
1273130803Smarcel
127498944Sobrienstatic void
127598944Sobrieninit_thread_db_ops (void)
127698944Sobrien{
127798944Sobrien  thread_db_ops.to_shortname = "multi-thread";
127898944Sobrien  thread_db_ops.to_longname = "multi-threaded child process.";
127998944Sobrien  thread_db_ops.to_doc = "Threads and pthreads support.";
128098944Sobrien  thread_db_ops.to_attach = thread_db_attach;
128198944Sobrien  thread_db_ops.to_detach = thread_db_detach;
128298944Sobrien  thread_db_ops.to_resume = thread_db_resume;
128398944Sobrien  thread_db_ops.to_wait = thread_db_wait;
128498944Sobrien  thread_db_ops.to_fetch_registers = thread_db_fetch_registers;
128598944Sobrien  thread_db_ops.to_store_registers = thread_db_store_registers;
128698944Sobrien  thread_db_ops.to_xfer_memory = thread_db_xfer_memory;
128798944Sobrien  thread_db_ops.to_kill = thread_db_kill;
128898944Sobrien  thread_db_ops.to_create_inferior = thread_db_create_inferior;
128998944Sobrien  thread_db_ops.to_post_startup_inferior = thread_db_post_startup_inferior;
129098944Sobrien  thread_db_ops.to_mourn_inferior = thread_db_mourn_inferior;
129198944Sobrien  thread_db_ops.to_thread_alive = thread_db_thread_alive;
129298944Sobrien  thread_db_ops.to_find_new_threads = thread_db_find_new_threads;
129398944Sobrien  thread_db_ops.to_pid_to_str = thread_db_pid_to_str;
129498944Sobrien  thread_db_ops.to_stratum = thread_stratum;
129598944Sobrien  thread_db_ops.to_has_thread_control = tc_schedlock;
1296130803Smarcel  thread_db_ops.to_get_thread_local_address
1297130803Smarcel    = thread_db_get_thread_local_address;
129898944Sobrien  thread_db_ops.to_magic = OPS_MAGIC;
129998944Sobrien}
130098944Sobrien
130198944Sobrienvoid
130298944Sobrien_initialize_thread_db (void)
130398944Sobrien{
130498944Sobrien  /* Only initialize the module if we can load libthread_db.  */
130598944Sobrien  if (thread_db_load ())
130698944Sobrien    {
130798944Sobrien      init_thread_db_ops ();
130898944Sobrien      add_target (&thread_db_ops);
130998944Sobrien
131098944Sobrien      /* Add ourselves to objfile event chain.  */
131198944Sobrien      target_new_objfile_chain = target_new_objfile_hook;
131298944Sobrien      target_new_objfile_hook = thread_db_new_objfile;
131398944Sobrien    }
131498944Sobrien}
1315