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