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