1 /* Low level interface for debugging Solaris threads for GDB, the GNU debugger.
2 Copyright 1996 Free Software Foundation, Inc.
4 This file is part of GDB.
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.
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.
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. */
31 #include "/usr/include/thread.h"
32 #include <proc_service.h>
33 #include <thread_db.h>
34 #include "gdbthread.h"
41 static void sol_thread_resume
PARAMS ((int pid
, int step
,
42 enum target_signal signo
));
44 extern struct target_ops sol_thread_ops
; /* Forward declaration */
46 extern int procfs_suppress_run
;
53 static struct ps_prochandle main_ph
;
54 static td_thragent_t
*main_ta
;
56 static int sol_thread_active
= 0;
60 extern struct target_ops procfs_ops
;
62 /* Convert thread_id to an LWP id. */
64 static int thread_to_lwp
PARAMS ((int thread_id
, int default_lwp
));
67 thread_to_lwp (thread_id
, default_lwp
)
77 if (!(thread_id
& 0x80000000))
78 return thread_id
; /* It's already an LWP id */
80 /* It's a thread. Convert to lwp */
82 pid
= thread_id
& 0xffff;
83 thread_id
= (thread_id
>> 16) & 0x7fff;
85 val
= td_ta_map_id2thr (main_ta
, thread_id
, &th
);
87 error ("thread_to_lwp: td_ta_map_id2thr %d", val
);
89 val
= td_thr_get_info (&th
, &ti
);
92 error ("thread_to_lwp: td_thr_get_info: %d", val
);
94 if (ti
.ti_state
!= TD_THR_ACTIVE
)
96 if (default_lwp
!= -1)
98 error ("thread_to_lwp: thread state not active: %d", ti
.ti_state
);
101 lwp
= (ti
.ti_lid
<< 16) | pid
;
106 /* Convert an LWP id to a thread. */
108 static int lwp_to_thread
PARAMS ((int lwp
));
120 if (lwp
& 0x80000000)
121 return lwp
; /* It's already a thread id */
123 /* It's an lwp. Convert it to a thread id. */
126 lwp
= (lwp
>> 16) & 0xffff;
128 val
= td_ta_map_lwp2thr (main_ta
, lwp
, &th
);
130 error ("lwp_to_thread: td_thr_get_info: %d.", val
);
132 val
= td_thr_get_info (&th
, &ti
);
135 error ("lwp_to_thread: td_thr_get_info: %d.", val
);
137 thread_id
= (ti
.ti_tid
<< 16) | pid
| 0x80000000;
145 sol_thread_open (arg
, from_tty
)
149 procfs_ops
.to_open (arg
, from_tty
);
152 /* Attach to process PID, then initialize for debugging it
153 and wait for the trace-trap that results from attaching. */
156 sol_thread_attach (args
, from_tty
)
160 procfs_ops
.to_attach (args
, from_tty
);
162 /* XXX - might want to iterate over all the threads and register them. */
165 /* Take a program previously attached to and detaches it.
166 The program resumes execution and will no longer stop
167 on signals, etc. We'd better not have left any breakpoints
168 in the program or it'll die when it hits one. For this
169 to work, it may be necessary for the process to have been
170 previously attached. It *might* work if the program was
171 started via the normal ptrace (PTRACE_TRACEME). */
174 sol_thread_detach (args
, from_tty
)
178 procfs_ops
.to_detach (args
, from_tty
);
181 /* Resume execution of process PID. If STEP is nozero, then
182 just single step it. If SIGNAL is nonzero, restart it with that
186 sol_thread_resume (pid
, step
, signo
)
189 enum target_signal signo
;
193 save_pid
= inferior_pid
;
195 inferior_pid
= thread_to_lwp (inferior_pid
, main_ph
.pid
);
198 pid
= thread_to_lwp (pid
, -1);
200 procfs_ops
.to_resume (pid
, step
, signo
);
202 inferior_pid
= save_pid
;
205 /* Wait for any LWPs to stop */
208 sol_thread_wait (pid
, ourstatus
)
210 struct target_waitstatus
*ourstatus
;
216 if (!sol_thread_active
)
217 return procfs_ops
.to_wait (pid
, ourstatus
);
219 save_pid
= inferior_pid
;
221 inferior_pid
= thread_to_lwp (inferior_pid
, main_ph
.pid
);
224 pid
= thread_to_lwp (pid
, -1);
226 rtnval
= procfs_ops
.to_wait (pid
, ourstatus
);
228 if (rtnval
!= save_pid
229 && !in_thread_list (rtnval
))
231 fprintf_unfiltered (gdb_stderr
, "[New %s]\n",
232 target_pid_to_str (rtnval
));
236 inferior_pid
= save_pid
; /* XXX need to make a cleanup for this in case of error */
238 /* During process initialization, we may get here without the thread package
239 being initialized, since that can only happen after we've found the shared
242 /* Map the LWP of interest back to the appropriate thread ID */
244 rtnval
= lwp_to_thread (rtnval
);
250 sol_thread_fetch_registers (regno
)
254 td_thrhandle_t thandle
;
257 prfpregset_t fpregset
;
261 if (!sol_thread_active
262 || !(inferior_pid
& 0x80000000))
264 procfs_ops
.to_fetch_registers (regno
);
268 /* Convert inferior_pid into a td_thrhandle_t */
270 thread
= (inferior_pid
>> 16) & 0x7fff;
273 error ("sol_thread_fetch_registers: thread == 0");
275 val
= td_ta_map_id2thr (main_ta
, thread
, &thandle
);
277 error ("sol_thread_fetch_registers: td_ta_map_id2thr: %d", val
);
279 /* Get the integer regs */
281 val
= td_thr_getgregs (&thandle
, regset
);
283 supply_gregset (regset
);
284 else if (val
== TD_PARTIALREG
)
286 /* For the sparc, only i0->i7, l0->l7, pc and sp are saved by a thread
289 supply_gregset (regset
); /* This is not entirely correct, as it sets
290 the valid bits for the o, g, ps, y, npc,
291 wim and tbr. That should be harmless
292 though, as the context switch routine
293 doesn't need to save them. */
296 error ("sol_thread_fetch_registers: td_thr_getgregs %d", val
);
298 /* And, now the fp regs */
300 val
= td_thr_getfpregs (&thandle
, &fpregset
);
302 supply_fpregset (&fpregset
);
303 else if (val
!= TD_NOFPREGS
)
304 error ("sol_thread_fetch_registers: td_thr_getfpregs %d", val
);
307 /* thread_db doesn't seem to handle this right */
308 val
= td_thr_getxregsize (&thandle
, &xregsize
);
309 if (val
!= TD_OK
&& val
!= TD_NOXREGS
)
310 error ("sol_thread_fetch_registers: td_thr_getxregsize %d", val
);
314 xregset
= alloca (xregsize
);
315 val
= td_thr_getxregs (&thandle
, xregset
);
317 error ("sol_thread_fetch_registers: td_thr_getxregs %d", val
);
323 sol_thread_store_registers (regno
)
327 td_thrhandle_t thandle
;
330 prfpregset_t fpregset
;
334 if (!sol_thread_active
335 || !(inferior_pid
& 0x80000000))
337 procfs_ops
.to_store_registers (regno
);
341 /* Convert inferior_pid into a td_thrhandle_t */
343 thread
= (inferior_pid
>> 16) & 0x7fff;
345 val
= td_ta_map_id2thr (main_ta
, thread
, &thandle
);
347 error ("sol_thread_store_registers: td_ta_map_id2thr %d", val
);
350 { /* Not writing all the regs */
351 val
= td_thr_getgregs (&thandle
, regset
);
353 error ("sol_thread_store_registers: td_thr_getgregs %d", val
);
354 val
= td_thr_getfpregs (&thandle
, &fpregset
);
356 error ("sol_thread_store_registers: td_thr_getfpregs %d", val
);
359 /* thread_db doesn't seem to handle this right */
360 val
= td_thr_getxregsize (&thandle
, &xregsize
);
361 if (val
!= TD_OK
&& val
!= TD_NOXREGS
)
362 error ("sol_thread_store_registers: td_thr_getxregsize %d", val
);
366 xregset
= alloca (xregsize
);
367 val
= td_thr_getxregs (&thandle
, xregset
);
369 error ("sol_thread_store_registers: td_thr_getxregs %d", val
);
374 fill_gregset (regset
, regno
);
375 fill_fpregset (&fpregset
, regno
);
377 val
= td_thr_setgregs (&thandle
, regset
);
379 error ("sol_thread_store_registers: td_thr_setgregs %d", val
);
380 val
= td_thr_setfpregs (&thandle
, &fpregset
);
382 error ("sol_thread_store_registers: td_thr_setfpregs %d", val
);
385 /* thread_db doesn't seem to handle this right */
386 val
= td_thr_getxregsize (&thandle
, &xregsize
);
387 if (val
!= TD_OK
&& val
!= TD_NOXREGS
)
388 error ("sol_thread_store_registers: td_thr_getxregsize %d", val
);
390 /* Should probably do something about writing the xregs here, but what are
395 /* Get ready to modify the registers array. On machines which store
396 individual registers, this doesn't need to do anything. On machines
397 which store all the registers in one fell swoop, this makes sure
398 that registers contains all the registers from the program being
402 sol_thread_prepare_to_store ()
404 procfs_ops
.to_prepare_to_store ();
408 sol_thread_xfer_memory (memaddr
, myaddr
, len
, dowrite
, target
)
413 struct target_ops
*target
; /* ignored */
418 save_pid
= inferior_pid
;
420 if (inferior_pid
& 0x80000000)
421 inferior_pid
= main_ph
.pid
; /* It's a thread. Convert to lwp */
423 retval
= procfs_ops
.to_xfer_memory (memaddr
, myaddr
, len
, dowrite
, target
);
425 inferior_pid
= save_pid
;
430 /* Print status information about what we're accessing. */
433 sol_thread_files_info (ignore
)
434 struct target_ops
*ignore
;
436 procfs_ops
.to_files_info (ignore
);
440 sol_thread_kill_inferior ()
442 procfs_ops
.to_kill ();
446 sol_thread_notice_signals (pid
)
449 procfs_ops
.to_notice_signals (pid
);
452 void target_new_objfile
PARAMS ((struct objfile
*objfile
));
454 /* Fork an inferior process, and start debugging it with /proc. */
457 sol_thread_create_inferior (exec_file
, allargs
, env
)
462 procfs_ops
.to_create_inferior (exec_file
, allargs
, env
);
464 if (sol_thread_active
)
466 td_thrhandle_t thandle
;
470 main_ph
.pid
= inferior_pid
; /* Save for xfer_memory */
472 push_target (&sol_thread_ops
);
474 inferior_pid
= lwp_to_thread (inferior_pid
);
476 add_thread (inferior_pid
);
480 /* This routine is called whenever a new symbol table is read in, or when all
481 symbol tables are removed. */
484 sol_thread_new_objfile (objfile
)
485 struct objfile
*objfile
;
491 sol_thread_active
= 0;
496 /* Now, initialize the thread debugging library. This needs to be done after
497 the shared libraries are located because it needs information from the
498 user's thread library. */
502 error ("target_new_objfile: td_init: %d", val
);
504 val
= td_ta_new (&main_ph
, &main_ta
);
505 if (val
== TD_NOLIBTHREAD
)
507 else if (val
!= TD_OK
)
508 error ("target_new_objfile: td_ta_new: %d", val
);
510 sol_thread_active
= 1;
513 /* Clean up after the inferior dies. */
516 sol_thread_mourn_inferior ()
518 procfs_ops
.to_mourn_inferior ();
521 /* Mark our target-struct as eligible for stray "run" and "attach" commands. */
523 sol_thread_can_run ()
525 return procfs_suppress_run
;
529 sol_thread_alive (pid
)
538 procfs_ops
.to_stop ();
541 /* Service routines we must supply to libthread_db */
545 struct lwp_map
*next
;
552 struct lwp_map
*lwp_map
;
554 /* Create a /proc file descriptor for the given LWPID */
557 get_lwp_fd (const struct ps_prochandle
*ph
, const lwpid_t lwpid
, int *fd
)
561 for (lp
= lwp_map
; lp
; lp
= lp
->next
)
562 if (lp
->pid
= ph
->pid
570 lp
= xmalloc (sizeof (struct lwp_map
));
572 if ((lp
->lwpfd
= ioctl (ph
->fd
, PIOCOPENLWP
, &lwpid
)) < 0)
574 print_sys_errmsg ("get_lwp_fd (): PIOCOPENLWP", errno
);
590 ps_pstop (const struct ps_prochandle
*ph
)
593 if (ioctl (ph
->fd
, PIOCSTOP
, NULL
))
595 print_sys_errmsg ("ps_pstop (): PIOCSTOP", errno
);
603 ps_pcontinue (const struct ps_prochandle
*ph
)
606 if (ioctl (ph
->fd
, PIOCRUN
, NULL
))
608 print_sys_errmsg ("ps_pcontinue (): PIOCRUN", errno
);
616 ps_lstop (const struct ps_prochandle
*ph
, lwpid_t lwpid
)
622 val
= get_lwp_fd (ph
, lwpid
, &lwp_fd
);
626 if (ioctl (lwp_fd
, PIOCSTOP
, NULL
))
628 print_sys_errmsg ("ps_lstop (): PIOCSTOP", errno
);
637 ps_lcontinue (const struct ps_prochandle
*ph
, lwpid_t lwpid
)
643 val
= get_lwp_fd (ph
, lwpid
, &lwp_fd
);
647 if (ioctl (lwp_fd
, PIOCRUN
, NULL
))
649 print_sys_errmsg ("ps_lcontinue (): PIOCRUN", errno
);
658 ps_pglobal_lookup (const struct ps_prochandle
*ph
, const char *ld_object_name
,
659 const char *ld_symbol_name
, paddr_t
*ld_symbol_addr
)
661 struct minimal_symbol
*ms
;
663 ms
= lookup_minimal_symbol (ld_symbol_name
, NULL
, NULL
);
668 *ld_symbol_addr
= SYMBOL_VALUE_ADDRESS (ms
);
674 rw_common (int dowrite
, const struct ps_prochandle
*ph
, paddr_t addr
,
679 save_pid
= inferior_pid
;
681 if (inferior_pid
& 0x80000000)
682 inferior_pid
= main_ph
.pid
; /* It's a thread. Convert to lwp */
688 cc
= procfs_ops
.to_xfer_memory (addr
, buf
, size
, dowrite
, &procfs_ops
);
693 print_sys_errmsg ("ps_pdread (): read", errno
);
695 print_sys_errmsg ("ps_pdread (): write", errno
);
697 inferior_pid
= save_pid
;
705 inferior_pid
= save_pid
;
711 ps_pdread (const struct ps_prochandle
*ph
, paddr_t addr
, char *buf
, int size
)
713 return rw_common (0, ph
, addr
, buf
, size
);
717 ps_pdwrite (const struct ps_prochandle
*ph
, paddr_t addr
, char *buf
, int size
)
719 return rw_common (1, ph
, addr
, buf
, size
);
723 ps_ptread (const struct ps_prochandle
*ph
, paddr_t addr
, char *buf
, int size
)
725 return rw_common (0, ph
, addr
, buf
, size
);
729 ps_ptwrite (const struct ps_prochandle
*ph
, paddr_t addr
, char *buf
, int size
)
731 return rw_common (1, ph
, addr
, buf
, size
);
735 ps_lgetregs (const struct ps_prochandle
*ph
, lwpid_t lwpid
,
740 save_pid
= inferior_pid
;
742 inferior_pid
= (lwpid
<< 16) | (inferior_pid
& 0xffff);
744 procfs_ops
.to_fetch_registers (-1);
745 fill_gregset (gregset
, -1);
747 inferior_pid
= save_pid
;
753 ps_lsetregs (const struct ps_prochandle
*ph
, lwpid_t lwpid
,
754 const prgregset_t gregset
)
758 save_pid
= inferior_pid
;
760 inferior_pid
= (lwpid
<< 16) | (inferior_pid
& 0xffff);
762 supply_gregset (gregset
);
763 procfs_ops
.to_store_registers (-1);
765 inferior_pid
= save_pid
;
771 ps_plog (const char *fmt
, ...)
775 va_start (args
, fmt
);
777 vfprintf_filtered (gdb_stderr
, fmt
, args
);
781 ps_lgetxregsize (const struct ps_prochandle
*ph
, lwpid_t lwpid
, int *xregsize
)
788 val
= get_lwp_fd (ph
, lwpid
, &lwp_fd
);
792 if (ioctl (lwp_fd
, PIOCGXREGSIZE
, ®size
))
795 return PS_NOFREGS
; /* XXX Wrong code, but this is the closest
796 thing in proc_service.h */
798 print_sys_errmsg ("ps_lgetxregsize (): PIOCGXREGSIZE", errno
);
807 ps_lgetxregs (const struct ps_prochandle
*ph
, lwpid_t lwpid
, caddr_t xregset
)
813 val
= get_lwp_fd (ph
, lwpid
, &lwp_fd
);
817 if (ioctl (lwp_fd
, PIOCGXREG
, xregset
))
819 print_sys_errmsg ("ps_lgetxregs (): PIOCGXREG", errno
);
828 ps_lsetxregs (const struct ps_prochandle
*ph
, lwpid_t lwpid
, caddr_t xregset
)
834 val
= get_lwp_fd (ph
, lwpid
, &lwp_fd
);
838 if (ioctl (lwp_fd
, PIOCSXREG
, xregset
))
840 print_sys_errmsg ("ps_lsetxregs (): PIOCSXREG", errno
);
849 ps_lgetfpregs (const struct ps_prochandle
*ph
, lwpid_t lwpid
,
850 prfpregset_t
*fpregset
)
854 save_pid
= inferior_pid
;
856 inferior_pid
= (lwpid
<< 16) | (inferior_pid
& 0xffff);
858 procfs_ops
.to_fetch_registers (-1);
859 fill_fpregset (fpregset
, -1);
861 inferior_pid
= save_pid
;
867 ps_lsetfpregs (const struct ps_prochandle
*ph
, lwpid_t lwpid
,
868 const prfpregset_t
*fpregset
)
872 save_pid
= inferior_pid
;
874 inferior_pid
= (lwpid
<< 16) | (inferior_pid
& 0xffff);
876 supply_gregset (fpregset
);
877 procfs_ops
.to_store_registers (-1);
879 inferior_pid
= save_pid
;
885 solaris_pid_to_str (pid
)
888 static char buf
[100];
890 if (pid
& 0x80000000)
894 lwp
= thread_to_lwp (pid
, -2);
897 sprintf (buf
, "Thread %d (LWP %d)", (pid
>> 16) & 0x7fff,
898 (lwp
>> 16) & 0xffff);
900 sprintf (buf
, "Thread %d ", (pid
>> 16) & 0x7fff);
903 sprintf (buf
, "LWP %d ", (pid
>> 16) & 0xffff);
908 struct target_ops sol_thread_ops
= {
909 "solaris-threads", /* to_shortname */
910 "Solaris threads and pthread.", /* to_longname */
911 "Solaris threads and pthread support.", /* to_doc */
912 sol_thread_open
, /* to_open */
914 sol_thread_attach
, /* to_attach */
915 sol_thread_detach
, /* to_detach */
916 sol_thread_resume
, /* to_resume */
917 sol_thread_wait
, /* to_wait */
918 sol_thread_fetch_registers
, /* to_fetch_registers */
919 sol_thread_store_registers
, /* to_store_registers */
920 sol_thread_prepare_to_store
, /* to_prepare_to_store */
921 sol_thread_xfer_memory
, /* to_xfer_memory */
922 sol_thread_files_info
, /* to_files_info */
923 memory_insert_breakpoint
, /* to_insert_breakpoint */
924 memory_remove_breakpoint
, /* to_remove_breakpoint */
925 terminal_init_inferior
, /* to_terminal_init */
926 terminal_inferior
, /* to_terminal_inferior */
927 terminal_ours_for_output
, /* to_terminal_ours_for_output */
928 terminal_ours
, /* to_terminal_ours */
929 child_terminal_info
, /* to_terminal_info */
930 sol_thread_kill_inferior
, /* to_kill */
932 0, /* to_lookup_symbol */
933 sol_thread_create_inferior
, /* to_create_inferior */
934 sol_thread_mourn_inferior
, /* to_mourn_inferior */
935 sol_thread_can_run
, /* to_can_run */
936 sol_thread_notice_signals
, /* to_notice_signals */
937 sol_thread_alive
, /* to_thread_alive */
938 sol_thread_stop
, /* to_stop */
939 process_stratum
, /* to_stratum */
941 1, /* to_has_all_memory */
942 1, /* to_has_memory */
943 1, /* to_has_stack */
944 1, /* to_has_registers */
945 1, /* to_has_execution */
947 0, /* sections_end */
948 OPS_MAGIC
/* to_magic */
952 _initialize_sol_thread ()
954 add_target (&sol_thread_ops
);
956 procfs_suppress_run
= 1;