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"
71 extern struct target_ops sol_thread_ops; /* Forward declaration */
73 extern int procfs_suppress_run;
74 extern struct target_ops procfs_ops; /* target vector for procfs.c */
76 /* Note that these prototypes differ slightly from those used in procfs.c
77 for of two reasons. One, we can't use gregset_t, as that's got a whole
78 different meaning under Solaris (also, see above). Two, we can't use the
79 pointer form here as these are actually arrays of ints (for Sparc's at
80 least), and are automatically coerced into pointers to ints when used as
81 parameters. That makes it impossible to avoid a compiler warning when
82 passing pr{g fp}regset_t's from a parameter to an argument of one of
85 extern void supply_gregset PARAMS ((const prgregset_t));
86 extern void fill_gregset PARAMS ((prgregset_t, int));
87 extern void supply_fpregset PARAMS ((const prfpregset_t));
88 extern void fill_fpregset PARAMS ((prfpregset_t, int));
90 /* This struct is defined by us, but mainly used for the proc_service interface.
91 We don't have much use for it, except as a handy place to get a real pid
92 for memory accesses. */
105 static struct ps_prochandle main_ph;
106 static td_thragent_t *main_ta;
107 static int sol_thread_active = 0;
109 static struct cleanup * save_inferior_pid PARAMS ((void));
110 static void restore_inferior_pid PARAMS ((int pid));
111 static char *td_err_string PARAMS ((td_err_e errcode));
112 static char *td_state_string PARAMS ((td_thr_state_e statecode));
113 static int thread_to_lwp PARAMS ((int thread_id, int default_lwp));
114 static void sol_thread_resume PARAMS ((int pid, int step,
115 enum target_signal signo));
116 static int lwp_to_thread PARAMS ((int lwp));
118 #define THREAD_FLAG 0x80000000
119 #define is_thread(ARG) (((ARG) & THREAD_FLAG) != 0)
120 #define is_lwp(ARG) (((ARG) & THREAD_FLAG) == 0)
121 #define GET_LWP(LWP_ID) (TIDGET(LWP_ID))
122 #define GET_THREAD(THREAD_ID) (((THREAD_ID) >> 16) & 0x7fff)
123 #define BUILD_LWP(LWP_ID, PID) ((LWP_ID) << 16 | (PID))
124 #define BUILD_THREAD(THREAD_ID, PID) (THREAD_FLAG | BUILD_LWP (THREAD_ID, PID))
126 /* Pointers to routines from lithread_db resolved by dlopen() */
129 (*p_td_log) (const int on_off);
131 (*p_td_ta_new) (const struct ps_prochandle *ph_p, td_thragent_t **ta_pp);
133 (*p_td_ta_delete) (td_thragent_t *ta_p);
137 (*p_td_ta_get_ph) (const td_thragent_t *ta_p, struct ps_prochandle **ph_pp);
139 (*p_td_ta_get_nthreads) (const td_thragent_t *ta_p, int *nthread_p);
141 (*p_td_ta_tsd_iter) (const td_thragent_t *ta_p, td_key_iter_f *cb, void *cbdata_p);
143 (*p_td_ta_thr_iter) (const td_thragent_t *ta_p, td_thr_iter_f *cb, void *cbdata_p, td_thr_state_e state,
144 int ti_pri, sigset_t *ti_sigmask_p, unsigned ti_user_flags);
146 (*p_td_thr_validate) (const td_thrhandle_t *th_p);
148 (*p_td_thr_tsd) (const td_thrhandle_t *th_p, const thread_key_t key, void **data_pp);
150 (*p_td_thr_get_info) (const td_thrhandle_t *th_p, td_thrinfo_t *ti_p);
152 (*p_td_thr_getfpregs) (const td_thrhandle_t *th_p, prfpregset_t *fpregset);
154 (*p_td_thr_getxregsize) (const td_thrhandle_t *th_p, int *xregsize);
156 (*p_td_thr_getxregs) (const td_thrhandle_t *th_p, const caddr_t xregset);
158 (*p_td_thr_sigsetmask) (const td_thrhandle_t *th_p, const sigset_t ti_sigmask);
160 (*p_td_thr_setprio) (const td_thrhandle_t *th_p, const int ti_pri);
162 (*p_td_thr_setsigpending) (const td_thrhandle_t *th_p, const uchar_t ti_pending_flag, const sigset_t ti_pending);
164 (*p_td_thr_setfpregs) (const td_thrhandle_t *th_p, const prfpregset_t *fpregset);
166 (*p_td_thr_setxregs) (const td_thrhandle_t *th_p, const caddr_t xregset);
168 (*p_td_ta_map_id2thr) (const td_thragent_t *ta_p, thread_t tid, td_thrhandle_t *th_p);
170 (*p_td_ta_map_lwp2thr) (const td_thragent_t *ta_p, lwpid_t lwpid, td_thrhandle_t *th_p);
172 (*p_td_thr_getgregs) (const td_thrhandle_t *th_p, prgregset_t regset);
174 (*p_td_thr_setgregs) (const td_thrhandle_t *th_p, const prgregset_t regset);
180 td_err_string - Convert a thread_db error code to a string
184 char * td_err_string (errcode)
188 Return the thread_db error string associated with errcode. If errcode
189 is unknown, then return a message.
194 td_err_string (errcode)
197 static struct string_map
199 {TD_OK, "generic \"call succeeded\""},
200 {TD_ERR, "generic error."},
201 {TD_NOTHR, "no thread can be found to satisfy query"},
202 {TD_NOSV, "no synch. variable can be found to satisfy query"},
203 {TD_NOLWP, "no lwp can be found to satisfy query"},
204 {TD_BADPH, "invalid process handle"},
205 {TD_BADTH, "invalid thread handle"},
206 {TD_BADSH, "invalid synchronization handle"},
207 {TD_BADTA, "invalid thread agent"},
208 {TD_BADKEY, "invalid key"},
209 {TD_NOMSG, "td_thr_event_getmsg() called when there was no message"},
210 {TD_NOFPREGS, "FPU register set not available for given thread"},
211 {TD_NOLIBTHREAD, "application not linked with libthread"},
212 {TD_NOEVENT, "requested event is not supported"},
213 {TD_NOCAPAB, "capability not available"},
214 {TD_DBERR, "Debugger service failed"},
215 {TD_NOAPLIC, "Operation not applicable to"},
216 {TD_NOTSD, "No thread specific data for this thread"},
217 {TD_MALLOC, "Malloc failed"},
218 {TD_PARTIALREG, "Only part of register set was writen/read"},
219 {TD_NOXREGS, "X register set not available for given thread"}
221 const int td_err_size = sizeof td_err_table / sizeof (struct string_map);
225 for (i = 0; i < td_err_size; i++)
226 if (td_err_table[i].num == errcode)
227 return td_err_table[i].str;
229 sprintf (buf, "Unknown thread_db error code: %d", errcode);
238 td_state_string - Convert a thread_db state code to a string
242 char * td_state_string (statecode)
246 Return the thread_db state string associated with statecode. If
247 statecode is unknown, then return a message.
252 td_state_string (statecode)
253 td_thr_state_e statecode;
255 static struct string_map
256 td_thr_state_table[] = {
257 {TD_THR_ANY_STATE, "any state"},
258 {TD_THR_UNKNOWN, "unknown"},
259 {TD_THR_STOPPED, "stopped"},
261 {TD_THR_ACTIVE, "active"},
262 {TD_THR_ZOMBIE, "zombie"},
263 {TD_THR_SLEEP, "sleep"},
264 {TD_THR_STOPPED_ASLEEP, "stopped asleep"}
266 const int td_thr_state_table_size = sizeof td_thr_state_table / sizeof (struct string_map);
270 for (i = 0; i < td_thr_state_table_size; i++)
271 if (td_thr_state_table[i].num == statecode)
272 return td_thr_state_table[i].str;
274 sprintf (buf, "Unknown thread_db state code: %d", statecode);
283 thread_to_lwp - Convert a Posix or Solaris thread id to a LWP id.
287 int thread_to_lwp (thread_id, default_lwp)
291 This function converts a Posix or Solaris thread id to a lightweight
292 process id. If thread_id is non-existent, that's an error. If it's
293 an inactive thread, then we return default_lwp.
297 This function probably shouldn't call error()...
302 thread_to_lwp (thread_id, default_lwp)
312 if (is_lwp (thread_id))
313 return thread_id; /* It's already an LWP id */
315 /* It's a thread. Convert to lwp */
317 pid = PIDGET (thread_id);
318 thread_id = GET_THREAD(thread_id);
320 val = p_td_ta_map_id2thr (main_ta, thread_id, &th);
322 error ("thread_to_lwp: td_ta_map_id2thr %s", td_err_string (val));
324 val = p_td_thr_get_info (&th, &ti);
327 error ("thread_to_lwp: td_thr_get_info: %s", td_err_string (val));
329 if (ti.ti_state != TD_THR_ACTIVE)
331 if (default_lwp != -1)
333 error ("thread_to_lwp: thread state not active: %s",
334 td_state_string (ti.ti_state));
337 lwp = BUILD_LWP (ti.ti_lid, pid);
346 lwp_to_thread - Convert a LWP id to a Posix or Solaris thread id.
350 int lwp_to_thread (lwp_id)
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.
359 This function probably shouldn't call error()...
374 return lwp; /* It's already a thread id */
376 /* It's an lwp. Convert it to a thread id. */
381 val = p_td_ta_map_lwp2thr (main_ta, lwp, &th);
383 error ("lwp_to_thread: td_thr_get_info: %s.", td_err_string (val));
385 val = p_td_thr_get_info (&th, &ti);
388 error ("lwp_to_thread: td_thr_get_info: %s.", td_err_string (val));
390 thread_id = BUILD_THREAD (ti.ti_tid, pid);
399 save_inferior_pid - Save inferior_pid on the cleanup list
400 restore_inferior_pid - Restore inferior_pid from the cleanup list
404 struct cleanup *save_inferior_pid ()
405 void restore_inferior_pid (int pid)
409 These two functions act in unison to restore inferior_pid in
414 inferior_pid is a global variable that needs to be changed by many of
415 these routines before calling functions in procfs.c. In order to
416 guarantee that inferior_pid gets restored (in case of errors), you
417 need to call save_inferior_pid before changing it. At the end of the
418 function, you should invoke do_cleanups to restore it.
423 static struct cleanup *
426 return make_cleanup (restore_inferior_pid, inferior_pid);
430 restore_inferior_pid (pid)
437 /* Most target vector functions from here on actually just pass through to
438 procfs.c, as they don't need to do anything specific for threads. */
443 sol_thread_open (arg, from_tty)
447 procfs_ops.to_open (arg, from_tty);
450 /* Attach to process PID, then initialize for debugging it
451 and wait for the trace-trap that results from attaching. */
454 sol_thread_attach (args, from_tty)
458 procfs_ops.to_attach (args, from_tty);
460 /* XXX - might want to iterate over all the threads and register them. */
463 /* Take a program previously attached to and detaches it.
464 The program resumes execution and will no longer stop
465 on signals, etc. We'd better not have left any breakpoints
466 in the program or it'll die when it hits one. For this
467 to work, it may be necessary for the process to have been
468 previously attached. It *might* work if the program was
469 started via the normal ptrace (PTRACE_TRACEME). */
472 sol_thread_detach (args, from_tty)
476 procfs_ops.to_detach (args, from_tty);
479 /* Resume execution of process PID. If STEP is nozero, then
480 just single step it. If SIGNAL is nonzero, restart it with that
481 signal activated. We may have to convert pid from a thread-id to an LWP id
485 sol_thread_resume (pid, step, signo)
488 enum target_signal signo;
490 struct cleanup *old_chain;
492 old_chain = save_inferior_pid ();
494 inferior_pid = thread_to_lwp (inferior_pid, main_ph.pid);
498 pid = thread_to_lwp (pid, -2);
499 if (pid == -2) /* Inactive thread */
500 error ("This version of Solaris can't start inactive threads.");
503 procfs_ops.to_resume (pid, step, signo);
505 do_cleanups (old_chain);
508 /* Wait for any threads to stop. We may have to convert PID from a thread id
509 to a LWP id, and vice versa on the way out. */
512 sol_thread_wait (pid, ourstatus)
514 struct target_waitstatus *ourstatus;
518 struct cleanup *old_chain;
520 save_pid = inferior_pid;
521 old_chain = save_inferior_pid ();
523 inferior_pid = thread_to_lwp (inferior_pid, main_ph.pid);
526 pid = thread_to_lwp (pid, -1);
528 rtnval = procfs_ops.to_wait (pid, ourstatus);
530 if (rtnval != save_pid
531 && !in_thread_list (rtnval))
533 fprintf_unfiltered (gdb_stderr, "[New %s]\n",
534 target_pid_to_str (rtnval));
538 /* During process initialization, we may get here without the thread package
539 being initialized, since that can only happen after we've found the shared
542 /* Map the LWP of interest back to the appropriate thread ID */
544 rtnval = lwp_to_thread (rtnval);
546 do_cleanups (old_chain);
552 sol_thread_fetch_registers (regno)
556 td_thrhandle_t thandle;
559 prfpregset_t fpregset;
565 /* Convert inferior_pid into a td_thrhandle_t */
567 thread = GET_THREAD (inferior_pid);
570 error ("sol_thread_fetch_registers: thread == 0");
572 val = p_td_ta_map_id2thr (main_ta, thread, &thandle);
574 error ("sol_thread_fetch_registers: td_ta_map_id2thr: %s",
575 td_err_string (val));
577 /* Get the integer regs */
579 val = p_td_thr_getgregs (&thandle, gregset);
581 && val != TD_PARTIALREG)
582 error ("sol_thread_fetch_registers: td_thr_getgregs %s",
583 td_err_string (val));
585 /* For the sparc, TD_PARTIALREG means that only i0->i7, l0->l7, pc and sp
586 are saved (by a thread context switch). */
588 /* And, now the fp regs */
590 val = p_td_thr_getfpregs (&thandle, &fpregset);
592 && val != TD_NOFPREGS)
593 error ("sol_thread_fetch_registers: td_thr_getfpregs %s",
594 td_err_string (val));
596 /* Note that we must call supply_{g fp}regset *after* calling the td routines
597 because the td routines call ps_lget* which affect the values stored in the
600 supply_gregset (gregset);
601 supply_fpregset (fpregset);
604 /* thread_db doesn't seem to handle this right */
605 val = td_thr_getxregsize (&thandle, &xregsize);
606 if (val != TD_OK && val != TD_NOXREGS)
607 error ("sol_thread_fetch_registers: td_thr_getxregsize %s",
608 td_err_string (val));
612 xregset = alloca (xregsize);
613 val = td_thr_getxregs (&thandle, xregset);
615 error ("sol_thread_fetch_registers: td_thr_getxregs %s",
616 td_err_string (val));
622 sol_thread_store_registers (regno)
626 td_thrhandle_t thandle;
629 prfpregset_t fpregset;
635 /* Convert inferior_pid into a td_thrhandle_t */
637 thread = GET_THREAD (inferior_pid);
639 val = p_td_ta_map_id2thr (main_ta, thread, &thandle);
641 error ("sol_thread_store_registers: td_ta_map_id2thr %s",
642 td_err_string (val));
645 { /* Not writing all the regs */
646 val = p_td_thr_getgregs (&thandle, regset);
648 error ("sol_thread_store_registers: td_thr_getgregs %s",
649 td_err_string (val));
650 val = p_td_thr_getfpregs (&thandle, &fpregset);
652 error ("sol_thread_store_registers: td_thr_getfpregs %s",
653 td_err_string (val));
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_store_registers: td_thr_getxregsize %s",
660 td_err_string (val));
664 xregset = alloca (xregsize);
665 val = td_thr_getxregs (&thandle, xregset);
667 error ("sol_thread_store_registers: td_thr_getxregs %s",
668 td_err_string (val));
673 fill_gregset (regset, regno);
674 fill_fpregset (fpregset, regno);
676 val = p_td_thr_setgregs (&thandle, regset);
678 error ("sol_thread_store_registers: td_thr_setgregs %s",
679 td_err_string (val));
680 val = p_td_thr_setfpregs (&thandle, &fpregset);
682 error ("sol_thread_store_registers: td_thr_setfpregs %s",
683 td_err_string (val));
686 /* thread_db doesn't seem to handle this right */
687 val = td_thr_getxregsize (&thandle, &xregsize);
688 if (val != TD_OK && val != TD_NOXREGS)
689 error ("sol_thread_store_registers: td_thr_getxregsize %s",
690 td_err_string (val));
692 /* Should probably do something about writing the xregs here, but what are
697 /* Get ready to modify the registers array. On machines which store
698 individual registers, this doesn't need to do anything. On machines
699 which store all the registers in one fell swoop, this makes sure
700 that registers contains all the registers from the program being
704 sol_thread_prepare_to_store ()
706 procfs_ops.to_prepare_to_store ();
710 sol_thread_xfer_memory (memaddr, myaddr, len, dowrite, target)
715 struct target_ops *target; /* ignored */
718 struct cleanup *old_chain;
720 old_chain = save_inferior_pid ();
722 if (is_thread (inferior_pid))
723 inferior_pid = main_ph.pid; /* It's a thread. Convert to lwp */
725 retval = procfs_ops.to_xfer_memory (memaddr, myaddr, len, dowrite, target);
727 do_cleanups (old_chain);
732 /* Print status information about what we're accessing. */
735 sol_thread_files_info (ignore)
736 struct target_ops *ignore;
738 procfs_ops.to_files_info (ignore);
742 sol_thread_kill_inferior ()
744 procfs_ops.to_kill ();
748 sol_thread_notice_signals (pid)
751 procfs_ops.to_notice_signals (pid);
754 void target_new_objfile PARAMS ((struct objfile *objfile));
756 /* Fork an inferior process, and start debugging it with /proc. */
759 sol_thread_create_inferior (exec_file, allargs, env)
764 procfs_ops.to_create_inferior (exec_file, allargs, env);
766 if (sol_thread_active)
768 main_ph.pid = inferior_pid; /* Save for xfer_memory */
770 push_target (&sol_thread_ops);
772 inferior_pid = lwp_to_thread (inferior_pid);
774 add_thread (inferior_pid);
778 /* This routine is called whenever a new symbol table is read in, or when all
779 symbol tables are removed. libthread_db can only be initialized when it
780 finds the right variables in libthread.so. Since it's a shared library,
781 those variables don't show up until the library gets mapped and the symbol
785 sol_thread_new_objfile (objfile)
786 struct objfile *objfile;
792 sol_thread_active = 0;
797 /* Now, initialize the thread debugging library. This needs to be done after
798 the shared libraries are located because it needs information from the
799 user's thread library. */
803 error ("target_new_objfile: td_init: %s", td_err_string (val));
805 val = p_td_ta_new (&main_ph, &main_ta);
806 if (val == TD_NOLIBTHREAD)
808 else if (val != TD_OK)
809 error ("target_new_objfile: td_ta_new: %s", td_err_string (val));
811 sol_thread_active = 1;
814 /* Clean up after the inferior dies. */
817 sol_thread_mourn_inferior ()
819 procfs_ops.to_mourn_inferior ();
822 /* Mark our target-struct as eligible for stray "run" and "attach" commands. */
825 sol_thread_can_run ()
827 return procfs_suppress_run;
831 sol_thread_alive (pid)
840 procfs_ops.to_stop ();
843 /* These routines implement the lower half of the thread_db interface. Ie: the
846 /* The next four routines are called by thread_db to tell us to stop and stop
847 a particular process or lwp. Since GDB ensures that these are all stopped
848 by the time we call anything in thread_db, these routines need to do
852 ps_pstop (const struct ps_prochandle *ph)
858 ps_pcontinue (const struct ps_prochandle *ph)
864 ps_lstop (const struct ps_prochandle *ph, lwpid_t lwpid)
870 ps_lcontinue (const struct ps_prochandle *ph, lwpid_t lwpid)
876 ps_pglobal_lookup (const struct ps_prochandle *ph, const char *ld_object_name,
877 const char *ld_symbol_name, paddr_t *ld_symbol_addr)
879 struct minimal_symbol *ms;
881 ms = lookup_minimal_symbol (ld_symbol_name, NULL, NULL);
886 *ld_symbol_addr = SYMBOL_VALUE_ADDRESS (ms);
891 /* Common routine for reading and writing memory. */
894 rw_common (int dowrite, const struct ps_prochandle *ph, paddr_t addr,
897 struct cleanup *old_chain;
899 old_chain = save_inferior_pid ();
901 if (is_thread (inferior_pid))
902 inferior_pid = main_ph.pid; /* It's a thread. Convert to lwp */
908 cc = procfs_ops.to_xfer_memory (addr, buf, size, dowrite, &procfs_ops);
913 print_sys_errmsg ("ps_pdread (): read", errno);
915 print_sys_errmsg ("ps_pdread (): write", errno);
917 do_cleanups (old_chain);
925 do_cleanups (old_chain);
931 ps_pdread (const struct ps_prochandle *ph, paddr_t addr, char *buf, int size)
933 return rw_common (0, ph, addr, buf, size);
937 ps_pdwrite (const struct ps_prochandle *ph, paddr_t addr, char *buf, int size)
939 return rw_common (1, ph, addr, buf, size);
943 ps_ptread (const struct ps_prochandle *ph, paddr_t addr, char *buf, int size)
945 return rw_common (0, ph, addr, buf, size);
949 ps_ptwrite (const struct ps_prochandle *ph, paddr_t addr, char *buf, int size)
951 return rw_common (1, ph, addr, buf, size);
954 /* Get integer regs */
957 ps_lgetregs (const struct ps_prochandle *ph, lwpid_t lwpid,
960 struct cleanup *old_chain;
962 old_chain = save_inferior_pid ();
964 inferior_pid = BUILD_LWP (lwpid, PIDGET (inferior_pid));
966 procfs_ops.to_fetch_registers (-1);
967 fill_gregset (gregset, -1);
969 do_cleanups (old_chain);
974 /* Set integer regs */
977 ps_lsetregs (const struct ps_prochandle *ph, lwpid_t lwpid,
978 const prgregset_t gregset)
980 struct cleanup *old_chain;
982 old_chain = save_inferior_pid ();
984 inferior_pid = BUILD_LWP (lwpid, PIDGET (inferior_pid));
986 supply_gregset (gregset);
987 procfs_ops.to_store_registers (-1);
989 do_cleanups (old_chain);
995 ps_plog (const char *fmt, ...)
999 va_start (args, fmt);
1001 vfprintf_filtered (gdb_stderr, fmt, args);
1004 /* Get size of extra register set. Currently a noop. */
1007 ps_lgetxregsize (const struct ps_prochandle *ph, lwpid_t lwpid, int *xregsize)
1014 val = get_lwp_fd (ph, lwpid, &lwp_fd);
1018 if (ioctl (lwp_fd, PIOCGXREGSIZE, ®size))
1020 if (errno == EINVAL)
1021 return PS_NOFREGS; /* XXX Wrong code, but this is the closest
1022 thing in proc_service.h */
1024 print_sys_errmsg ("ps_lgetxregsize (): PIOCGXREGSIZE", errno);
1032 /* Get extra register set. Currently a noop. */
1035 ps_lgetxregs (const struct ps_prochandle *ph, lwpid_t lwpid, caddr_t xregset)
1041 val = get_lwp_fd (ph, lwpid, &lwp_fd);
1045 if (ioctl (lwp_fd, PIOCGXREG, xregset))
1047 print_sys_errmsg ("ps_lgetxregs (): PIOCGXREG", errno);
1055 /* Set extra register set. Currently a noop. */
1058 ps_lsetxregs (const struct ps_prochandle *ph, lwpid_t lwpid, caddr_t xregset)
1064 val = get_lwp_fd (ph, lwpid, &lwp_fd);
1068 if (ioctl (lwp_fd, PIOCSXREG, xregset))
1070 print_sys_errmsg ("ps_lsetxregs (): PIOCSXREG", errno);
1078 /* Get floating-point regs. */
1081 ps_lgetfpregs (const struct ps_prochandle *ph, lwpid_t lwpid,
1082 prfpregset_t *fpregset)
1084 struct cleanup *old_chain;
1086 old_chain = save_inferior_pid ();
1088 inferior_pid = BUILD_LWP (lwpid, PIDGET (inferior_pid));
1090 procfs_ops.to_fetch_registers (-1);
1091 fill_fpregset (*fpregset, -1);
1093 do_cleanups (old_chain);
1098 /* Set floating-point regs. */
1101 ps_lsetfpregs (const struct ps_prochandle *ph, lwpid_t lwpid,
1102 const prfpregset_t *fpregset)
1104 struct cleanup *old_chain;
1106 old_chain = save_inferior_pid ();
1108 inferior_pid = BUILD_LWP (lwpid, PIDGET (inferior_pid));
1110 supply_fpregset (*fpregset);
1111 procfs_ops.to_store_registers (-1);
1113 do_cleanups (old_chain);
1118 /* Convert a pid to printable form. */
1121 solaris_pid_to_str (pid)
1124 static char buf[100];
1126 if (is_thread (pid))
1130 lwp = thread_to_lwp (pid, -2);
1133 sprintf (buf, "Thread %d (LWP %d)", GET_THREAD (pid), GET_LWP (lwp));
1135 sprintf (buf, "Thread %d ", GET_THREAD (pid));
1138 sprintf (buf, "LWP %d ", GET_LWP (pid));
1143 struct target_ops sol_thread_ops = {
1144 "solaris-threads", /* to_shortname */
1145 "Solaris threads and pthread.", /* to_longname */
1146 "Solaris threads and pthread support.", /* to_doc */
1147 sol_thread_open, /* to_open */
1149 sol_thread_attach, /* to_attach */
1150 sol_thread_detach, /* to_detach */
1151 sol_thread_resume, /* to_resume */
1152 sol_thread_wait, /* to_wait */
1153 sol_thread_fetch_registers, /* to_fetch_registers */
1154 sol_thread_store_registers, /* to_store_registers */
1155 sol_thread_prepare_to_store, /* to_prepare_to_store */
1156 sol_thread_xfer_memory, /* to_xfer_memory */
1157 sol_thread_files_info, /* to_files_info */
1158 memory_insert_breakpoint, /* to_insert_breakpoint */
1159 memory_remove_breakpoint, /* to_remove_breakpoint */
1160 terminal_init_inferior, /* to_terminal_init */
1161 terminal_inferior, /* to_terminal_inferior */
1162 terminal_ours_for_output, /* to_terminal_ours_for_output */
1163 terminal_ours, /* to_terminal_ours */
1164 child_terminal_info, /* to_terminal_info */
1165 sol_thread_kill_inferior, /* to_kill */
1167 0, /* to_lookup_symbol */
1168 sol_thread_create_inferior, /* to_create_inferior */
1169 sol_thread_mourn_inferior, /* to_mourn_inferior */
1170 sol_thread_can_run, /* to_can_run */
1171 sol_thread_notice_signals, /* to_notice_signals */
1172 sol_thread_alive, /* to_thread_alive */
1173 sol_thread_stop, /* to_stop */
1174 process_stratum, /* to_stratum */
1176 1, /* to_has_all_memory */
1177 1, /* to_has_memory */
1178 1, /* to_has_stack */
1179 1, /* to_has_registers */
1180 1, /* to_has_execution */
1182 0, /* sections_end */
1183 OPS_MAGIC /* to_magic */
1187 _initialize_sol_thread ()
1191 dlhandle = dlopen ("libthread_db.so.1", RTLD_NOW);
1195 #define resolve(X) \
1196 if (!(p_##X = dlsym (dlhandle, #X))) \
1200 resolve (td_ta_new);
1201 resolve (td_ta_delete);
1203 resolve (td_ta_get_ph);
1204 resolve (td_ta_get_nthreads);
1205 resolve (td_ta_tsd_iter);
1206 resolve (td_ta_thr_iter);
1207 resolve (td_thr_validate);
1208 resolve (td_thr_tsd);
1209 resolve (td_thr_get_info);
1210 resolve (td_thr_getfpregs);
1211 resolve (td_thr_getxregsize);
1212 resolve (td_thr_getxregs);
1213 resolve (td_thr_sigsetmask);
1214 resolve (td_thr_setprio);
1215 resolve (td_thr_setsigpending);
1216 resolve (td_thr_setfpregs);
1217 resolve (td_thr_setxregs);
1218 resolve (td_ta_map_id2thr);
1219 resolve (td_ta_map_lwp2thr);
1220 resolve (td_thr_getgregs);
1221 resolve (td_thr_setgregs);
1223 add_target (&sol_thread_ops);
1225 procfs_suppress_run = 1;
1231 fprintf_unfiltered (gdb_stderr, "[GDB will not be able to debug user-mode threads: %s]\n", dlerror ());