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