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