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