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