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