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