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, ®size))
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