xref: /openbsd/gnu/usr.bin/binutils/gdb/sol-thread.c (revision 78b63d65)
1 /* Low level interface for debugging Solaris threads for GDB, the GNU debugger.
2    Copyright 1996 Free Software Foundation, Inc.
3 
4 This file is part of GDB.
5 
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10 
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
19 
20 /* This module implements a sort of half target that sits between the
21    machine-independent parts of GDB and the /proc interface (procfs.c) to
22    provide access to the Solaris user-mode thread implementation.
23 
24    Solaris threads are true user-mode threads, which are invoked via the thr_*
25    and pthread_* (native and Posix respectivly) interfaces.  These are mostly
26    implemented in user-space, with all thread context kept in various
27    structures that live in the user's heap.  These should not be confused with
28    lightweight processes (LWPs), which are implemented by the kernel, and
29    scheduled without explicit intervention by the process.
30 
31    Just to confuse things a little, Solaris threads (both native and Posix) are
32    actually implemented using LWPs.  In general, there are going to be more
33    threads than LWPs.  There is no fixed correspondence between a thread and an
34    LWP.  When a thread wants to run, it gets scheduled onto the first available
35    LWP and can therefore migrate from one LWP to another as time goes on.  A
36    sleeping thread may not be associated with an LWP at all!
37 
38    To make it possible to mess with threads, Sun provides a library called
39    libthread_db.so.1 (not to be confused with libthread_db.so.0, which doesn't
40    have a published interface).  This interface has an upper part, which it
41    provides, and a lower part which I provide.  The upper part consists of the
42    td_* routines, which allow me to find all the threads, query their state,
43    etc...  The lower part consists of all of the ps_*, which are used by the
44    td_* routines to read/write memory, manipulate LWPs, lookup symbols, etc...
45    The ps_* routines actually do most of their work by calling functions in
46    procfs.c.  */
47 
48 #include "defs.h"
49 
50 /* Undefine gregset_t and fpregset_t to avoid conflict with defs in xm file. */
51 
52 #ifdef gregset_t
53 #undef gregset_t
54 #endif
55 
56 #ifdef fpregset_t
57 #undef fpregset_t
58 #endif
59 
60 #include <thread.h>
61 #include <proc_service.h>
62 #include <thread_db.h>
63 #include "gdbthread.h"
64 #include "target.h"
65 #include "inferior.h"
66 #include <fcntl.h>
67 #include <unistd.h>
68 #include <sys/stat.h>
69 #include <dlfcn.h>
70 
71 extern struct target_ops sol_thread_ops; /* Forward declaration */
72 
73 extern int procfs_suppress_run;
74 extern struct target_ops procfs_ops; /* target vector for procfs.c */
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 ((int 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 
118 #define THREAD_FLAG 0x80000000
119 #define is_thread(ARG) (((ARG) & THREAD_FLAG) != 0)
120 #define is_lwp(ARG) (((ARG) & THREAD_FLAG) == 0)
121 #define GET_LWP(LWP_ID) (TIDGET(LWP_ID))
122 #define GET_THREAD(THREAD_ID) (((THREAD_ID) >> 16) & 0x7fff)
123 #define BUILD_LWP(LWP_ID, PID) ((LWP_ID) << 16 | (PID))
124 #define BUILD_THREAD(THREAD_ID, PID) (THREAD_FLAG | BUILD_LWP (THREAD_ID, PID))
125 
126 /* Pointers to routines from lithread_db resolved by dlopen() */
127 
128 static void
129   (*p_td_log) (const int on_off);
130 static td_err_e
131   (*p_td_ta_new) (const struct ps_prochandle *ph_p, td_thragent_t **ta_pp);
132 static td_err_e
133   (*p_td_ta_delete) (td_thragent_t *ta_p);
134 static td_err_e
135   (*p_td_init) (void);
136 static td_err_e
137   (*p_td_ta_get_ph) (const td_thragent_t *ta_p, struct ps_prochandle **ph_pp);
138 static td_err_e
139   (*p_td_ta_get_nthreads) (const td_thragent_t *ta_p, int *nthread_p);
140 static td_err_e
141   (*p_td_ta_tsd_iter) (const td_thragent_t *ta_p, td_key_iter_f *cb, void *cbdata_p);
142 static td_err_e
143   (*p_td_ta_thr_iter) (const td_thragent_t *ta_p, td_thr_iter_f *cb, void *cbdata_p, td_thr_state_e state,
144 		       int ti_pri, sigset_t *ti_sigmask_p, unsigned ti_user_flags);
145 static td_err_e
146   (*p_td_thr_validate) (const td_thrhandle_t *th_p);
147 static td_err_e
148   (*p_td_thr_tsd) (const td_thrhandle_t *th_p, const thread_key_t key, void **data_pp);
149 static td_err_e
150   (*p_td_thr_get_info) (const td_thrhandle_t *th_p, td_thrinfo_t *ti_p);
151 static td_err_e
152   (*p_td_thr_getfpregs) (const td_thrhandle_t *th_p, prfpregset_t *fpregset);
153 static td_err_e
154   (*p_td_thr_getxregsize) (const td_thrhandle_t *th_p, int *xregsize);
155 static td_err_e
156   (*p_td_thr_getxregs) (const td_thrhandle_t *th_p, const caddr_t xregset);
157 static td_err_e
158   (*p_td_thr_sigsetmask) (const td_thrhandle_t *th_p, const sigset_t ti_sigmask);
159 static td_err_e
160   (*p_td_thr_setprio) (const td_thrhandle_t *th_p, const int ti_pri);
161 static td_err_e
162   (*p_td_thr_setsigpending) (const td_thrhandle_t *th_p, const uchar_t ti_pending_flag, const sigset_t ti_pending);
163 static td_err_e
164   (*p_td_thr_setfpregs) (const td_thrhandle_t *th_p, const prfpregset_t *fpregset);
165 static td_err_e
166   (*p_td_thr_setxregs) (const td_thrhandle_t *th_p, const caddr_t xregset);
167 static td_err_e
168   (*p_td_ta_map_id2thr) (const td_thragent_t *ta_p, thread_t tid, td_thrhandle_t *th_p);
169 static td_err_e
170   (*p_td_ta_map_lwp2thr) (const td_thragent_t *ta_p, lwpid_t lwpid, td_thrhandle_t *th_p);
171 static td_err_e
172   (*p_td_thr_getgregs) (const td_thrhandle_t *th_p, prgregset_t regset);
173 static td_err_e
174   (*p_td_thr_setgregs) (const td_thrhandle_t *th_p, const prgregset_t regset);
175 
176 /*
177 
178 LOCAL FUNCTION
179 
180 	td_err_string - Convert a thread_db error code to a string
181 
182 SYNOPSIS
183 
184 	char * td_err_string (errcode)
185 
186 DESCRIPTION
187 
188 	Return the thread_db error string associated with errcode.  If errcode
189 	is unknown, then return a message.
190 
191  */
192 
193 static char *
194 td_err_string (errcode)
195      td_err_e errcode;
196 {
197   static struct string_map
198     td_err_table[] = {
199       {TD_OK,		"generic \"call succeeded\""},
200       {TD_ERR,		"generic error."},
201       {TD_NOTHR,	"no thread can be found to satisfy query"},
202       {TD_NOSV,		"no synch. variable can be found to satisfy query"},
203       {TD_NOLWP,	"no lwp can be found to satisfy query"},
204       {TD_BADPH,	"invalid process handle"},
205       {TD_BADTH,	"invalid thread handle"},
206       {TD_BADSH,	"invalid synchronization handle"},
207       {TD_BADTA,	"invalid thread agent"},
208       {TD_BADKEY,	"invalid key"},
209       {TD_NOMSG,	"td_thr_event_getmsg() called when there was no message"},
210       {TD_NOFPREGS,	"FPU register set not available for given thread"},
211       {TD_NOLIBTHREAD,	"application not linked with libthread"},
212       {TD_NOEVENT,	"requested event is not supported"},
213       {TD_NOCAPAB,	"capability not available"},
214       {TD_DBERR,	"Debugger service failed"},
215       {TD_NOAPLIC,	"Operation not applicable to"},
216       {TD_NOTSD,	"No thread specific data for this thread"},
217       {TD_MALLOC,	"Malloc failed"},
218       {TD_PARTIALREG,	"Only part of register set was writen/read"},
219       {TD_NOXREGS,	"X register set not available for given thread"}
220     };
221   const int td_err_size = sizeof td_err_table / sizeof (struct string_map);
222   int i;
223   static char buf[50];
224 
225   for (i = 0; i < td_err_size; i++)
226     if (td_err_table[i].num == errcode)
227       return td_err_table[i].str;
228 
229   sprintf (buf, "Unknown thread_db error code: %d", errcode);
230 
231   return buf;
232 }
233 
234 /*
235 
236 LOCAL FUNCTION
237 
238 	td_state_string - Convert a thread_db state code to a string
239 
240 SYNOPSIS
241 
242 	char * td_state_string (statecode)
243 
244 DESCRIPTION
245 
246 	Return the thread_db state string associated with statecode.  If
247 	statecode is unknown, then return a message.
248 
249  */
250 
251 static char *
252 td_state_string (statecode)
253      td_thr_state_e statecode;
254 {
255   static struct string_map
256     td_thr_state_table[] = {
257       {TD_THR_ANY_STATE, "any state"},
258       {TD_THR_UNKNOWN,	"unknown"},
259       {TD_THR_STOPPED,	"stopped"},
260       {TD_THR_RUN,	"run"},
261       {TD_THR_ACTIVE,	"active"},
262       {TD_THR_ZOMBIE,	"zombie"},
263       {TD_THR_SLEEP,	"sleep"},
264       {TD_THR_STOPPED_ASLEEP, "stopped asleep"}
265     };
266   const int td_thr_state_table_size = sizeof td_thr_state_table / sizeof (struct string_map);
267   int i;
268   static char buf[50];
269 
270   for (i = 0; i < td_thr_state_table_size; i++)
271     if (td_thr_state_table[i].num == statecode)
272       return td_thr_state_table[i].str;
273 
274   sprintf (buf, "Unknown thread_db state code: %d", statecode);
275 
276   return buf;
277 }
278 
279 /*
280 
281 LOCAL FUNCTION
282 
283 	thread_to_lwp - Convert a Posix or Solaris thread id to a LWP id.
284 
285 SYNOPSIS
286 
287 	int thread_to_lwp (thread_id, default_lwp)
288 
289 DESCRIPTION
290 
291 	This function converts a Posix or Solaris thread id to a lightweight
292 	process id.  If thread_id is non-existent, that's an error.  If it's
293 	an inactive thread, then we return default_lwp.
294 
295 NOTES
296 
297 	This function probably shouldn't call error()...
298 
299  */
300 
301 static int
302 thread_to_lwp (thread_id, default_lwp)
303      int thread_id;
304      int default_lwp;
305 {
306   td_thrinfo_t ti;
307   td_thrhandle_t th;
308   td_err_e val;
309   int pid;
310   int lwp;
311 
312   if (is_lwp (thread_id))
313     return thread_id;			/* It's already an LWP id */
314 
315   /* It's a thread.  Convert to lwp */
316 
317   pid = PIDGET (thread_id);
318   thread_id = GET_THREAD(thread_id);
319 
320   val = p_td_ta_map_id2thr (main_ta, thread_id, &th);
321   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 
326   if (val != TD_OK)
327     error ("thread_to_lwp: td_thr_get_info: %s", td_err_string (val));
328 
329   if (ti.ti_state != TD_THR_ACTIVE)
330     {
331       if (default_lwp != -1)
332 	return default_lwp;
333       error ("thread_to_lwp: thread state not active: %s",
334 	     td_state_string (ti.ti_state));
335     }
336 
337   lwp = BUILD_LWP (ti.ti_lid, pid);
338 
339   return lwp;
340 }
341 
342 /*
343 
344 LOCAL FUNCTION
345 
346 	lwp_to_thread - Convert a LWP id to a Posix or Solaris thread id.
347 
348 SYNOPSIS
349 
350 	int lwp_to_thread (lwp_id)
351 
352 DESCRIPTION
353 
354 	This function converts a lightweight process id to a Posix or Solaris
355 	thread id.  If thread_id is non-existent, that's an error.
356 
357 NOTES
358 
359 	This function probably shouldn't call error()...
360 
361  */
362 
363 static int
364 lwp_to_thread (lwp)
365      int lwp;
366 {
367   td_thrinfo_t ti;
368   td_thrhandle_t th;
369   td_err_e val;
370   int pid;
371   int thread_id;
372 
373   if (is_thread (lwp))
374     return lwp;			/* It's already a thread id */
375 
376   /* It's an lwp.  Convert it to a thread id.  */
377 
378   pid = PIDGET (lwp);
379   lwp = GET_LWP (lwp);
380 
381   val = p_td_ta_map_lwp2thr (main_ta, lwp, &th);
382   if (val != TD_OK)
383     error ("lwp_to_thread: td_thr_get_info: %s.", td_err_string (val));
384 
385   val = p_td_thr_get_info (&th, &ti);
386 
387   if (val != TD_OK)
388     error ("lwp_to_thread: td_thr_get_info: %s.", td_err_string (val));
389 
390   thread_id = BUILD_THREAD (ti.ti_tid, pid);
391 
392   return thread_id;
393 }
394 
395 /*
396 
397 LOCAL FUNCTION
398 
399 	save_inferior_pid - Save inferior_pid on the cleanup list
400 	restore_inferior_pid - Restore inferior_pid from the cleanup list
401 
402 SYNOPSIS
403 
404 	struct cleanup *save_inferior_pid ()
405 	void restore_inferior_pid (int pid)
406 
407 DESCRIPTION
408 
409 	These two functions act in unison to restore inferior_pid in
410 	case of an error.
411 
412 NOTES
413 
414 	inferior_pid is a global variable that needs to be changed by many of
415 	these routines before calling functions in procfs.c.  In order to
416 	guarantee that inferior_pid gets restored (in case of errors), you
417 	need to call save_inferior_pid before changing it.  At the end of the
418 	function, you should invoke do_cleanups to restore it.
419 
420  */
421 
422 
423 static struct cleanup *
424 save_inferior_pid ()
425 {
426   return make_cleanup (restore_inferior_pid, inferior_pid);
427 }
428 
429 static void
430 restore_inferior_pid (pid)
431      int pid;
432 {
433   inferior_pid = pid;
434 }
435 
436 
437 /* Most target vector functions from here on actually just pass through to
438    procfs.c, as they don't need to do anything specific for threads.  */
439 
440 
441 /* ARGSUSED */
442 static void
443 sol_thread_open (arg, from_tty)
444      char *arg;
445      int from_tty;
446 {
447   procfs_ops.to_open (arg, from_tty);
448 }
449 
450 /* Attach to process PID, then initialize for debugging it
451    and wait for the trace-trap that results from attaching.  */
452 
453 static void
454 sol_thread_attach (args, from_tty)
455      char *args;
456      int from_tty;
457 {
458   procfs_ops.to_attach (args, from_tty);
459 
460   /* XXX - might want to iterate over all the threads and register them. */
461 }
462 
463 /* Take a program previously attached to and detaches it.
464    The program resumes execution and will no longer stop
465    on signals, etc.  We'd better not have left any breakpoints
466    in the program or it'll die when it hits one.  For this
467    to work, it may be necessary for the process to have been
468    previously attached.  It *might* work if the program was
469    started via the normal ptrace (PTRACE_TRACEME).  */
470 
471 static void
472 sol_thread_detach (args, from_tty)
473      char *args;
474      int from_tty;
475 {
476   procfs_ops.to_detach (args, from_tty);
477 }
478 
479 /* Resume execution of process PID.  If STEP is nozero, then
480    just single step it.  If SIGNAL is nonzero, restart it with that
481    signal activated.  We may have to convert pid from a thread-id to an LWP id
482    for procfs.  */
483 
484 static void
485 sol_thread_resume (pid, step, signo)
486      int pid;
487      int step;
488      enum target_signal signo;
489 {
490   struct cleanup *old_chain;
491 
492   old_chain = save_inferior_pid ();
493 
494   inferior_pid = thread_to_lwp (inferior_pid, main_ph.pid);
495 
496   if (pid != -1)
497     {
498       pid = thread_to_lwp (pid, -2);
499       if (pid == -2)		/* Inactive thread */
500 	error ("This version of Solaris can't start inactive threads.");
501     }
502 
503   procfs_ops.to_resume (pid, step, signo);
504 
505   do_cleanups (old_chain);
506 }
507 
508 /* Wait for any threads to stop.  We may have to convert PID from a thread id
509    to a LWP id, and vice versa on the way out.  */
510 
511 static int
512 sol_thread_wait (pid, ourstatus)
513      int pid;
514      struct target_waitstatus *ourstatus;
515 {
516   int rtnval;
517   int save_pid;
518   struct cleanup *old_chain;
519 
520   save_pid = inferior_pid;
521   old_chain = save_inferior_pid ();
522 
523   inferior_pid = thread_to_lwp (inferior_pid, main_ph.pid);
524 
525   if (pid != -1)
526     pid = thread_to_lwp (pid, -1);
527 
528   rtnval = procfs_ops.to_wait (pid, ourstatus);
529 
530   if (rtnval != save_pid
531       && !in_thread_list (rtnval))
532     {
533       fprintf_unfiltered (gdb_stderr, "[New %s]\n",
534 			  target_pid_to_str (rtnval));
535       add_thread (rtnval);
536     }
537 
538   /* During process initialization, we may get here without the thread package
539      being initialized, since that can only happen after we've found the shared
540      libs.  */
541 
542   /* Map the LWP of interest back to the appropriate thread ID */
543 
544   rtnval = lwp_to_thread (rtnval);
545 
546   do_cleanups (old_chain);
547 
548   return rtnval;
549 }
550 
551 static void
552 sol_thread_fetch_registers (regno)
553      int regno;
554 {
555   thread_t thread;
556   td_thrhandle_t thandle;
557   td_err_e val;
558   prgregset_t gregset;
559   prfpregset_t fpregset;
560 #if 0
561   int xregsize;
562   caddr_t xregset;
563 #endif
564 
565   /* Convert inferior_pid into a td_thrhandle_t */
566 
567   thread = GET_THREAD (inferior_pid);
568 
569   if (thread == 0)
570     error ("sol_thread_fetch_registers:  thread == 0");
571 
572   val = p_td_ta_map_id2thr (main_ta, thread, &thandle);
573   if (val != TD_OK)
574     error ("sol_thread_fetch_registers: td_ta_map_id2thr: %s",
575 	   td_err_string (val));
576 
577   /* Get the integer regs */
578 
579   val = p_td_thr_getgregs (&thandle, gregset);
580   if (val != TD_OK
581       && val != TD_PARTIALREG)
582     error ("sol_thread_fetch_registers: td_thr_getgregs %s",
583 	   td_err_string (val));
584 
585   /* For the sparc, TD_PARTIALREG means that only i0->i7, l0->l7, pc and sp
586      are saved (by a thread context switch).  */
587 
588   /* And, now the fp regs */
589 
590   val = p_td_thr_getfpregs (&thandle, &fpregset);
591   if (val != TD_OK
592       && val != TD_NOFPREGS)
593     error ("sol_thread_fetch_registers: td_thr_getfpregs %s",
594 	   td_err_string (val));
595 
596 /* Note that we must call supply_{g fp}regset *after* calling the td routines
597    because the td routines call ps_lget* which affect the values stored in the
598    registers array.  */
599 
600   supply_gregset (gregset);
601   supply_fpregset (fpregset);
602 
603 #if 0
604 /* thread_db doesn't seem to handle this right */
605   val = td_thr_getxregsize (&thandle, &xregsize);
606   if (val != TD_OK && val != TD_NOXREGS)
607     error ("sol_thread_fetch_registers: td_thr_getxregsize %s",
608 	   td_err_string (val));
609 
610   if (val == TD_OK)
611     {
612       xregset = alloca (xregsize);
613       val = td_thr_getxregs (&thandle, xregset);
614       if (val != TD_OK)
615 	error ("sol_thread_fetch_registers: td_thr_getxregs %s",
616 	       td_err_string (val));
617     }
618 #endif
619 }
620 
621 static void
622 sol_thread_store_registers (regno)
623      int regno;
624 {
625   thread_t thread;
626   td_thrhandle_t thandle;
627   td_err_e val;
628   prgregset_t regset;
629   prfpregset_t fpregset;
630 #if 0
631   int xregsize;
632   caddr_t xregset;
633 #endif
634 
635   /* Convert inferior_pid into a td_thrhandle_t */
636 
637   thread = GET_THREAD (inferior_pid);
638 
639   val = p_td_ta_map_id2thr (main_ta, thread, &thandle);
640   if (val != TD_OK)
641     error ("sol_thread_store_registers: td_ta_map_id2thr %s",
642 	   td_err_string (val));
643 
644   if (regno != -1)
645     {				/* Not writing all the regs */
646       val = p_td_thr_getgregs (&thandle, regset);
647       if (val != TD_OK)
648 	error ("sol_thread_store_registers: td_thr_getgregs %s",
649 	       td_err_string (val));
650       val = p_td_thr_getfpregs (&thandle, &fpregset);
651       if (val != TD_OK)
652 	error ("sol_thread_store_registers: td_thr_getfpregs %s",
653 	       td_err_string (val));
654 
655 #if 0
656 /* thread_db doesn't seem to handle this right */
657       val = td_thr_getxregsize (&thandle, &xregsize);
658       if (val != TD_OK && val != TD_NOXREGS)
659 	error ("sol_thread_store_registers: td_thr_getxregsize %s",
660 	       td_err_string (val));
661 
662       if (val == TD_OK)
663 	{
664 	  xregset = alloca (xregsize);
665 	  val = td_thr_getxregs (&thandle, xregset);
666 	  if (val != TD_OK)
667 	    error ("sol_thread_store_registers: td_thr_getxregs %s",
668 		   td_err_string (val));
669 	}
670 #endif
671     }
672 
673   fill_gregset (regset, regno);
674   fill_fpregset (fpregset, regno);
675 
676   val = p_td_thr_setgregs (&thandle, regset);
677   if (val != TD_OK)
678     error ("sol_thread_store_registers: td_thr_setgregs %s",
679 	   td_err_string (val));
680   val = p_td_thr_setfpregs (&thandle, &fpregset);
681   if (val != TD_OK)
682     error ("sol_thread_store_registers: td_thr_setfpregs %s",
683 	   td_err_string (val));
684 
685 #if 0
686 /* thread_db doesn't seem to handle this right */
687   val = td_thr_getxregsize (&thandle, &xregsize);
688   if (val != TD_OK && val != TD_NOXREGS)
689     error ("sol_thread_store_registers: td_thr_getxregsize %s",
690 	   td_err_string (val));
691 
692   /* Should probably do something about writing the xregs here, but what are
693      they? */
694 #endif
695 }
696 
697 /* Get ready to modify the registers array.  On machines which store
698    individual registers, this doesn't need to do anything.  On machines
699    which store all the registers in one fell swoop, this makes sure
700    that registers contains all the registers from the program being
701    debugged.  */
702 
703 static void
704 sol_thread_prepare_to_store ()
705 {
706   procfs_ops.to_prepare_to_store ();
707 }
708 
709 static int
710 sol_thread_xfer_memory (memaddr, myaddr, len, dowrite, target)
711      CORE_ADDR memaddr;
712      char *myaddr;
713      int len;
714      int dowrite;
715      struct target_ops *target; /* ignored */
716 {
717   int retval;
718   struct cleanup *old_chain;
719 
720   old_chain = save_inferior_pid ();
721 
722   if (is_thread (inferior_pid))
723     inferior_pid = main_ph.pid;	/* It's a thread.  Convert to lwp */
724 
725   retval = procfs_ops.to_xfer_memory (memaddr, myaddr, len, dowrite, target);
726 
727   do_cleanups (old_chain);
728 
729   return retval;
730 }
731 
732 /* Print status information about what we're accessing.  */
733 
734 static void
735 sol_thread_files_info (ignore)
736      struct target_ops *ignore;
737 {
738   procfs_ops.to_files_info (ignore);
739 }
740 
741 static void
742 sol_thread_kill_inferior ()
743 {
744   procfs_ops.to_kill ();
745 }
746 
747 static void
748 sol_thread_notice_signals (pid)
749      int pid;
750 {
751   procfs_ops.to_notice_signals (pid);
752 }
753 
754 void target_new_objfile PARAMS ((struct objfile *objfile));
755 
756 /* Fork an inferior process, and start debugging it with /proc.  */
757 
758 static void
759 sol_thread_create_inferior (exec_file, allargs, env)
760      char *exec_file;
761      char *allargs;
762      char **env;
763 {
764   procfs_ops.to_create_inferior (exec_file, allargs, env);
765 
766   if (sol_thread_active)
767     {
768       main_ph.pid = inferior_pid; /* Save for xfer_memory */
769 
770       push_target (&sol_thread_ops);
771 
772       inferior_pid = lwp_to_thread (inferior_pid);
773 
774       add_thread (inferior_pid);
775     }
776 }
777 
778 /* This routine is called whenever a new symbol table is read in, or when all
779    symbol tables are removed.  libthread_db can only be initialized when it
780    finds the right variables in libthread.so.  Since it's a shared library,
781    those variables don't show up until the library gets mapped and the symbol
782    table is read in.  */
783 
784 void
785 sol_thread_new_objfile (objfile)
786      struct objfile *objfile;
787 {
788   td_err_e val;
789 
790   if (!objfile)
791     {
792       sol_thread_active = 0;
793 
794       return;
795     }
796 
797   /* Now, initialize the thread debugging library.  This needs to be done after
798      the shared libraries are located because it needs information from the
799      user's thread library.  */
800 
801   val = p_td_init ();
802   if (val != TD_OK)
803     error ("target_new_objfile: td_init: %s", td_err_string (val));
804 
805   val = p_td_ta_new (&main_ph, &main_ta);
806   if (val == TD_NOLIBTHREAD)
807     return;
808   else if (val != TD_OK)
809     error ("target_new_objfile: td_ta_new: %s", td_err_string (val));
810 
811   sol_thread_active = 1;
812 }
813 
814 /* Clean up after the inferior dies.  */
815 
816 static void
817 sol_thread_mourn_inferior ()
818 {
819   procfs_ops.to_mourn_inferior ();
820 }
821 
822 /* Mark our target-struct as eligible for stray "run" and "attach" commands.  */
823 
824 static int
825 sol_thread_can_run ()
826 {
827   return procfs_suppress_run;
828 }
829 
830 static int
831 sol_thread_alive (pid)
832      int pid;
833 {
834   return 1;
835 }
836 
837 static void
838 sol_thread_stop ()
839 {
840   procfs_ops.to_stop ();
841 }
842 
843 /* These routines implement the lower half of the thread_db interface.  Ie: the
844    ps_* routines.  */
845 
846 /* The next four routines are called by thread_db to tell us to stop and stop
847    a particular process or lwp.  Since GDB ensures that these are all stopped
848    by the time we call anything in thread_db, these routines need to do
849    nothing.  */
850 
851 ps_err_e
852 ps_pstop (const struct ps_prochandle *ph)
853 {
854   return PS_OK;
855 }
856 
857 ps_err_e
858 ps_pcontinue (const struct ps_prochandle *ph)
859 {
860   return PS_OK;
861 }
862 
863 ps_err_e
864 ps_lstop (const struct ps_prochandle *ph, lwpid_t lwpid)
865 {
866   return PS_OK;
867 }
868 
869 ps_err_e
870 ps_lcontinue (const struct ps_prochandle *ph, lwpid_t lwpid)
871 {
872   return PS_OK;
873 }
874 
875 ps_err_e
876 ps_pglobal_lookup (const struct ps_prochandle *ph, const char *ld_object_name,
877 		   const char *ld_symbol_name, paddr_t *ld_symbol_addr)
878 {
879   struct minimal_symbol *ms;
880 
881   ms = lookup_minimal_symbol (ld_symbol_name, NULL, NULL);
882 
883   if (!ms)
884     return PS_NOSYM;
885 
886   *ld_symbol_addr = SYMBOL_VALUE_ADDRESS (ms);
887 
888   return PS_OK;
889 }
890 
891 /* Common routine for reading and writing memory.  */
892 
893 static ps_err_e
894 rw_common (int dowrite, const struct ps_prochandle *ph, paddr_t addr,
895 	   char *buf, int size)
896 {
897   struct cleanup *old_chain;
898 
899   old_chain = save_inferior_pid ();
900 
901   if (is_thread (inferior_pid))
902     inferior_pid = main_ph.pid;	/* It's a thread.  Convert to lwp */
903 
904   while (size > 0)
905     {
906       int cc;
907 
908       cc = procfs_ops.to_xfer_memory (addr, buf, size, dowrite, &procfs_ops);
909 
910       if (cc < 0)
911 	{
912 	  if (dowrite == 0)
913 	    print_sys_errmsg ("ps_pdread (): read", errno);
914 	  else
915 	    print_sys_errmsg ("ps_pdread (): write", errno);
916 
917 	  do_cleanups (old_chain);
918 
919 	  return PS_ERR;
920 	}
921       size -= cc;
922       buf += cc;
923     }
924 
925   do_cleanups (old_chain);
926 
927   return PS_OK;
928 }
929 
930 ps_err_e
931 ps_pdread (const struct ps_prochandle *ph, paddr_t addr, char *buf, int size)
932 {
933   return rw_common (0, ph, addr, buf, size);
934 }
935 
936 ps_err_e
937 ps_pdwrite (const struct ps_prochandle *ph, paddr_t addr, char *buf, int size)
938 {
939   return rw_common (1, ph, addr, buf, size);
940 }
941 
942 ps_err_e
943 ps_ptread (const struct ps_prochandle *ph, paddr_t addr, char *buf, int size)
944 {
945   return rw_common (0, ph, addr, buf, size);
946 }
947 
948 ps_err_e
949 ps_ptwrite (const struct ps_prochandle *ph, paddr_t addr, char *buf, int size)
950 {
951   return rw_common (1, ph, addr, buf, size);
952 }
953 
954 /* Get integer regs */
955 
956 ps_err_e
957 ps_lgetregs (const struct ps_prochandle *ph, lwpid_t lwpid,
958 	     prgregset_t gregset)
959 {
960   struct cleanup *old_chain;
961 
962   old_chain = save_inferior_pid ();
963 
964   inferior_pid = BUILD_LWP (lwpid, PIDGET (inferior_pid));
965 
966   procfs_ops.to_fetch_registers (-1);
967   fill_gregset (gregset, -1);
968 
969   do_cleanups (old_chain);
970 
971   return PS_OK;
972 }
973 
974 /* Set integer regs */
975 
976 ps_err_e
977 ps_lsetregs (const struct ps_prochandle *ph, lwpid_t lwpid,
978 	     const prgregset_t gregset)
979 {
980   struct cleanup *old_chain;
981 
982   old_chain = save_inferior_pid ();
983 
984   inferior_pid = BUILD_LWP (lwpid, PIDGET (inferior_pid));
985 
986   supply_gregset (gregset);
987   procfs_ops.to_store_registers (-1);
988 
989   do_cleanups (old_chain);
990 
991   return PS_OK;
992 }
993 
994 void
995 ps_plog (const char *fmt, ...)
996 {
997   va_list args;
998 
999   va_start (args, fmt);
1000 
1001   vfprintf_filtered (gdb_stderr, fmt, args);
1002 }
1003 
1004 /* Get size of extra register set.  Currently a noop.  */
1005 
1006 ps_err_e
1007 ps_lgetxregsize (const struct ps_prochandle *ph, lwpid_t lwpid, int *xregsize)
1008 {
1009 #if 0
1010   int lwp_fd;
1011   int regsize;
1012   ps_err_e val;
1013 
1014   val = get_lwp_fd (ph, lwpid, &lwp_fd);
1015   if (val != PS_OK)
1016     return val;
1017 
1018   if (ioctl (lwp_fd, PIOCGXREGSIZE, &regsize))
1019     {
1020       if (errno == EINVAL)
1021 	return PS_NOFREGS;	/* XXX Wrong code, but this is the closest
1022 				   thing in proc_service.h  */
1023 
1024       print_sys_errmsg ("ps_lgetxregsize (): PIOCGXREGSIZE", errno);
1025       return PS_ERR;
1026     }
1027 #endif
1028 
1029   return PS_OK;
1030 }
1031 
1032 /* Get extra register set.  Currently a noop.  */
1033 
1034 ps_err_e
1035 ps_lgetxregs (const struct ps_prochandle *ph, lwpid_t lwpid, caddr_t xregset)
1036 {
1037 #if 0
1038   int lwp_fd;
1039   ps_err_e val;
1040 
1041   val = get_lwp_fd (ph, lwpid, &lwp_fd);
1042   if (val != PS_OK)
1043     return val;
1044 
1045   if (ioctl (lwp_fd, PIOCGXREG, xregset))
1046     {
1047       print_sys_errmsg ("ps_lgetxregs (): PIOCGXREG", errno);
1048       return PS_ERR;
1049     }
1050 #endif
1051 
1052   return PS_OK;
1053 }
1054 
1055 /* Set extra register set.  Currently a noop.  */
1056 
1057 ps_err_e
1058 ps_lsetxregs (const struct ps_prochandle *ph, lwpid_t lwpid, caddr_t xregset)
1059 {
1060 #if 0
1061   int lwp_fd;
1062   ps_err_e val;
1063 
1064   val = get_lwp_fd (ph, lwpid, &lwp_fd);
1065   if (val != PS_OK)
1066     return val;
1067 
1068   if (ioctl (lwp_fd, PIOCSXREG, xregset))
1069     {
1070       print_sys_errmsg ("ps_lsetxregs (): PIOCSXREG", errno);
1071       return PS_ERR;
1072     }
1073 #endif
1074 
1075   return PS_OK;
1076 }
1077 
1078 /* Get floating-point regs.  */
1079 
1080 ps_err_e
1081 ps_lgetfpregs (const struct ps_prochandle *ph, lwpid_t lwpid,
1082 	       prfpregset_t *fpregset)
1083 {
1084   struct cleanup *old_chain;
1085 
1086   old_chain = save_inferior_pid ();
1087 
1088   inferior_pid = BUILD_LWP (lwpid, PIDGET (inferior_pid));
1089 
1090   procfs_ops.to_fetch_registers (-1);
1091   fill_fpregset (*fpregset, -1);
1092 
1093   do_cleanups (old_chain);
1094 
1095   return PS_OK;
1096 }
1097 
1098 /* Set floating-point regs.  */
1099 
1100 ps_err_e
1101 ps_lsetfpregs (const struct ps_prochandle *ph, lwpid_t lwpid,
1102 	       const prfpregset_t *fpregset)
1103 {
1104   struct cleanup *old_chain;
1105 
1106   old_chain = save_inferior_pid ();
1107 
1108   inferior_pid = BUILD_LWP (lwpid, PIDGET (inferior_pid));
1109 
1110   supply_fpregset (*fpregset);
1111   procfs_ops.to_store_registers (-1);
1112 
1113   do_cleanups (old_chain);
1114 
1115   return PS_OK;
1116 }
1117 
1118 /* Convert a pid to printable form. */
1119 
1120 char *
1121 solaris_pid_to_str (pid)
1122      int pid;
1123 {
1124   static char buf[100];
1125 
1126   if (is_thread (pid))
1127     {
1128       int lwp;
1129 
1130       lwp = thread_to_lwp (pid, -2);
1131 
1132       if (lwp != -2)
1133 	sprintf (buf, "Thread %d (LWP %d)", GET_THREAD (pid), GET_LWP (lwp));
1134       else
1135 	sprintf (buf, "Thread %d        ", GET_THREAD (pid));
1136     }
1137   else
1138     sprintf (buf, "LWP    %d        ", GET_LWP (pid));
1139 
1140   return buf;
1141 }
1142 
1143 struct target_ops sol_thread_ops = {
1144   "solaris-threads",		/* to_shortname */
1145   "Solaris threads and pthread.", /* to_longname */
1146   "Solaris threads and pthread support.", /* to_doc */
1147   sol_thread_open,		/* to_open */
1148   0,				/* to_close */
1149   sol_thread_attach,		/* to_attach */
1150   sol_thread_detach, 		/* to_detach */
1151   sol_thread_resume,		/* to_resume */
1152   sol_thread_wait,		/* to_wait */
1153   sol_thread_fetch_registers,	/* to_fetch_registers */
1154   sol_thread_store_registers,	/* to_store_registers */
1155   sol_thread_prepare_to_store,	/* to_prepare_to_store */
1156   sol_thread_xfer_memory,	/* to_xfer_memory */
1157   sol_thread_files_info,	/* to_files_info */
1158   memory_insert_breakpoint,	/* to_insert_breakpoint */
1159   memory_remove_breakpoint,	/* to_remove_breakpoint */
1160   terminal_init_inferior,	/* to_terminal_init */
1161   terminal_inferior, 		/* to_terminal_inferior */
1162   terminal_ours_for_output,	/* to_terminal_ours_for_output */
1163   terminal_ours,		/* to_terminal_ours */
1164   child_terminal_info,		/* to_terminal_info */
1165   sol_thread_kill_inferior,	/* to_kill */
1166   0,				/* to_load */
1167   0,				/* to_lookup_symbol */
1168   sol_thread_create_inferior,	/* to_create_inferior */
1169   sol_thread_mourn_inferior,	/* to_mourn_inferior */
1170   sol_thread_can_run,		/* to_can_run */
1171   sol_thread_notice_signals,	/* to_notice_signals */
1172   sol_thread_alive,		/* to_thread_alive */
1173   sol_thread_stop,		/* to_stop */
1174   process_stratum,		/* to_stratum */
1175   0,				/* to_next */
1176   1,				/* to_has_all_memory */
1177   1,				/* to_has_memory */
1178   1,				/* to_has_stack */
1179   1,				/* to_has_registers */
1180   1,				/* to_has_execution */
1181   0,				/* sections */
1182   0,				/* sections_end */
1183   OPS_MAGIC			/* to_magic */
1184 };
1185 
1186 void
1187 _initialize_sol_thread ()
1188 {
1189   void *dlhandle;
1190 
1191   dlhandle = dlopen ("libthread_db.so.1", RTLD_NOW);
1192   if (!dlhandle)
1193     goto die;
1194 
1195 #define resolve(X) \
1196   if (!(p_##X = dlsym (dlhandle, #X))) \
1197     goto die;
1198 
1199   resolve (td_log);
1200   resolve (td_ta_new);
1201   resolve (td_ta_delete);
1202   resolve (td_init);
1203   resolve (td_ta_get_ph);
1204   resolve (td_ta_get_nthreads);
1205   resolve (td_ta_tsd_iter);
1206   resolve (td_ta_thr_iter);
1207   resolve (td_thr_validate);
1208   resolve (td_thr_tsd);
1209   resolve (td_thr_get_info);
1210   resolve (td_thr_getfpregs);
1211   resolve (td_thr_getxregsize);
1212   resolve (td_thr_getxregs);
1213   resolve (td_thr_sigsetmask);
1214   resolve (td_thr_setprio);
1215   resolve (td_thr_setsigpending);
1216   resolve (td_thr_setfpregs);
1217   resolve (td_thr_setxregs);
1218   resolve (td_ta_map_id2thr);
1219   resolve (td_ta_map_lwp2thr);
1220   resolve (td_thr_getgregs);
1221   resolve (td_thr_setgregs);
1222 
1223   add_target (&sol_thread_ops);
1224 
1225   procfs_suppress_run = 1;
1226 
1227   return;
1228 
1229  die:
1230 
1231   fprintf_unfiltered (gdb_stderr, "[GDB will not be able to debug user-mode threads: %s]\n", dlerror ());
1232 
1233   if (dlhandle)
1234     dlclose (dlhandle);
1235 
1236   return;
1237 }
1238