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