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