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