1/* Solaris threads debugging interface.
2
3   Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004
4   Free Software Foundation, Inc.
5
6   This file is part of GDB.
7
8   This program is free software; you can redistribute it and/or modify
9   it under the terms of the GNU General Public License as published by
10   the Free Software Foundation; either version 2 of the License, or
11   (at your option) any later version.
12
13   This program is distributed in the hope that it will be useful,
14   but WITHOUT ANY WARRANTY; without even the implied warranty of
15   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   GNU General Public License for more details.
17
18   You should have received a copy of the GNU General Public License
19   along with this program; if not, write to the Free Software
20   Foundation, Inc., 59 Temple Place - Suite 330,
21   Boston, MA 02111-1307, USA.  */
22
23/* This module implements a sort of half target that sits between the
24   machine-independent parts of GDB and the /proc interface (procfs.c)
25   to provide access to the Solaris user-mode thread implementation.
26
27   Solaris threads are true user-mode threads, which are invoked via
28   the thr_* and pthread_* (native and POSIX respectivly) interfaces.
29   These are mostly implemented in user-space, with all thread context
30   kept in various structures that live in the user's heap.  These
31   should not be confused with lightweight processes (LWPs), which are
32   implemented by the kernel, and scheduled without explicit
33   intervention by the process.
34
35   Just to confuse things a little, Solaris threads (both native and
36   POSIX) are actually implemented using LWPs.  In general, there are
37   going to be more threads than LWPs.  There is no fixed
38   correspondence between a thread and an LWP.  When a thread wants to
39   run, it gets scheduled onto the first available LWP and can
40   therefore migrate from one LWP to another as time goes on.  A
41   sleeping thread may not be associated with an LWP at all!
42
43   To make it possible to mess with threads, Sun provides a library
44   called libthread_db.so.1 (not to be confused with
45   libthread_db.so.0, which doesn't have a published interface).  This
46   interface has an upper part, which it provides, and a lower part
47   which we provide.  The upper part consists of the td_* routines,
48   which allow us to find all the threads, query their state, etc...
49   The lower part consists of all of the ps_*, which are used by the
50   td_* routines to read/write memory, manipulate LWPs, lookup
51   symbols, etc...  The ps_* routines actually do most of their work
52   by calling functions in procfs.c.  */
53
54#include "defs.h"
55#include <thread.h>
56#include <proc_service.h>
57#include <thread_db.h>
58#include "gdbthread.h"
59#include "target.h"
60#include "inferior.h"
61#include <fcntl.h>
62#include "gdb_stat.h"
63#include <dlfcn.h>
64#include "gdbcmd.h"
65#include "gdbcore.h"
66#include "regcache.h"
67#include "symfile.h"
68
69#include "gdb_string.h"
70
71extern struct target_ops sol_thread_ops;	/* Forward declaration */
72extern struct target_ops sol_core_ops;	/* Forward declaration */
73
74/* place to store core_ops before we overwrite it */
75static struct target_ops orig_core_ops;
76
77struct target_ops sol_thread_ops;
78struct target_ops sol_core_ops;
79
80extern int procfs_suppress_run;
81extern struct target_ops procfs_ops;	/* target vector for procfs.c */
82extern struct target_ops core_ops;	/* target vector for corelow.c */
83extern char *procfs_pid_to_str (ptid_t ptid);
84
85/* Prototypes for supply_gregset etc. */
86#include "gregset.h"
87
88/* This struct is defined by us, but mainly used for the proc_service
89   interface.  We don't have much use for it, except as a handy place
90   to get a real PID for memory accesses.  */
91
92struct ps_prochandle
93{
94  ptid_t ptid;
95};
96
97struct string_map
98{
99  int num;
100  char *str;
101};
102
103static struct ps_prochandle main_ph;
104static td_thragent_t *main_ta;
105static int sol_thread_active = 0;
106
107static void sol_thread_resume (ptid_t ptid, int step, enum target_signal signo);
108static int sol_thread_alive (ptid_t ptid);
109static void sol_core_close (int quitting);
110
111static void init_sol_thread_ops (void);
112static void init_sol_core_ops (void);
113
114/* Default definitions: These must be defined in tm.h if they are to
115   be shared with a process module such as procfs.  */
116
117#define GET_PID(ptid)		ptid_get_pid (ptid)
118#define GET_LWP(ptid)		ptid_get_lwp (ptid)
119#define GET_THREAD(ptid)	ptid_get_tid (ptid)
120
121#define is_lwp(ptid)		(GET_LWP (ptid) != 0)
122#define is_thread(ptid)		(GET_THREAD (ptid) != 0)
123
124#define BUILD_LWP(lwp, pid)	ptid_build (pid, lwp, 0)
125#define BUILD_THREAD(tid, pid)	ptid_build (pid, 0, tid)
126
127/* Pointers to routines from libthread_db resolved by dlopen().  */
128
129static void (*p_td_log)(const int on_off);
130static td_err_e (*p_td_ta_new)(const struct ps_prochandle *ph_p,
131			       td_thragent_t **ta_pp);
132static td_err_e (*p_td_ta_delete)(td_thragent_t *ta_p);
133static td_err_e (*p_td_init)(void);
134static td_err_e (*p_td_ta_get_ph)(const td_thragent_t *ta_p,
135				  struct ps_prochandle **ph_pp);
136static td_err_e (*p_td_ta_get_nthreads)(const td_thragent_t *ta_p,
137					int *nthread_p);
138static td_err_e (*p_td_ta_tsd_iter)(const td_thragent_t *ta_p,
139				    td_key_iter_f *cb, void *cbdata_p);
140static td_err_e (*p_td_ta_thr_iter)(const td_thragent_t *ta_p,
141				    td_thr_iter_f *cb, void *cbdata_p,
142				    td_thr_state_e state, int ti_pri,
143				    sigset_t *ti_sigmask_p,
144				    unsigned ti_user_flags);
145static td_err_e (*p_td_thr_validate)(const td_thrhandle_t *th_p);
146static td_err_e (*p_td_thr_tsd)(const td_thrhandle_t * th_p,
147				const thread_key_t key, void **data_pp);
148static td_err_e (*p_td_thr_get_info)(const td_thrhandle_t *th_p,
149				     td_thrinfo_t *ti_p);
150static td_err_e (*p_td_thr_getfpregs)(const td_thrhandle_t *th_p,
151				      prfpregset_t *fpregset);
152static td_err_e (*p_td_thr_getxregsize)(const td_thrhandle_t *th_p,
153					int *xregsize);
154static td_err_e (*p_td_thr_getxregs)(const td_thrhandle_t *th_p,
155				     const caddr_t xregset);
156static td_err_e (*p_td_thr_sigsetmask)(const td_thrhandle_t *th_p,
157				       const sigset_t ti_sigmask);
158static td_err_e (*p_td_thr_setprio)(const td_thrhandle_t *th_p,
159				    const int ti_pri);
160static td_err_e (*p_td_thr_setsigpending)(const td_thrhandle_t *th_p,
161					  const uchar_t ti_pending_flag,
162					  const sigset_t ti_pending);
163static td_err_e (*p_td_thr_setfpregs)(const td_thrhandle_t *th_p,
164				      const prfpregset_t *fpregset);
165static td_err_e (*p_td_thr_setxregs)(const td_thrhandle_t *th_p,
166				     const caddr_t xregset);
167static td_err_e (*p_td_ta_map_id2thr)(const td_thragent_t *ta_p,
168				      thread_t tid,
169				      td_thrhandle_t *th_p);
170static td_err_e (*p_td_ta_map_lwp2thr)(const td_thragent_t *ta_p,
171				       lwpid_t lwpid,
172				       td_thrhandle_t *th_p);
173static td_err_e (*p_td_thr_getgregs)(const td_thrhandle_t *th_p,
174				     prgregset_t regset);
175static td_err_e (*p_td_thr_setgregs)(const td_thrhandle_t *th_p,
176				     const prgregset_t regset);
177
178
179/* Return the libthread_db error string associated with ERRCODE.  If
180   ERRCODE is unknown, return an appropriate message.  */
181
182static char *
183td_err_string (td_err_e errcode)
184{
185  static struct string_map td_err_table[] =
186  {
187    { TD_OK, "generic \"call succeeded\"" },
188    { TD_ERR, "generic error." },
189    { TD_NOTHR, "no thread can be found to satisfy query" },
190    { TD_NOSV, "no synch. variable can be found to satisfy query" },
191    { TD_NOLWP, "no lwp can be found to satisfy query" },
192    { TD_BADPH, "invalid process handle" },
193    { TD_BADTH, "invalid thread handle" },
194    { TD_BADSH, "invalid synchronization handle" },
195    { TD_BADTA, "invalid thread agent" },
196    { TD_BADKEY, "invalid key" },
197    { TD_NOMSG, "td_thr_event_getmsg() called when there was no message" },
198    { TD_NOFPREGS, "FPU register set not available for given thread" },
199    { TD_NOLIBTHREAD, "application not linked with libthread" },
200    { TD_NOEVENT, "requested event is not supported" },
201    { TD_NOCAPAB, "capability not available" },
202    { TD_DBERR, "Debugger service failed" },
203    { TD_NOAPLIC, "Operation not applicable to" },
204    { TD_NOTSD, "No thread specific data for this thread" },
205    { TD_MALLOC, "Malloc failed" },
206    { TD_PARTIALREG, "Only part of register set was written/read" },
207    { TD_NOXREGS, "X register set not available for given thread" }
208  };
209  const int td_err_size = sizeof td_err_table / sizeof (struct string_map);
210  int i;
211  static char buf[50];
212
213  for (i = 0; i < td_err_size; i++)
214    if (td_err_table[i].num == errcode)
215      return td_err_table[i].str;
216
217  sprintf (buf, "Unknown libthread_db error code: %d", errcode);
218
219  return buf;
220}
221
222/* Return the the libthread_db state string assicoated with STATECODE.
223   If STATECODE is unknown, return an appropriate message.  */
224
225static char *
226td_state_string (td_thr_state_e statecode)
227{
228  static struct string_map td_thr_state_table[] =
229  {
230    { TD_THR_ANY_STATE, "any state" },
231    { TD_THR_UNKNOWN, "unknown" },
232    { TD_THR_STOPPED, "stopped" },
233    { TD_THR_RUN, "run" },
234    { TD_THR_ACTIVE, "active" },
235    { TD_THR_ZOMBIE, "zombie" },
236    { TD_THR_SLEEP, "sleep" },
237    { TD_THR_STOPPED_ASLEEP, "stopped asleep" }
238  };
239  const int td_thr_state_table_size =
240    sizeof td_thr_state_table / sizeof (struct string_map);
241  int i;
242  static char buf[50];
243
244  for (i = 0; i < td_thr_state_table_size; i++)
245    if (td_thr_state_table[i].num == statecode)
246      return td_thr_state_table[i].str;
247
248  sprintf (buf, "Unknown libthread_db state code: %d", statecode);
249
250  return buf;
251}
252
253
254/* Convert a POSIX or Solaris thread ID into a LWP ID.  If THREAD_ID
255   doesn't exist, that's an error.  If it's an inactive thread, return
256   DEFAULT_LPW.
257
258   NOTE: This function probably shouldn't call error().  */
259
260static ptid_t
261thread_to_lwp (ptid_t thread_id, int default_lwp)
262{
263  td_thrinfo_t ti;
264  td_thrhandle_t th;
265  td_err_e val;
266
267  if (is_lwp (thread_id))
268    return thread_id;		/* It's already an LWP ID.  */
269
270  /* It's a thread.  Convert to LWP.  */
271
272  val = p_td_ta_map_id2thr (main_ta, GET_THREAD (thread_id), &th);
273  if (val == TD_NOTHR)
274    return pid_to_ptid (-1);	/* Thread must have terminated.  */
275  else if (val != TD_OK)
276    error ("thread_to_lwp: td_ta_map_id2thr %s", td_err_string (val));
277
278  val = p_td_thr_get_info (&th, &ti);
279  if (val == TD_NOTHR)
280    return pid_to_ptid (-1);	/* Thread must have terminated.  */
281  else if (val != TD_OK)
282    error ("thread_to_lwp: td_thr_get_info: %s", td_err_string (val));
283
284  if (ti.ti_state != TD_THR_ACTIVE)
285    {
286      if (default_lwp != -1)
287	return pid_to_ptid (default_lwp);
288      error ("thread_to_lwp: thread state not active: %s",
289	     td_state_string (ti.ti_state));
290    }
291
292  return BUILD_LWP (ti.ti_lid, PIDGET (thread_id));
293}
294
295/* Convert an LWP ID into a POSIX or Solaris thread ID.  If LWP_ID
296   doesn't exists, that's an error.
297
298   NOTE: This function probably shouldn't call error().  */
299
300static ptid_t
301lwp_to_thread (ptid_t lwp)
302{
303  td_thrinfo_t ti;
304  td_thrhandle_t th;
305  td_err_e val;
306
307  if (is_thread (lwp))
308    return lwp;			/* It's already a thread ID.  */
309
310  /* It's an LWP.  Convert it to a thread ID.  */
311
312  if (!sol_thread_alive (lwp))
313    return pid_to_ptid (-1);	/* Must be a defunct LPW.  */
314
315  val = p_td_ta_map_lwp2thr (main_ta, GET_LWP (lwp), &th);
316  if (val == TD_NOTHR)
317    return pid_to_ptid (-1);	/* Thread must have terminated.  */
318  else if (val != TD_OK)
319    error ("lwp_to_thread: td_ta_map_lwp2thr: %s.", td_err_string (val));
320
321  val = p_td_thr_validate (&th);
322  if (val == TD_NOTHR)
323    return lwp;			/* Unknown to libthread; just return LPW,  */
324  else if (val != TD_OK)
325    error ("lwp_to_thread: td_thr_validate: %s.", td_err_string (val));
326
327  val = p_td_thr_get_info (&th, &ti);
328  if (val == TD_NOTHR)
329    return pid_to_ptid (-1);	/* Thread must have terminated.  */
330  else if (val != TD_OK)
331    error ("lwp_to_thread: td_thr_get_info: %s.", td_err_string (val));
332
333  return BUILD_THREAD (ti.ti_tid, PIDGET (lwp));
334}
335
336
337/* Most target vector functions from here on actually just pass
338   through to procfs.c, as they don't need to do anything specific for
339   threads.  */
340
341static void
342sol_thread_open (char *arg, int from_tty)
343{
344  procfs_ops.to_open (arg, from_tty);
345}
346
347/* Attach to process PID, then initialize for debugging it and wait
348   for the trace-trap that results from attaching.  */
349
350static void
351sol_thread_attach (char *args, int from_tty)
352{
353  procfs_ops.to_attach (args, from_tty);
354
355  /* Must get symbols from shared libraries before libthread_db can run!  */
356  SOLIB_ADD ((char *) 0, from_tty, (struct target_ops *) 0, auto_solib_add);
357
358  if (sol_thread_active)
359    {
360      printf_filtered ("sol-thread active.\n");
361      main_ph.ptid = inferior_ptid; /* Save for xfer_memory.  */
362      push_target (&sol_thread_ops);
363      inferior_ptid = lwp_to_thread (inferior_ptid);
364      if (PIDGET (inferior_ptid) == -1)
365	inferior_ptid = main_ph.ptid;
366      else
367	add_thread (inferior_ptid);
368    }
369
370  /* FIXME: Might want to iterate over all the threads and register
371     them.  */
372}
373
374/* Take a program previously attached to and detaches it.  The program
375   resumes execution and will no longer stop on signals, etc.  We'd
376   better not have left any breakpoints in the program or it'll die
377   when it hits one.  For this to work, it may be necessary for the
378   process to have been previously attached.  It *might* work if the
379   program was started via the normal ptrace (PTRACE_TRACEME).  */
380
381static void
382sol_thread_detach (char *args, int from_tty)
383{
384  inferior_ptid = pid_to_ptid (PIDGET (main_ph.ptid));
385  unpush_target (&sol_thread_ops);
386  procfs_ops.to_detach (args, from_tty);
387}
388
389/* Resume execution of process PTID.  If STEP is nozero, then just
390   single step it.  If SIGNAL is nonzero, restart it with that signal
391   activated.  We may have to convert PTID from a thread ID to an LWP
392   ID for procfs.  */
393
394static void
395sol_thread_resume (ptid_t ptid, int step, enum target_signal signo)
396{
397  struct cleanup *old_chain;
398
399  old_chain = save_inferior_ptid ();
400
401  inferior_ptid = thread_to_lwp (inferior_ptid, PIDGET (main_ph.ptid));
402  if (PIDGET (inferior_ptid) == -1)
403    inferior_ptid = procfs_first_available ();
404
405  if (PIDGET (ptid) != -1)
406    {
407      ptid_t save_ptid = ptid;
408
409      ptid = thread_to_lwp (ptid, -2);
410      if (PIDGET (ptid) == -2)		/* Inactive thread.  */
411	error ("This version of Solaris can't start inactive threads.");
412      if (info_verbose && PIDGET (ptid) == -1)
413	warning ("Specified thread %ld seems to have terminated",
414		 GET_THREAD (save_ptid));
415    }
416
417  procfs_ops.to_resume (ptid, step, signo);
418
419  do_cleanups (old_chain);
420}
421
422/* Wait for any threads to stop.  We may have to convert PIID from a
423   thread ID to an LWP ID, and vice versa on the way out.  */
424
425static ptid_t
426sol_thread_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
427{
428  ptid_t rtnval;
429  ptid_t save_ptid;
430  struct cleanup *old_chain;
431
432  save_ptid = inferior_ptid;
433  old_chain = save_inferior_ptid ();
434
435  inferior_ptid = thread_to_lwp (inferior_ptid, PIDGET (main_ph.ptid));
436  if (PIDGET (inferior_ptid) == -1)
437    inferior_ptid = procfs_first_available ();
438
439  if (PIDGET (ptid) != -1)
440    {
441      ptid_t save_ptid = ptid;
442
443      ptid = thread_to_lwp (ptid, -2);
444      if (PIDGET (ptid) == -2)		/* Inactive thread.  */
445	error ("This version of Solaris can't start inactive threads.");
446      if (info_verbose && PIDGET (ptid) == -1)
447	warning ("Specified thread %ld seems to have terminated",
448		 GET_THREAD (save_ptid));
449    }
450
451  rtnval = procfs_ops.to_wait (ptid, ourstatus);
452
453  if (ourstatus->kind != TARGET_WAITKIND_EXITED)
454    {
455      /* Map the LWP of interest back to the appropriate thread ID.  */
456      rtnval = lwp_to_thread (rtnval);
457      if (PIDGET (rtnval) == -1)
458	rtnval = save_ptid;
459
460      /* See if we have a new thread.  */
461      if (is_thread (rtnval)
462	  && !ptid_equal (rtnval, save_ptid)
463	  && !in_thread_list (rtnval))
464	{
465	  printf_filtered ("[New %s]\n", target_pid_to_str (rtnval));
466	  add_thread (rtnval);
467	}
468    }
469
470  /* During process initialization, we may get here without the thread
471     package being initialized, since that can only happen after we've
472     found the shared libs.  */
473
474  do_cleanups (old_chain);
475
476  return rtnval;
477}
478
479static void
480sol_thread_fetch_registers (int regnum)
481{
482  thread_t thread;
483  td_thrhandle_t thandle;
484  td_err_e val;
485  prgregset_t gregset;
486  prfpregset_t fpregset;
487#if 0
488  int xregsize;
489  caddr_t xregset;
490#endif
491
492  if (!is_thread (inferior_ptid))
493    {
494      /* It's an LWP; pass the request on to procfs.  */
495      if (target_has_execution)
496	procfs_ops.to_fetch_registers (regnum);
497      else
498	orig_core_ops.to_fetch_registers (regnum);
499      return;
500    }
501
502  /* Solaris thread: convert INFERIOR_PTID into a td_thrhandle_t.  */
503  thread = GET_THREAD (inferior_ptid);
504  if (thread == 0)
505    error ("sol_thread_fetch_registers: thread == 0");
506
507  val = p_td_ta_map_id2thr (main_ta, thread, &thandle);
508  if (val != TD_OK)
509    error ("sol_thread_fetch_registers: td_ta_map_id2thr: %s",
510	   td_err_string (val));
511
512  /* Get the general-purpose registers.  */
513
514  val = p_td_thr_getgregs (&thandle, gregset);
515  if (val != TD_OK && val != TD_PARTIALREG)
516    error ("sol_thread_fetch_registers: td_thr_getgregs %s",
517	   td_err_string (val));
518
519  /* For SPARC, TD_PARTIALREG means that only %i0...%i7, %l0..%l7, %pc
520     and %sp are saved (by a thread context switch).  */
521
522  /* And, now the floating-point registers.  */
523
524  val = p_td_thr_getfpregs (&thandle, &fpregset);
525  if (val != TD_OK && val != TD_NOFPREGS)
526    error ("sol_thread_fetch_registers: td_thr_getfpregs %s",
527	   td_err_string (val));
528
529  /* Note that we must call supply_gregset and supply_fpregset *after*
530     calling the td routines because the td routines call ps_lget*
531     which affect the values stored in the registers array.  */
532
533  supply_gregset ((gdb_gregset_t *) &gregset);
534  supply_fpregset ((gdb_fpregset_t *) &fpregset);
535
536#if 0
537  /* FIXME: libthread_db doesn't seem to handle this right.  */
538  val = td_thr_getxregsize (&thandle, &xregsize);
539  if (val != TD_OK && val != TD_NOXREGS)
540    error ("sol_thread_fetch_registers: td_thr_getxregsize %s",
541	   td_err_string (val));
542
543  if (val == TD_OK)
544    {
545      xregset = alloca (xregsize);
546      val = td_thr_getxregs (&thandle, xregset);
547      if (val != TD_OK)
548	error ("sol_thread_fetch_registers: td_thr_getxregs %s",
549	       td_err_string (val));
550    }
551#endif
552}
553
554static void
555sol_thread_store_registers (int regnum)
556{
557  thread_t thread;
558  td_thrhandle_t thandle;
559  td_err_e val;
560  prgregset_t gregset;
561  prfpregset_t fpregset;
562#if 0
563  int xregsize;
564  caddr_t xregset;
565#endif
566
567  if (!is_thread (inferior_ptid))
568    {
569      /* It's an LWP; pass the request on to procfs.c.  */
570      procfs_ops.to_store_registers (regnum);
571      return;
572    }
573
574  /* Solaris thread: convert INFERIOR_PTID into a td_thrhandle_t.  */
575  thread = GET_THREAD (inferior_ptid);
576
577  val = p_td_ta_map_id2thr (main_ta, thread, &thandle);
578  if (val != TD_OK)
579    error ("sol_thread_store_registers: td_ta_map_id2thr %s",
580	   td_err_string (val));
581
582  if (regnum != -1)
583    {
584      /* Not writing all the registers.  */
585      char old_value[MAX_REGISTER_SIZE];
586
587      /* Save new register value.  */
588      regcache_raw_collect (current_regcache, regnum, old_value);
589
590      val = p_td_thr_getgregs (&thandle, gregset);
591      if (val != TD_OK)
592	error ("sol_thread_store_registers: td_thr_getgregs %s",
593	       td_err_string (val));
594      val = p_td_thr_getfpregs (&thandle, &fpregset);
595      if (val != TD_OK)
596	error ("sol_thread_store_registers: td_thr_getfpregs %s",
597	       td_err_string (val));
598
599      /* Restore new register value.  */
600      regcache_raw_supply (current_regcache, regnum, old_value);
601
602#if 0
603      /* FIXME: libthread_db doesn't seem to handle this right.  */
604      val = td_thr_getxregsize (&thandle, &xregsize);
605      if (val != TD_OK && val != TD_NOXREGS)
606	error ("sol_thread_store_registers: td_thr_getxregsize %s",
607	       td_err_string (val));
608
609      if (val == TD_OK)
610	{
611	  xregset = alloca (xregsize);
612	  val = td_thr_getxregs (&thandle, xregset);
613	  if (val != TD_OK)
614	    error ("sol_thread_store_registers: td_thr_getxregs %s",
615		   td_err_string (val));
616	}
617#endif
618    }
619
620  fill_gregset ((gdb_gregset_t *) &gregset, regnum);
621  fill_fpregset ((gdb_fpregset_t *) &fpregset, regnum);
622
623  val = p_td_thr_setgregs (&thandle, gregset);
624  if (val != TD_OK)
625    error ("sol_thread_store_registers: td_thr_setgregs %s",
626	   td_err_string (val));
627  val = p_td_thr_setfpregs (&thandle, &fpregset);
628  if (val != TD_OK)
629    error ("sol_thread_store_registers: td_thr_setfpregs %s",
630	   td_err_string (val));
631
632#if 0
633  /* FIXME: libthread_db doesn't seem to handle this right.  */
634  val = td_thr_getxregsize (&thandle, &xregsize);
635  if (val != TD_OK && val != TD_NOXREGS)
636    error ("sol_thread_store_registers: td_thr_getxregsize %s",
637	   td_err_string (val));
638
639  /* ??? Should probably do something about writing the xregs here,
640     but what are they?  */
641#endif
642}
643
644/* Get ready to modify the registers array.  On machines which store
645   individual registers, this doesn't need to do anything.  On
646   machines which store all the registers in one fell swoop, this
647   makes sure that registers contains all the registers from the
648   program being debugged.  */
649
650static void
651sol_thread_prepare_to_store (void)
652{
653  procfs_ops.to_prepare_to_store ();
654}
655
656/* Transfer LEN bytes between GDB address MYADDR and target address
657   MEMADDR.  If DOWRITE is non-zero, transfer them to the target,
658   otherwise transfer them from the target.  TARGET is unused.
659
660   Returns the number of bytes transferred.  */
661
662static int
663sol_thread_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int dowrite,
664			struct mem_attrib *attrib,
665			struct target_ops *target)
666{
667  int retval;
668  struct cleanup *old_chain;
669
670  old_chain = save_inferior_ptid ();
671
672  if (is_thread (inferior_ptid) || !target_thread_alive (inferior_ptid))
673    {
674      /* It's either a thread or an LWP that isn't alive.  Any live
675         LWP will do so use the first available.
676
677	 NOTE: We don't need to call switch_to_thread; we're just
678	 reading memory.  */
679      inferior_ptid = procfs_first_available ();
680    }
681
682  if (target_has_execution)
683    retval = procfs_ops.deprecated_xfer_memory (memaddr, myaddr, len,
684						dowrite, attrib, target);
685  else
686    retval = orig_core_ops.deprecated_xfer_memory (memaddr, myaddr, len,
687						   dowrite, attrib, target);
688
689  do_cleanups (old_chain);
690
691  return retval;
692}
693
694/* Perform partial transfers on OBJECT.  See target_read_partial and
695   target_write_partial for details of each variant.  One, and only
696   one, of readbuf or writebuf must be non-NULL.  */
697
698static LONGEST
699sol_thread_xfer_partial (struct target_ops *ops, enum target_object object,
700			  const char *annex, void *readbuf,
701			  const void *writebuf, ULONGEST offset, LONGEST len)
702{
703  int retval;
704  struct cleanup *old_chain;
705
706  old_chain = save_inferior_ptid ();
707
708  if (is_thread (inferior_ptid) || !target_thread_alive (inferior_ptid))
709    {
710      /* It's either a thread or an LWP that isn't alive.  Any live
711         LWP will do so use the first available.
712
713	 NOTE: We don't need to call switch_to_thread; we're just
714	 reading memory.  */
715      inferior_ptid = procfs_first_available ();
716    }
717
718  if (target_has_execution)
719    retval = procfs_ops.to_xfer_partial (ops, object, annex,
720					 readbuf, writebuf, offset, len);
721  else
722    retval = orig_core_ops.to_xfer_partial (ops, object, annex,
723					    readbuf, writebuf, offset, len);
724
725  do_cleanups (old_chain);
726
727  return retval;
728}
729
730/* Print status information about what we're accessing.  */
731
732static void
733sol_thread_files_info (struct target_ops *ignore)
734{
735  procfs_ops.to_files_info (ignore);
736}
737
738static void
739sol_thread_kill_inferior (void)
740{
741  procfs_ops.to_kill ();
742}
743
744static void
745sol_thread_notice_signals (ptid_t ptid)
746{
747  procfs_ops.to_notice_signals (pid_to_ptid (PIDGET (ptid)));
748}
749
750/* Fork an inferior process, and start debugging it with /proc.  */
751
752static void
753sol_thread_create_inferior (char *exec_file, char *allargs, char **env,
754			    int from_tty)
755{
756  procfs_ops.to_create_inferior (exec_file, allargs, env, from_tty);
757
758  if (sol_thread_active && !ptid_equal (inferior_ptid, null_ptid))
759    {
760      /* Save for xfer_memory.  */
761      main_ph.ptid = inferior_ptid;
762
763      push_target (&sol_thread_ops);
764
765      inferior_ptid = lwp_to_thread (inferior_ptid);
766      if (PIDGET (inferior_ptid) == -1)
767	inferior_ptid = main_ph.ptid;
768
769      if (!in_thread_list (inferior_ptid))
770	add_thread (inferior_ptid);
771    }
772}
773
774/* This routine is called whenever a new symbol table is read in, or
775   when all symbol tables are removed.  libthread_db can only be
776   initialized when it finds the right variables in libthread.so.
777   Since it's a shared library, those variables don't show up until
778   the library gets mapped and the symbol table is read in.
779
780   This new_objfile event is managed by a chained function pointer.
781   It is the callee's responsability to call the next client on the
782   chain.  */
783
784/* Saved pointer to previous owner of the new_objfile event. */
785static void (*target_new_objfile_chain) (struct objfile *);
786
787void
788sol_thread_new_objfile (struct objfile *objfile)
789{
790  td_err_e val;
791
792  if (!objfile)
793    {
794      sol_thread_active = 0;
795      goto quit;
796    }
797
798  /* Don't do anything if init failed to resolve the libthread_db
799     library.  */
800  if (!procfs_suppress_run)
801    goto quit;
802
803  /* Now, initialize libthread_db.  This needs to be done after the
804     shared libraries are located because it needs information from
805     the user's thread library.  */
806
807  val = p_td_init ();
808  if (val != TD_OK)
809    {
810      warning ("sol_thread_new_objfile: td_init: %s", td_err_string (val));
811      goto quit;
812    }
813
814  val = p_td_ta_new (&main_ph, &main_ta);
815  if (val == TD_NOLIBTHREAD)
816    goto quit;
817  else if (val != TD_OK)
818    {
819      warning ("sol_thread_new_objfile: td_ta_new: %s", td_err_string (val));
820      goto quit;
821    }
822
823  sol_thread_active = 1;
824
825quit:
826  /* Call predecessor on chain, if any.  */
827  if (target_new_objfile_chain)
828    target_new_objfile_chain (objfile);
829}
830
831/* Clean up after the inferior dies.  */
832
833static void
834sol_thread_mourn_inferior (void)
835{
836  unpush_target (&sol_thread_ops);
837  procfs_ops.to_mourn_inferior ();
838}
839
840/* Mark our target-struct as eligible for stray "run" and "attach"
841   commands.  */
842
843static int
844sol_thread_can_run (void)
845{
846  return procfs_suppress_run;
847}
848
849/*
850
851   LOCAL FUNCTION
852
853   sol_thread_alive     - test thread for "aliveness"
854
855   SYNOPSIS
856
857   static bool sol_thread_alive (ptid_t ptid);
858
859   DESCRIPTION
860
861   returns true if thread still active in inferior.
862
863 */
864
865/* Return true if PTID is still active in the inferior.  */
866
867static int
868sol_thread_alive (ptid_t ptid)
869{
870  if (is_thread (ptid))
871    {
872      /* It's a (user-level) thread.  */
873      td_err_e val;
874      td_thrhandle_t th;
875      int pid;
876
877      pid = GET_THREAD (ptid);
878      if ((val = p_td_ta_map_id2thr (main_ta, pid, &th)) != TD_OK)
879	return 0;		/* Thread not found.  */
880      if ((val = p_td_thr_validate (&th)) != TD_OK)
881	return 0;		/* Thread not valid.  */
882      return 1;			/* Known thread.  */
883    }
884  else
885    {
886      /* It's an LPW; pass the request on to procfs.  */
887      if (target_has_execution)
888	return procfs_ops.to_thread_alive (ptid);
889      else
890	return orig_core_ops.to_thread_alive (ptid);
891    }
892}
893
894static void
895sol_thread_stop (void)
896{
897  procfs_ops.to_stop ();
898}
899
900/* These routines implement the lower half of the thread_db interface,
901   i.e. the ps_* routines.  */
902
903/* Various versions of <proc_service.h> have slightly different
904   function prototypes.  In particular, we have
905
906   NEWER                        OLDER
907   struct ps_prochandle *       const struct ps_prochandle *
908   void*                        char*
909   const void*          	char*
910   int                  	size_t
911
912   Which one you have depends on the Solaris version and what patches
913   you've applied.  On the theory that there are only two major
914   variants, we have configure check the prototype of ps_pdwrite (),
915   and use that info to make appropriate typedefs here. */
916
917#ifdef PROC_SERVICE_IS_OLD
918typedef const struct ps_prochandle *gdb_ps_prochandle_t;
919typedef char *gdb_ps_read_buf_t;
920typedef char *gdb_ps_write_buf_t;
921typedef int gdb_ps_size_t;
922typedef paddr_t gdb_ps_addr_t;
923#else
924typedef struct ps_prochandle *gdb_ps_prochandle_t;
925typedef void *gdb_ps_read_buf_t;
926typedef const void *gdb_ps_write_buf_t;
927typedef size_t gdb_ps_size_t;
928typedef psaddr_t gdb_ps_addr_t;
929#endif
930
931/* The next four routines are called by libthread_db to tell us to
932   stop and stop a particular process or lwp.  Since GDB ensures that
933   these are all stopped by the time we call anything in thread_db,
934   these routines need to do nothing.  */
935
936/* Process stop.  */
937
938ps_err_e
939ps_pstop (gdb_ps_prochandle_t ph)
940{
941  return PS_OK;
942}
943
944/* Process continue.  */
945
946ps_err_e
947ps_pcontinue (gdb_ps_prochandle_t ph)
948{
949  return PS_OK;
950}
951
952/* LWP stop.  */
953
954ps_err_e
955ps_lstop (gdb_ps_prochandle_t ph, lwpid_t lwpid)
956{
957  return PS_OK;
958}
959
960/* LWP continue.  */
961
962ps_err_e
963ps_lcontinue (gdb_ps_prochandle_t ph, lwpid_t lwpid)
964{
965  return PS_OK;
966}
967
968/* Looks up the symbol LD_SYMBOL_NAME in the debugger's symbol table.  */
969
970ps_err_e
971ps_pglobal_lookup (gdb_ps_prochandle_t ph, const char *ld_object_name,
972		   const char *ld_symbol_name, gdb_ps_addr_t *ld_symbol_addr)
973{
974  struct minimal_symbol *ms;
975
976  ms = lookup_minimal_symbol (ld_symbol_name, NULL, NULL);
977  if (!ms)
978    return PS_NOSYM;
979
980  *ld_symbol_addr = SYMBOL_VALUE_ADDRESS (ms);
981  return PS_OK;
982}
983
984/* Common routine for reading and writing memory.  */
985
986static ps_err_e
987rw_common (int dowrite, const struct ps_prochandle *ph, gdb_ps_addr_t addr,
988	   char *buf, int size)
989{
990  struct cleanup *old_chain;
991
992  old_chain = save_inferior_ptid ();
993
994  if (is_thread (inferior_ptid) || !target_thread_alive (inferior_ptid))
995    {
996      /* It's either a thread or an LWP that isn't alive.  Any live
997         LWP will do so use the first available.
998
999	 NOTE: We don't need to call switch_to_thread; we're just
1000	 reading memory.  */
1001      inferior_ptid = procfs_first_available ();
1002    }
1003
1004#if defined (__sparcv9)
1005  /* For Sparc64 cross Sparc32, make sure the address has not been
1006     accidentally sign-extended (or whatever) to beyond 32 bits.  */
1007  if (bfd_get_arch_size (exec_bfd) == 32)
1008    addr &= 0xffffffff;
1009#endif
1010
1011  while (size > 0)
1012    {
1013      int cc;
1014
1015      /* FIXME: passing 0 as attrib argument.  */
1016      if (target_has_execution)
1017	cc = procfs_ops.deprecated_xfer_memory (addr, buf, size,
1018						dowrite, 0, &procfs_ops);
1019      else
1020	cc = orig_core_ops.deprecated_xfer_memory (addr, buf, size,
1021						   dowrite, 0, &core_ops);
1022
1023      if (cc < 0)
1024	{
1025	  if (dowrite == 0)
1026	    print_sys_errmsg ("rw_common (): read", errno);
1027	  else
1028	    print_sys_errmsg ("rw_common (): write", errno);
1029
1030	  do_cleanups (old_chain);
1031
1032	  return PS_ERR;
1033	}
1034      else if (cc == 0)
1035	{
1036	  if (dowrite == 0)
1037	    warning ("rw_common (): unable to read at addr 0x%lx",
1038		     (long) addr);
1039	  else
1040	    warning ("rw_common (): unable to write at addr 0x%lx",
1041		     (long) addr);
1042
1043	  do_cleanups (old_chain);
1044
1045	  return PS_ERR;
1046	}
1047
1048      size -= cc;
1049      buf += cc;
1050    }
1051
1052  do_cleanups (old_chain);
1053
1054  return PS_OK;
1055}
1056
1057/* Copies SIZE bytes from target process .data segment to debugger memory.  */
1058
1059ps_err_e
1060ps_pdread (gdb_ps_prochandle_t ph, gdb_ps_addr_t addr,
1061	   gdb_ps_read_buf_t buf, gdb_ps_size_t size)
1062{
1063  return rw_common (0, ph, addr, buf, size);
1064}
1065
1066/* Copies SIZE bytes from debugger memory .data segment to target process.  */
1067
1068ps_err_e
1069ps_pdwrite (gdb_ps_prochandle_t ph, gdb_ps_addr_t addr,
1070	    gdb_ps_write_buf_t buf, gdb_ps_size_t size)
1071{
1072  return rw_common (1, ph, addr, (char *) buf, size);
1073}
1074
1075/* Copies SIZE bytes from target process .text segment to debugger memory.  */
1076
1077ps_err_e
1078ps_ptread (gdb_ps_prochandle_t ph, gdb_ps_addr_t addr,
1079	   gdb_ps_read_buf_t buf, gdb_ps_size_t size)
1080{
1081  return rw_common (0, ph, addr, buf, size);
1082}
1083
1084/* Copies SIZE bytes from debugger memory .text segment to target process.  */
1085
1086ps_err_e
1087ps_ptwrite (gdb_ps_prochandle_t ph, gdb_ps_addr_t addr,
1088	    gdb_ps_write_buf_t buf, gdb_ps_size_t size)
1089{
1090  return rw_common (1, ph, addr, (char *) buf, size);
1091}
1092
1093/* Get general-purpose registers for LWP.  */
1094
1095ps_err_e
1096ps_lgetregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, prgregset_t gregset)
1097{
1098  struct cleanup *old_chain;
1099
1100  old_chain = save_inferior_ptid ();
1101
1102  inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid));
1103
1104  if (target_has_execution)
1105    procfs_ops.to_fetch_registers (-1);
1106  else
1107    orig_core_ops.to_fetch_registers (-1);
1108  fill_gregset ((gdb_gregset_t *) gregset, -1);
1109
1110  do_cleanups (old_chain);
1111
1112  return PS_OK;
1113}
1114
1115/* Set general-purpose registers for LWP.  */
1116
1117ps_err_e
1118ps_lsetregs (gdb_ps_prochandle_t ph, lwpid_t lwpid,
1119	     const prgregset_t gregset)
1120{
1121  struct cleanup *old_chain;
1122
1123  old_chain = save_inferior_ptid ();
1124
1125  inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid));
1126
1127  supply_gregset ((gdb_gregset_t *) gregset);
1128  if (target_has_execution)
1129    procfs_ops.to_store_registers (-1);
1130  else
1131    orig_core_ops.to_store_registers (-1);
1132
1133  do_cleanups (old_chain);
1134
1135  return PS_OK;
1136}
1137
1138/* Log a message (sends to gdb_stderr).  */
1139
1140void
1141ps_plog (const char *fmt, ...)
1142{
1143  va_list args;
1144
1145  va_start (args, fmt);
1146
1147  vfprintf_filtered (gdb_stderr, fmt, args);
1148}
1149
1150/* Get size of extra register set.  Currently a noop.  */
1151
1152ps_err_e
1153ps_lgetxregsize (gdb_ps_prochandle_t ph, lwpid_t lwpid, int *xregsize)
1154{
1155#if 0
1156  int lwp_fd;
1157  int regsize;
1158  ps_err_e val;
1159
1160  val = get_lwp_fd (ph, lwpid, &lwp_fd);
1161  if (val != PS_OK)
1162    return val;
1163
1164  if (ioctl (lwp_fd, PIOCGXREGSIZE, &regsize))
1165    {
1166      if (errno == EINVAL)
1167	return PS_NOFREGS;	/* XXX Wrong code, but this is the closest
1168				   thing in proc_service.h  */
1169
1170      print_sys_errmsg ("ps_lgetxregsize (): PIOCGXREGSIZE", errno);
1171      return PS_ERR;
1172    }
1173#endif
1174
1175  return PS_OK;
1176}
1177
1178/* Get extra register set.  Currently a noop.  */
1179
1180ps_err_e
1181ps_lgetxregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, caddr_t xregset)
1182{
1183#if 0
1184  int lwp_fd;
1185  ps_err_e val;
1186
1187  val = get_lwp_fd (ph, lwpid, &lwp_fd);
1188  if (val != PS_OK)
1189    return val;
1190
1191  if (ioctl (lwp_fd, PIOCGXREG, xregset))
1192    {
1193      print_sys_errmsg ("ps_lgetxregs (): PIOCGXREG", errno);
1194      return PS_ERR;
1195    }
1196#endif
1197
1198  return PS_OK;
1199}
1200
1201/* Set extra register set.  Currently a noop.  */
1202
1203ps_err_e
1204ps_lsetxregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, caddr_t xregset)
1205{
1206#if 0
1207  int lwp_fd;
1208  ps_err_e val;
1209
1210  val = get_lwp_fd (ph, lwpid, &lwp_fd);
1211  if (val != PS_OK)
1212    return val;
1213
1214  if (ioctl (lwp_fd, PIOCSXREG, xregset))
1215    {
1216      print_sys_errmsg ("ps_lsetxregs (): PIOCSXREG", errno);
1217      return PS_ERR;
1218    }
1219#endif
1220
1221  return PS_OK;
1222}
1223
1224/* Get floating-point registers for LWP.  */
1225
1226ps_err_e
1227ps_lgetfpregs (gdb_ps_prochandle_t ph, lwpid_t lwpid,
1228	       prfpregset_t *fpregset)
1229{
1230  struct cleanup *old_chain;
1231
1232  old_chain = save_inferior_ptid ();
1233
1234  inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid));
1235
1236  if (target_has_execution)
1237    procfs_ops.to_fetch_registers (-1);
1238  else
1239    orig_core_ops.to_fetch_registers (-1);
1240  fill_fpregset ((gdb_fpregset_t *) fpregset, -1);
1241
1242  do_cleanups (old_chain);
1243
1244  return PS_OK;
1245}
1246
1247/* Set floating-point regs for LWP */
1248
1249ps_err_e
1250ps_lsetfpregs (gdb_ps_prochandle_t ph, lwpid_t lwpid,
1251	       const prfpregset_t * fpregset)
1252{
1253  struct cleanup *old_chain;
1254
1255  old_chain = save_inferior_ptid ();
1256
1257  inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid));
1258
1259  supply_fpregset ((gdb_fpregset_t *) fpregset);
1260  if (target_has_execution)
1261    procfs_ops.to_store_registers (-1);
1262  else
1263    orig_core_ops.to_store_registers (-1);
1264
1265  do_cleanups (old_chain);
1266
1267  return PS_OK;
1268}
1269
1270#ifdef PR_MODEL_LP64
1271/* Identify process as 32-bit or 64-bit.  At the moment we're using
1272   BFD to do this.  There might be a more Solaris-specific
1273   (e.g. procfs) method, but this ought to work.  */
1274
1275ps_err_e
1276ps_pdmodel (gdb_ps_prochandle_t ph, int *data_model)
1277{
1278  if (exec_bfd == 0)
1279    *data_model = PR_MODEL_UNKNOWN;
1280  else if (bfd_get_arch_size (exec_bfd) == 32)
1281    *data_model = PR_MODEL_ILP32;
1282  else
1283    *data_model = PR_MODEL_LP64;
1284
1285  return PS_OK;
1286}
1287#endif /* PR_MODEL_LP64 */
1288
1289#ifdef TM_I386SOL2_H
1290
1291/* Reads the local descriptor table of a LWP.  */
1292
1293ps_err_e
1294ps_lgetLDT (gdb_ps_prochandle_t ph, lwpid_t lwpid,
1295	    struct ssd *pldt)
1296{
1297  /* NOTE: only used on Solaris, therefore OK to refer to procfs.c.  */
1298  extern struct ssd *procfs_find_LDT_entry (ptid_t);
1299  struct ssd *ret;
1300
1301  /* FIXME: can't I get the process ID from the prochandle or
1302     something?  */
1303
1304  if (PIDGET (inferior_ptid) <= 0 || lwpid <= 0)
1305    return PS_BADLID;
1306
1307  ret = procfs_find_LDT_entry (BUILD_LWP (lwpid, PIDGET (inferior_ptid)));
1308  if (ret)
1309    {
1310      memcpy (pldt, ret, sizeof (struct ssd));
1311      return PS_OK;
1312    }
1313  else
1314    /* LDT not found.  */
1315    return PS_ERR;
1316}
1317#endif /* TM_I386SOL2_H */
1318
1319
1320/* Convert PTID to printable form.  */
1321
1322char *
1323solaris_pid_to_str (ptid_t ptid)
1324{
1325  static char buf[100];
1326
1327  /* In case init failed to resolve the libthread_db library.  */
1328  if (!procfs_suppress_run)
1329    return procfs_pid_to_str (ptid);
1330
1331  if (is_thread (ptid))
1332    {
1333      ptid_t lwp;
1334
1335      lwp = thread_to_lwp (ptid, -2);
1336
1337      if (PIDGET (lwp) == -1)
1338	sprintf (buf, "Thread %ld (defunct)", GET_THREAD (ptid));
1339      else if (PIDGET (lwp) != -2)
1340	sprintf (buf, "Thread %ld (LWP %ld)",
1341		 GET_THREAD (ptid), GET_LWP (lwp));
1342      else
1343	sprintf (buf, "Thread %ld        ", GET_THREAD (ptid));
1344    }
1345  else if (GET_LWP (ptid) != 0)
1346    sprintf (buf, "LWP    %ld        ", GET_LWP (ptid));
1347  else
1348    sprintf (buf, "process %d    ", PIDGET (ptid));
1349
1350  return buf;
1351}
1352
1353
1354/* Worker bee for find_new_threads.  Callback function that gets
1355   called once per user-level thread (i.e. not for LWP's).  */
1356
1357static int
1358sol_find_new_threads_callback (const td_thrhandle_t *th, void *ignored)
1359{
1360  td_err_e retval;
1361  td_thrinfo_t ti;
1362  ptid_t ptid;
1363
1364  retval = p_td_thr_get_info (th, &ti);
1365  if (retval != TD_OK)
1366    return -1;
1367
1368  ptid = BUILD_THREAD (ti.ti_tid, PIDGET (inferior_ptid));
1369  if (!in_thread_list (ptid))
1370    add_thread (ptid);
1371
1372  return 0;
1373}
1374
1375static void
1376sol_find_new_threads (void)
1377{
1378  /* Don't do anything if init failed to resolve the libthread_db
1379     library.  */
1380  if (!procfs_suppress_run)
1381    return;
1382
1383  if (PIDGET (inferior_ptid) == -1)
1384    {
1385      printf_filtered ("No process.\n");
1386      return;
1387    }
1388
1389  /* First Find any new LWP's.  */
1390  procfs_ops.to_find_new_threads ();
1391
1392  /* Then find any new user-level threads.  */
1393  p_td_ta_thr_iter (main_ta, sol_find_new_threads_callback, (void *) 0,
1394		    TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
1395		    TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
1396}
1397
1398static void
1399sol_core_open (char *filename, int from_tty)
1400{
1401  orig_core_ops.to_open (filename, from_tty);
1402}
1403
1404static void
1405sol_core_close (int quitting)
1406{
1407  orig_core_ops.to_close (quitting);
1408}
1409
1410static void
1411sol_core_detach (char *args, int from_tty)
1412{
1413  unpush_target (&core_ops);
1414  orig_core_ops.to_detach (args, from_tty);
1415}
1416
1417static void
1418sol_core_files_info (struct target_ops *t)
1419{
1420  orig_core_ops.to_files_info (t);
1421}
1422
1423/* Worker bee for the "info sol-thread" command.  This is a callback
1424   function that gets called once for each Solaris user-level thread
1425   (i.e. not for LWPs) in the inferior.  Print anything interesting
1426   that we can think of.  */
1427
1428static int
1429info_cb (const td_thrhandle_t *th, void *s)
1430{
1431  td_err_e ret;
1432  td_thrinfo_t ti;
1433
1434  ret = p_td_thr_get_info (th, &ti);
1435  if (ret == TD_OK)
1436    {
1437      printf_filtered ("%s thread #%d, lwp %d, ",
1438		       ti.ti_type == TD_THR_SYSTEM ? "system" : "user  ",
1439		       ti.ti_tid, ti.ti_lid);
1440      switch (ti.ti_state)
1441	{
1442	default:
1443	case TD_THR_UNKNOWN:
1444	  printf_filtered ("<unknown state>");
1445	  break;
1446	case TD_THR_STOPPED:
1447	  printf_filtered ("(stopped)");
1448	  break;
1449	case TD_THR_RUN:
1450	  printf_filtered ("(run)    ");
1451	  break;
1452	case TD_THR_ACTIVE:
1453	  printf_filtered ("(active) ");
1454	  break;
1455	case TD_THR_ZOMBIE:
1456	  printf_filtered ("(zombie) ");
1457	  break;
1458	case TD_THR_SLEEP:
1459	  printf_filtered ("(asleep) ");
1460	  break;
1461	case TD_THR_STOPPED_ASLEEP:
1462	  printf_filtered ("(stopped asleep)");
1463	  break;
1464	}
1465      /* Print thr_create start function.  */
1466      if (ti.ti_startfunc != 0)
1467	{
1468	  struct minimal_symbol *msym;
1469	  msym = lookup_minimal_symbol_by_pc (ti.ti_startfunc);
1470	  if (msym)
1471	    printf_filtered ("   startfunc: %s\n",
1472			     DEPRECATED_SYMBOL_NAME (msym));
1473	  else
1474	    printf_filtered ("   startfunc: 0x%s\n", paddr (ti.ti_startfunc));
1475	}
1476
1477      /* If thread is asleep, print function that went to sleep.  */
1478      if (ti.ti_state == TD_THR_SLEEP)
1479	{
1480	  struct minimal_symbol *msym;
1481	  msym = lookup_minimal_symbol_by_pc (ti.ti_pc);
1482	  if (msym)
1483	    printf_filtered (" - Sleep func: %s\n",
1484			     DEPRECATED_SYMBOL_NAME (msym));
1485	  else
1486	    printf_filtered (" - Sleep func: 0x%s\n", paddr (ti.ti_startfunc));
1487	}
1488
1489      /* Wrap up line, if necessary.  */
1490      if (ti.ti_state != TD_THR_SLEEP && ti.ti_startfunc == 0)
1491	printf_filtered ("\n");	/* don't you hate counting newlines? */
1492    }
1493  else
1494    warning ("info sol-thread: failed to get info for thread.");
1495
1496  return 0;
1497}
1498
1499/* List some state about each Solaris user-level thread in the
1500   inferior.  */
1501
1502static void
1503info_solthreads (char *args, int from_tty)
1504{
1505  p_td_ta_thr_iter (main_ta, info_cb, args,
1506		    TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
1507		    TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
1508}
1509
1510static int
1511sol_find_memory_regions (int (*func) (CORE_ADDR, unsigned long,
1512				      int, int, int, void *),
1513			 void *data)
1514{
1515  return procfs_ops.to_find_memory_regions (func, data);
1516}
1517
1518static char *
1519sol_make_note_section (bfd *obfd, int *note_size)
1520{
1521  return procfs_ops.to_make_corefile_notes (obfd, note_size);
1522}
1523
1524static int
1525ignore (CORE_ADDR addr, char *contents)
1526{
1527  return 0;
1528}
1529
1530static void
1531init_sol_thread_ops (void)
1532{
1533  sol_thread_ops.to_shortname = "solaris-threads";
1534  sol_thread_ops.to_longname = "Solaris threads and pthread.";
1535  sol_thread_ops.to_doc = "Solaris threads and pthread support.";
1536  sol_thread_ops.to_open = sol_thread_open;
1537  sol_thread_ops.to_attach = sol_thread_attach;
1538  sol_thread_ops.to_detach = sol_thread_detach;
1539  sol_thread_ops.to_resume = sol_thread_resume;
1540  sol_thread_ops.to_wait = sol_thread_wait;
1541  sol_thread_ops.to_fetch_registers = sol_thread_fetch_registers;
1542  sol_thread_ops.to_store_registers = sol_thread_store_registers;
1543  sol_thread_ops.to_prepare_to_store = sol_thread_prepare_to_store;
1544  sol_thread_ops.deprecated_xfer_memory = sol_thread_xfer_memory;
1545  sol_thread_ops.to_xfer_partial = sol_thread_xfer_partial;
1546  sol_thread_ops.to_files_info = sol_thread_files_info;
1547  sol_thread_ops.to_insert_breakpoint = memory_insert_breakpoint;
1548  sol_thread_ops.to_remove_breakpoint = memory_remove_breakpoint;
1549  sol_thread_ops.to_terminal_init = terminal_init_inferior;
1550  sol_thread_ops.to_terminal_inferior = terminal_inferior;
1551  sol_thread_ops.to_terminal_ours_for_output = terminal_ours_for_output;
1552  sol_thread_ops.to_terminal_ours = terminal_ours;
1553  sol_thread_ops.to_terminal_save_ours = terminal_save_ours;
1554  sol_thread_ops.to_terminal_info = child_terminal_info;
1555  sol_thread_ops.to_kill = sol_thread_kill_inferior;
1556  sol_thread_ops.to_create_inferior = sol_thread_create_inferior;
1557  sol_thread_ops.to_mourn_inferior = sol_thread_mourn_inferior;
1558  sol_thread_ops.to_can_run = sol_thread_can_run;
1559  sol_thread_ops.to_notice_signals = sol_thread_notice_signals;
1560  sol_thread_ops.to_thread_alive = sol_thread_alive;
1561  sol_thread_ops.to_pid_to_str = solaris_pid_to_str;
1562  sol_thread_ops.to_find_new_threads = sol_find_new_threads;
1563  sol_thread_ops.to_stop = sol_thread_stop;
1564  sol_thread_ops.to_stratum = process_stratum;
1565  sol_thread_ops.to_has_all_memory = 1;
1566  sol_thread_ops.to_has_memory = 1;
1567  sol_thread_ops.to_has_stack = 1;
1568  sol_thread_ops.to_has_registers = 1;
1569  sol_thread_ops.to_has_execution = 1;
1570  sol_thread_ops.to_has_thread_control = tc_none;
1571  sol_thread_ops.to_find_memory_regions = sol_find_memory_regions;
1572  sol_thread_ops.to_make_corefile_notes = sol_make_note_section;
1573  sol_thread_ops.to_magic = OPS_MAGIC;
1574}
1575
1576static void
1577init_sol_core_ops (void)
1578{
1579  sol_core_ops.to_shortname = "solaris-core";
1580  sol_core_ops.to_longname = "Solaris core threads and pthread.";
1581  sol_core_ops.to_doc = "Solaris threads and pthread support for core files.";
1582  sol_core_ops.to_open = sol_core_open;
1583  sol_core_ops.to_close = sol_core_close;
1584  sol_core_ops.to_attach = sol_thread_attach;
1585  sol_core_ops.to_detach = sol_core_detach;
1586  sol_core_ops.to_fetch_registers = sol_thread_fetch_registers;
1587  sol_core_ops.deprecated_xfer_memory = sol_thread_xfer_memory;
1588  sol_core_ops.to_xfer_partial = sol_thread_xfer_partial;
1589  sol_core_ops.to_files_info = sol_core_files_info;
1590  sol_core_ops.to_insert_breakpoint = ignore;
1591  sol_core_ops.to_remove_breakpoint = ignore;
1592  sol_core_ops.to_create_inferior = sol_thread_create_inferior;
1593  sol_core_ops.to_stratum = core_stratum;
1594  sol_core_ops.to_has_memory = 1;
1595  sol_core_ops.to_has_stack = 1;
1596  sol_core_ops.to_has_registers = 1;
1597  sol_core_ops.to_has_thread_control = tc_none;
1598  sol_core_ops.to_thread_alive = sol_thread_alive;
1599  sol_core_ops.to_pid_to_str = solaris_pid_to_str;
1600  /* On Solaris/x86, when debugging a threaded core file from process
1601     <n>, the following causes "info threads" to produce "procfs:
1602     couldn't find pid <n> in procinfo list" where <n> is the pid of
1603     the process that produced the core file.  Disable it for now. */
1604#if 0
1605  sol_core_ops.to_find_new_threads = sol_find_new_threads;
1606#endif
1607  sol_core_ops.to_magic = OPS_MAGIC;
1608}
1609
1610/* We suppress the call to add_target of core_ops in corelow because
1611   if there are two targets in the stratum core_stratum,
1612   find_core_target won't know which one to return.  See corelow.c for
1613   an additonal comment on coreops_suppress_target.  */
1614int coreops_suppress_target = 1;
1615
1616void
1617_initialize_sol_thread (void)
1618{
1619  void *dlhandle;
1620
1621  init_sol_thread_ops ();
1622  init_sol_core_ops ();
1623
1624  dlhandle = dlopen ("libthread_db.so.1", RTLD_NOW);
1625  if (!dlhandle)
1626    goto die;
1627
1628#define resolve(X) \
1629  if (!(p_##X = dlsym (dlhandle, #X))) \
1630    goto die;
1631
1632  resolve (td_log);
1633  resolve (td_ta_new);
1634  resolve (td_ta_delete);
1635  resolve (td_init);
1636  resolve (td_ta_get_ph);
1637  resolve (td_ta_get_nthreads);
1638  resolve (td_ta_tsd_iter);
1639  resolve (td_ta_thr_iter);
1640  resolve (td_thr_validate);
1641  resolve (td_thr_tsd);
1642  resolve (td_thr_get_info);
1643  resolve (td_thr_getfpregs);
1644  resolve (td_thr_getxregsize);
1645  resolve (td_thr_getxregs);
1646  resolve (td_thr_sigsetmask);
1647  resolve (td_thr_setprio);
1648  resolve (td_thr_setsigpending);
1649  resolve (td_thr_setfpregs);
1650  resolve (td_thr_setxregs);
1651  resolve (td_ta_map_id2thr);
1652  resolve (td_ta_map_lwp2thr);
1653  resolve (td_thr_getgregs);
1654  resolve (td_thr_setgregs);
1655
1656  add_target (&sol_thread_ops);
1657
1658  procfs_suppress_run = 1;
1659
1660  add_cmd ("sol-threads", class_maintenance, info_solthreads,
1661	   "Show info on Solaris user threads.\n", &maintenanceinfolist);
1662
1663  memcpy (&orig_core_ops, &core_ops, sizeof (struct target_ops));
1664  memcpy (&core_ops, &sol_core_ops, sizeof (struct target_ops));
1665  add_target (&core_ops);
1666
1667  /* Hook into new_objfile notification.  */
1668  target_new_objfile_chain = deprecated_target_new_objfile_hook;
1669  deprecated_target_new_objfile_hook  = sol_thread_new_objfile;
1670  return;
1671
1672 die:
1673  fprintf_unfiltered (gdb_stderr, "\
1674[GDB will not be able to debug user-mode threads: %s]\n", dlerror ());
1675
1676  if (dlhandle)
1677    dlclose (dlhandle);
1678
1679  /* Allow the user to debug non-threaded core files.  */
1680  add_target (&core_ops);
1681
1682  return;
1683}
1684