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. */
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.
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.
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!
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
50 /* Undefine gregset_t and fpregset_t to avoid conflict with defs in xm file. */
61 #include <proc_service.h>
62 #include <thread_db.h>
63 #include "gdbthread.h"
70 extern struct target_ops sol_thread_ops
; /* Forward declaration */
72 extern int procfs_suppress_run
;
73 extern struct target_ops procfs_ops
; /* target vector for procfs.c */
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
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));
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. */
104 static struct ps_prochandle main_ph
;
105 static td_thragent_t
*main_ta
;
106 static int sol_thread_active
= 0;
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
));
117 #define THREAD_FLAG 0x80000000
118 #define is_thread(ARG) (((ARG) & THREAD_FLAG) != 0)
119 #define is_lwp(ARG) (((ARG) & THREAD_FLAG) == 0)
120 #define GET_LWP(LWP_ID) (TIDGET(LWP_ID))
121 #define GET_THREAD(THREAD_ID) (((THREAD_ID) >> 16) & 0x7fff)
122 #define BUILD_LWP(LWP_ID, PID) ((LWP_ID) << 16 | (PID))
123 #define BUILD_THREAD(THREAD_ID, PID) (THREAD_FLAG | BUILD_LWP (THREAD_ID, PID))
129 td_err_string - Convert a thread_db error code to a string
133 char * td_err_string (errcode)
137 Return the thread_db error string associated with errcode. If errcode
138 is unknown, then return a message.
143 td_err_string (errcode
)
146 static struct string_map
148 {TD_OK
, "generic \"call succeeded\""},
149 {TD_ERR
, "generic error."},
150 {TD_NOTHR
, "no thread can be found to satisfy query"},
151 {TD_NOSV
, "no synch. variable can be found to satisfy query"},
152 {TD_NOLWP
, "no lwp can be found to satisfy query"},
153 {TD_BADPH
, "invalid process handle"},
154 {TD_BADTH
, "invalid thread handle"},
155 {TD_BADSH
, "invalid synchronization handle"},
156 {TD_BADTA
, "invalid thread agent"},
157 {TD_BADKEY
, "invalid key"},
158 {TD_NOMSG
, "td_thr_event_getmsg() called when there was no message"},
159 {TD_NOFPREGS
, "FPU register set not available for given thread"},
160 {TD_NOLIBTHREAD
, "application not linked with libthread"},
161 {TD_NOEVENT
, "requested event is not supported"},
162 {TD_NOCAPAB
, "capability not available"},
163 {TD_DBERR
, "Debugger service failed"},
164 {TD_NOAPLIC
, "Operation not applicable to"},
165 {TD_NOTSD
, "No thread specific data for this thread"},
166 {TD_MALLOC
, "Malloc failed"},
167 {TD_PARTIALREG
, "Only part of register set was writen/read"},
168 {TD_NOXREGS
, "X register set not available for given thread"}
170 const int td_err_size
= sizeof td_err_table
/ sizeof (struct string_map
);
174 for (i
= 0; i
< td_err_size
; i
++)
175 if (td_err_table
[i
].num
== errcode
)
176 return td_err_table
[i
].str
;
178 sprintf (buf
, "Unknown thread_db error code: %d", errcode
);
187 td_state_string - Convert a thread_db state code to a string
191 char * td_state_string (statecode)
195 Return the thread_db state string associated with statecode. If
196 statecode is unknown, then return a message.
201 td_state_string (statecode
)
202 td_thr_state_e statecode
;
204 static struct string_map
205 td_thr_state_table
[] = {
206 {TD_THR_ANY_STATE
, "any state"},
207 {TD_THR_UNKNOWN
, "unknown"},
208 {TD_THR_STOPPED
, "stopped"},
210 {TD_THR_ACTIVE
, "active"},
211 {TD_THR_ZOMBIE
, "zombie"},
212 {TD_THR_SLEEP
, "sleep"},
213 {TD_THR_STOPPED_ASLEEP
, "stopped asleep"}
215 const int td_thr_state_table_size
= sizeof td_thr_state_table
/ sizeof (struct string_map
);
219 for (i
= 0; i
< td_thr_state_table_size
; i
++)
220 if (td_thr_state_table
[i
].num
== statecode
)
221 return td_thr_state_table
[i
].str
;
223 sprintf (buf
, "Unknown thread_db state code: %d", statecode
);
232 thread_to_lwp - Convert a Posix or Solaris thread id to a LWP id.
236 int thread_to_lwp (thread_id, default_lwp)
240 This function converts a Posix or Solaris thread id to a lightweight
241 process id. If thread_id is non-existent, that's an error. If it's
242 an inactive thread, then we return default_lwp.
246 This function probably shouldn't call error()...
251 thread_to_lwp (thread_id
, default_lwp
)
261 if (is_lwp (thread_id
))
262 return thread_id
; /* It's already an LWP id */
264 /* It's a thread. Convert to lwp */
266 pid
= PIDGET (thread_id
);
267 thread_id
= GET_THREAD(thread_id
);
269 val
= td_ta_map_id2thr (main_ta
, thread_id
, &th
);
271 error ("thread_to_lwp: td_ta_map_id2thr %s", td_err_string (val
));
273 val
= td_thr_get_info (&th
, &ti
);
276 error ("thread_to_lwp: td_thr_get_info: %s", td_err_string (val
));
278 if (ti
.ti_state
!= TD_THR_ACTIVE
)
280 if (default_lwp
!= -1)
282 error ("thread_to_lwp: thread state not active: %s",
283 td_state_string (ti
.ti_state
));
286 lwp
= BUILD_LWP (ti
.ti_lid
, pid
);
295 lwp_to_thread - Convert a LWP id to a Posix or Solaris thread id.
299 int lwp_to_thread (lwp_id)
303 This function converts a lightweight process id to a Posix or Solaris
304 thread id. If thread_id is non-existent, that's an error.
308 This function probably shouldn't call error()...
323 return lwp
; /* It's already a thread id */
325 /* It's an lwp. Convert it to a thread id. */
330 val
= td_ta_map_lwp2thr (main_ta
, lwp
, &th
);
332 error ("lwp_to_thread: td_thr_get_info: %s.", td_err_string (val
));
334 val
= td_thr_get_info (&th
, &ti
);
337 error ("lwp_to_thread: td_thr_get_info: %s.", td_err_string (val
));
339 thread_id
= BUILD_THREAD (ti
.ti_tid
, pid
);
348 save_inferior_pid - Save inferior_pid on the cleanup list
349 restore_inferior_pid - Restore inferior_pid from the cleanup list
353 struct cleanup *save_inferior_pid ()
354 void restore_inferior_pid (int pid)
358 These two functions act in unison to restore inferior_pid in
363 inferior_pid is a global variable that needs to be changed by many of
364 these routines before calling functions in procfs.c. In order to
365 guarantee that inferior_pid gets restored (in case of errors), you
366 need to call save_inferior_pid before changing it. At the end of the
367 function, you should invoke do_cleanups to restore it.
372 static struct cleanup
*
375 return make_cleanup (restore_inferior_pid
, inferior_pid
);
379 restore_inferior_pid (pid
)
386 /* Most target vector functions from here on actually just pass through to
387 procfs.c, as they don't need to do anything specific for threads. */
392 sol_thread_open (arg
, from_tty
)
396 procfs_ops
.to_open (arg
, from_tty
);
399 /* Attach to process PID, then initialize for debugging it
400 and wait for the trace-trap that results from attaching. */
403 sol_thread_attach (args
, from_tty
)
407 procfs_ops
.to_attach (args
, from_tty
);
409 /* XXX - might want to iterate over all the threads and register them. */
412 /* Take a program previously attached to and detaches it.
413 The program resumes execution and will no longer stop
414 on signals, etc. We'd better not have left any breakpoints
415 in the program or it'll die when it hits one. For this
416 to work, it may be necessary for the process to have been
417 previously attached. It *might* work if the program was
418 started via the normal ptrace (PTRACE_TRACEME). */
421 sol_thread_detach (args
, from_tty
)
425 procfs_ops
.to_detach (args
, from_tty
);
428 /* Resume execution of process PID. If STEP is nozero, then
429 just single step it. If SIGNAL is nonzero, restart it with that
430 signal activated. We may have to convert pid from a thread-id to an LWP id
434 sol_thread_resume (pid
, step
, signo
)
437 enum target_signal signo
;
439 struct cleanup
*old_chain
;
441 old_chain
= save_inferior_pid ();
443 inferior_pid
= thread_to_lwp (inferior_pid
, main_ph
.pid
);
447 pid
= thread_to_lwp (pid
, -2);
448 if (pid
== -2) /* Inactive thread */
449 error ("This version of Solaris can't start inactive threads.");
452 procfs_ops
.to_resume (pid
, step
, signo
);
454 do_cleanups (old_chain
);
457 /* Wait for any threads to stop. We may have to convert PID from a thread id
458 to a LWP id, and vice versa on the way out. */
461 sol_thread_wait (pid
, ourstatus
)
463 struct target_waitstatus
*ourstatus
;
467 struct cleanup
*old_chain
;
469 save_pid
= inferior_pid
;
470 old_chain
= save_inferior_pid ();
472 inferior_pid
= thread_to_lwp (inferior_pid
, main_ph
.pid
);
475 pid
= thread_to_lwp (pid
, -1);
477 rtnval
= procfs_ops
.to_wait (pid
, ourstatus
);
479 if (rtnval
!= save_pid
480 && !in_thread_list (rtnval
))
482 fprintf_unfiltered (gdb_stderr
, "[New %s]\n",
483 target_pid_to_str (rtnval
));
487 /* During process initialization, we may get here without the thread package
488 being initialized, since that can only happen after we've found the shared
491 /* Map the LWP of interest back to the appropriate thread ID */
493 rtnval
= lwp_to_thread (rtnval
);
495 do_cleanups (old_chain
);
501 sol_thread_fetch_registers (regno
)
505 td_thrhandle_t thandle
;
508 prfpregset_t fpregset
;
514 /* Convert inferior_pid into a td_thrhandle_t */
516 thread
= GET_THREAD (inferior_pid
);
519 error ("sol_thread_fetch_registers: thread == 0");
521 val
= td_ta_map_id2thr (main_ta
, thread
, &thandle
);
523 error ("sol_thread_fetch_registers: td_ta_map_id2thr: %s",
524 td_err_string (val
));
526 /* Get the integer regs */
528 val
= td_thr_getgregs (&thandle
, regset
);
530 supply_gregset (regset
);
531 else if (val
== TD_PARTIALREG
)
533 /* For the sparc, only i0->i7, l0->l7, pc and sp are saved by a thread
536 supply_gregset (regset
); /* This is not entirely correct, as it sets
537 the valid bits for the o, g, ps, y, npc,
538 wim and tbr. That should be harmless
539 though, as the context switch routine
540 doesn't need to save them. */
543 error ("sol_thread_fetch_registers: td_thr_getgregs %s",
544 td_err_string (val
));
546 /* And, now the fp regs */
548 val
= td_thr_getfpregs (&thandle
, &fpregset
);
550 supply_fpregset (fpregset
);
551 else if (val
!= TD_NOFPREGS
)
552 error ("sol_thread_fetch_registers: td_thr_getfpregs %s",
553 td_err_string (val
));
556 /* thread_db doesn't seem to handle this right */
557 val
= td_thr_getxregsize (&thandle
, &xregsize
);
558 if (val
!= TD_OK
&& val
!= TD_NOXREGS
)
559 error ("sol_thread_fetch_registers: td_thr_getxregsize %s",
560 td_err_string (val
));
564 xregset
= alloca (xregsize
);
565 val
= td_thr_getxregs (&thandle
, xregset
);
567 error ("sol_thread_fetch_registers: td_thr_getxregs %s",
568 td_err_string (val
));
574 sol_thread_store_registers (regno
)
578 td_thrhandle_t thandle
;
581 prfpregset_t fpregset
;
587 /* Convert inferior_pid into a td_thrhandle_t */
589 thread
= GET_THREAD (inferior_pid
);
591 val
= td_ta_map_id2thr (main_ta
, thread
, &thandle
);
593 error ("sol_thread_store_registers: td_ta_map_id2thr %s",
594 td_err_string (val
));
597 { /* Not writing all the regs */
598 val
= td_thr_getgregs (&thandle
, regset
);
600 error ("sol_thread_store_registers: td_thr_getgregs %s",
601 td_err_string (val
));
602 val
= td_thr_getfpregs (&thandle
, &fpregset
);
604 error ("sol_thread_store_registers: td_thr_getfpregs %s",
605 td_err_string (val
));
608 /* thread_db doesn't seem to handle this right */
609 val
= td_thr_getxregsize (&thandle
, &xregsize
);
610 if (val
!= TD_OK
&& val
!= TD_NOXREGS
)
611 error ("sol_thread_store_registers: td_thr_getxregsize %s",
612 td_err_string (val
));
616 xregset
= alloca (xregsize
);
617 val
= td_thr_getxregs (&thandle
, xregset
);
619 error ("sol_thread_store_registers: td_thr_getxregs %s",
620 td_err_string (val
));
625 fill_gregset (regset
, regno
);
626 fill_fpregset (fpregset
, regno
);
628 val
= td_thr_setgregs (&thandle
, regset
);
630 error ("sol_thread_store_registers: td_thr_setgregs %s",
631 td_err_string (val
));
632 val
= td_thr_setfpregs (&thandle
, &fpregset
);
634 error ("sol_thread_store_registers: td_thr_setfpregs %s",
635 td_err_string (val
));
638 /* thread_db doesn't seem to handle this right */
639 val
= td_thr_getxregsize (&thandle
, &xregsize
);
640 if (val
!= TD_OK
&& val
!= TD_NOXREGS
)
641 error ("sol_thread_store_registers: td_thr_getxregsize %s",
642 td_err_string (val
));
644 /* Should probably do something about writing the xregs here, but what are
649 /* Get ready to modify the registers array. On machines which store
650 individual registers, this doesn't need to do anything. On machines
651 which store all the registers in one fell swoop, this makes sure
652 that registers contains all the registers from the program being
656 sol_thread_prepare_to_store ()
658 procfs_ops
.to_prepare_to_store ();
662 sol_thread_xfer_memory (memaddr
, myaddr
, len
, dowrite
, target
)
667 struct target_ops
*target
; /* ignored */
670 struct cleanup
*old_chain
;
672 old_chain
= save_inferior_pid ();
674 if (is_thread (inferior_pid
))
675 inferior_pid
= main_ph
.pid
; /* It's a thread. Convert to lwp */
677 retval
= procfs_ops
.to_xfer_memory (memaddr
, myaddr
, len
, dowrite
, target
);
679 do_cleanups (old_chain
);
684 /* Print status information about what we're accessing. */
687 sol_thread_files_info (ignore
)
688 struct target_ops
*ignore
;
690 procfs_ops
.to_files_info (ignore
);
694 sol_thread_kill_inferior ()
696 procfs_ops
.to_kill ();
700 sol_thread_notice_signals (pid
)
703 procfs_ops
.to_notice_signals (pid
);
706 void target_new_objfile
PARAMS ((struct objfile
*objfile
));
708 /* Fork an inferior process, and start debugging it with /proc. */
711 sol_thread_create_inferior (exec_file
, allargs
, env
)
716 procfs_ops
.to_create_inferior (exec_file
, allargs
, env
);
718 if (sol_thread_active
)
720 main_ph
.pid
= inferior_pid
; /* Save for xfer_memory */
722 push_target (&sol_thread_ops
);
724 inferior_pid
= lwp_to_thread (inferior_pid
);
726 add_thread (inferior_pid
);
730 /* This routine is called whenever a new symbol table is read in, or when all
731 symbol tables are removed. libthread_db can only be initialized when it
732 finds the right variables in libthread.so. Since it's a shared library,
733 those variables don't show up until the library gets mapped and the symbol
737 sol_thread_new_objfile (objfile
)
738 struct objfile
*objfile
;
744 sol_thread_active
= 0;
749 /* Now, initialize the thread debugging library. This needs to be done after
750 the shared libraries are located because it needs information from the
751 user's thread library. */
755 error ("target_new_objfile: td_init: %s", td_err_string (val
));
757 val
= td_ta_new (&main_ph
, &main_ta
);
758 if (val
== TD_NOLIBTHREAD
)
760 else if (val
!= TD_OK
)
761 error ("target_new_objfile: td_ta_new: %s", td_err_string (val
));
763 sol_thread_active
= 1;
766 /* Clean up after the inferior dies. */
769 sol_thread_mourn_inferior ()
771 procfs_ops
.to_mourn_inferior ();
774 /* Mark our target-struct as eligible for stray "run" and "attach" commands. */
777 sol_thread_can_run ()
779 return procfs_suppress_run
;
783 sol_thread_alive (pid
)
792 procfs_ops
.to_stop ();
795 /* These routines implement the lower half of the thread_db interface. Ie: the
798 /* The next four routines are called by thread_db to tell us to stop and stop
799 a particular process or lwp. Since GDB ensures that these are all stopped
800 by the time we call anything in thread_db, these routines need to do
804 ps_pstop (const struct ps_prochandle
*ph
)
810 ps_pcontinue (const struct ps_prochandle
*ph
)
816 ps_lstop (const struct ps_prochandle
*ph
, lwpid_t lwpid
)
822 ps_lcontinue (const struct ps_prochandle
*ph
, lwpid_t lwpid
)
828 ps_pglobal_lookup (const struct ps_prochandle
*ph
, const char *ld_object_name
,
829 const char *ld_symbol_name
, paddr_t
*ld_symbol_addr
)
831 struct minimal_symbol
*ms
;
833 ms
= lookup_minimal_symbol (ld_symbol_name
, NULL
, NULL
);
838 *ld_symbol_addr
= SYMBOL_VALUE_ADDRESS (ms
);
843 /* Common routine for reading and writing memory. */
846 rw_common (int dowrite
, const struct ps_prochandle
*ph
, paddr_t addr
,
849 struct cleanup
*old_chain
;
851 old_chain
= save_inferior_pid ();
853 if (is_thread (inferior_pid
))
854 inferior_pid
= main_ph
.pid
; /* It's a thread. Convert to lwp */
860 cc
= procfs_ops
.to_xfer_memory (addr
, buf
, size
, dowrite
, &procfs_ops
);
865 print_sys_errmsg ("ps_pdread (): read", errno
);
867 print_sys_errmsg ("ps_pdread (): write", errno
);
869 do_cleanups (old_chain
);
877 do_cleanups (old_chain
);
883 ps_pdread (const struct ps_prochandle
*ph
, paddr_t addr
, char *buf
, int size
)
885 return rw_common (0, ph
, addr
, buf
, size
);
889 ps_pdwrite (const struct ps_prochandle
*ph
, paddr_t addr
, char *buf
, int size
)
891 return rw_common (1, ph
, addr
, buf
, size
);
895 ps_ptread (const struct ps_prochandle
*ph
, paddr_t addr
, char *buf
, int size
)
897 return rw_common (0, ph
, addr
, buf
, size
);
901 ps_ptwrite (const struct ps_prochandle
*ph
, paddr_t addr
, char *buf
, int size
)
903 return rw_common (1, ph
, addr
, buf
, size
);
906 /* Get integer regs */
909 ps_lgetregs (const struct ps_prochandle
*ph
, lwpid_t lwpid
,
912 struct cleanup
*old_chain
;
914 old_chain
= save_inferior_pid ();
916 inferior_pid
= BUILD_LWP (lwpid
, PIDGET (inferior_pid
));
918 procfs_ops
.to_fetch_registers (-1);
919 fill_gregset (gregset
, -1);
921 do_cleanups (old_chain
);
926 /* Set integer regs */
929 ps_lsetregs (const struct ps_prochandle
*ph
, lwpid_t lwpid
,
930 const prgregset_t gregset
)
932 struct cleanup
*old_chain
;
934 old_chain
= save_inferior_pid ();
936 inferior_pid
= BUILD_LWP (lwpid
, PIDGET (inferior_pid
));
938 supply_gregset (gregset
);
939 procfs_ops
.to_store_registers (-1);
941 do_cleanups (old_chain
);
947 ps_plog (const char *fmt
, ...)
951 va_start (args
, fmt
);
953 vfprintf_filtered (gdb_stderr
, fmt
, args
);
956 /* Get size of extra register set. Currently a noop. */
959 ps_lgetxregsize (const struct ps_prochandle
*ph
, lwpid_t lwpid
, int *xregsize
)
966 val
= get_lwp_fd (ph
, lwpid
, &lwp_fd
);
970 if (ioctl (lwp_fd
, PIOCGXREGSIZE
, ®size
))
973 return PS_NOFREGS
; /* XXX Wrong code, but this is the closest
974 thing in proc_service.h */
976 print_sys_errmsg ("ps_lgetxregsize (): PIOCGXREGSIZE", errno
);
984 /* Get extra register set. Currently a noop. */
987 ps_lgetxregs (const struct ps_prochandle
*ph
, lwpid_t lwpid
, caddr_t xregset
)
993 val
= get_lwp_fd (ph
, lwpid
, &lwp_fd
);
997 if (ioctl (lwp_fd
, PIOCGXREG
, xregset
))
999 print_sys_errmsg ("ps_lgetxregs (): PIOCGXREG", errno
);
1007 /* Set extra register set. Currently a noop. */
1010 ps_lsetxregs (const struct ps_prochandle
*ph
, lwpid_t lwpid
, caddr_t xregset
)
1016 val
= get_lwp_fd (ph
, lwpid
, &lwp_fd
);
1020 if (ioctl (lwp_fd
, PIOCSXREG
, xregset
))
1022 print_sys_errmsg ("ps_lsetxregs (): PIOCSXREG", errno
);
1030 /* Get floating-point regs. */
1033 ps_lgetfpregs (const struct ps_prochandle
*ph
, lwpid_t lwpid
,
1034 prfpregset_t
*fpregset
)
1036 struct cleanup
*old_chain
;
1038 old_chain
= save_inferior_pid ();
1040 inferior_pid
= BUILD_LWP (lwpid
, PIDGET (inferior_pid
));
1042 procfs_ops
.to_fetch_registers (-1);
1043 fill_fpregset (*fpregset
, -1);
1045 do_cleanups (old_chain
);
1050 /* Set floating-point regs. */
1053 ps_lsetfpregs (const struct ps_prochandle
*ph
, lwpid_t lwpid
,
1054 const prfpregset_t
*fpregset
)
1056 struct cleanup
*old_chain
;
1058 old_chain
= save_inferior_pid ();
1060 inferior_pid
= BUILD_LWP (lwpid
, PIDGET (inferior_pid
));
1062 supply_fpregset (*fpregset
);
1063 procfs_ops
.to_store_registers (-1);
1065 do_cleanups (old_chain
);
1070 /* Convert a pid to printable form. */
1073 solaris_pid_to_str (pid
)
1076 static char buf
[100];
1078 if (is_thread (pid
))
1082 lwp
= thread_to_lwp (pid
, -2);
1085 sprintf (buf
, "Thread %d (LWP %d)", GET_THREAD (pid
), GET_LWP (lwp
));
1087 sprintf (buf
, "Thread %d ", GET_THREAD (pid
));
1090 sprintf (buf
, "LWP %d ", GET_LWP (pid
));
1095 struct target_ops sol_thread_ops
= {
1096 "solaris-threads", /* to_shortname */
1097 "Solaris threads and pthread.", /* to_longname */
1098 "Solaris threads and pthread support.", /* to_doc */
1099 sol_thread_open
, /* to_open */
1101 sol_thread_attach
, /* to_attach */
1102 sol_thread_detach
, /* to_detach */
1103 sol_thread_resume
, /* to_resume */
1104 sol_thread_wait
, /* to_wait */
1105 sol_thread_fetch_registers
, /* to_fetch_registers */
1106 sol_thread_store_registers
, /* to_store_registers */
1107 sol_thread_prepare_to_store
, /* to_prepare_to_store */
1108 sol_thread_xfer_memory
, /* to_xfer_memory */
1109 sol_thread_files_info
, /* to_files_info */
1110 memory_insert_breakpoint
, /* to_insert_breakpoint */
1111 memory_remove_breakpoint
, /* to_remove_breakpoint */
1112 terminal_init_inferior
, /* to_terminal_init */
1113 terminal_inferior
, /* to_terminal_inferior */
1114 terminal_ours_for_output
, /* to_terminal_ours_for_output */
1115 terminal_ours
, /* to_terminal_ours */
1116 child_terminal_info
, /* to_terminal_info */
1117 sol_thread_kill_inferior
, /* to_kill */
1119 0, /* to_lookup_symbol */
1120 sol_thread_create_inferior
, /* to_create_inferior */
1121 sol_thread_mourn_inferior
, /* to_mourn_inferior */
1122 sol_thread_can_run
, /* to_can_run */
1123 sol_thread_notice_signals
, /* to_notice_signals */
1124 sol_thread_alive
, /* to_thread_alive */
1125 sol_thread_stop
, /* to_stop */
1126 process_stratum
, /* to_stratum */
1128 1, /* to_has_all_memory */
1129 1, /* to_has_memory */
1130 1, /* to_has_stack */
1131 1, /* to_has_registers */
1132 1, /* to_has_execution */
1134 0, /* sections_end */
1135 OPS_MAGIC
/* to_magic */
1139 _initialize_sol_thread ()
1141 add_target (&sol_thread_ops
);
1143 procfs_suppress_run
= 1;