Add h8300.exp.
[deliverable/binutils-gdb.git] / gdb / sol-thread.c
CommitLineData
8fc2b417
SG
1/* Low level interface for debugging Solaris threads for GDB, the GNU debugger.
2 Copyright 1996 Free Software Foundation, Inc.
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
SG
48#include "defs.h"
49
934741a1
SG
50/* Undefine gregset_t and fpregset_t to avoid conflict with defs in xm file. */
51
8fc2b417
SG
52#ifdef gregset_t
53#undef gregset_t
54#endif
55
56#ifdef fpregset_t
57#undef fpregset_t
58#endif
59
934741a1 60#include <thread.h>
8fc2b417
SG
61#include <proc_service.h>
62#include <thread_db.h>
fdfa3315 63#include "gdbthread.h"
8fc2b417
SG
64#include "target.h"
65#include "inferior.h"
66#include <fcntl.h>
67#include <unistd.h>
68#include <sys/stat.h>
4915acad 69#include <dlfcn.h>
8fc2b417 70
8fc2b417
SG
71extern struct target_ops sol_thread_ops; /* Forward declaration */
72
73extern int procfs_suppress_run;
934741a1
SG
74extern struct target_ops procfs_ops; /* target vector for procfs.c */
75
a50cedad
SG
76/* Note that these prototypes differ slightly from those used in procfs.c
77 for of two reasons. One, we can't use gregset_t, as that's got a whole
78 different meaning under Solaris (also, see above). Two, we can't use the
79 pointer form here as these are actually arrays of ints (for Sparc's at
80 least), and are automatically coerced into pointers to ints when used as
81 parameters. That makes it impossible to avoid a compiler warning when
82 passing pr{g fp}regset_t's from a parameter to an argument of one of
83 these functions. */
84
934741a1
SG
85extern void supply_gregset PARAMS ((const prgregset_t));
86extern void fill_gregset PARAMS ((prgregset_t, int));
87extern void supply_fpregset PARAMS ((const prfpregset_t));
88extern void fill_fpregset PARAMS ((prfpregset_t, int));
8fc2b417 89
a50cedad
SG
90/* This struct is defined by us, but mainly used for the proc_service interface.
91 We don't have much use for it, except as a handy place to get a real pid
92 for memory accesses. */
93
8fc2b417
SG
94struct ps_prochandle
95{
96 pid_t pid;
97};
98
934741a1
SG
99struct string_map
100{
101 int num;
102 char *str;
103};
104
8fc2b417
SG
105static struct ps_prochandle main_ph;
106static td_thragent_t *main_ta;
8fc2b417
SG
107static int sol_thread_active = 0;
108
934741a1
SG
109static struct cleanup * save_inferior_pid PARAMS ((void));
110static void restore_inferior_pid PARAMS ((int pid));
111static char *td_err_string PARAMS ((td_err_e errcode));
112static char *td_state_string PARAMS ((td_thr_state_e statecode));
113static int thread_to_lwp PARAMS ((int thread_id, int default_lwp));
114static void sol_thread_resume PARAMS ((int pid, int step,
115 enum target_signal signo));
116static int lwp_to_thread PARAMS ((int lwp));
117
118#define THREAD_FLAG 0x80000000
119#define is_thread(ARG) (((ARG) & THREAD_FLAG) != 0)
120#define is_lwp(ARG) (((ARG) & THREAD_FLAG) == 0)
121#define GET_LWP(LWP_ID) (TIDGET(LWP_ID))
122#define GET_THREAD(THREAD_ID) (((THREAD_ID) >> 16) & 0x7fff)
123#define BUILD_LWP(LWP_ID, PID) ((LWP_ID) << 16 | (PID))
124#define BUILD_THREAD(THREAD_ID, PID) (THREAD_FLAG | BUILD_LWP (THREAD_ID, PID))
4915acad
SG
125
126/* Pointers to routines from lithread_db resolved by dlopen() */
127
128static void
129 (*p_td_log) (const int on_off);
130static td_err_e
131 (*p_td_ta_new) (const struct ps_prochandle *ph_p, td_thragent_t **ta_pp);
132static td_err_e
133 (*p_td_ta_delete) (td_thragent_t *ta_p);
134static td_err_e
135 (*p_td_init) (void);
136static td_err_e
137 (*p_td_ta_get_ph) (const td_thragent_t *ta_p, struct ps_prochandle **ph_pp);
138static td_err_e
139 (*p_td_ta_get_nthreads) (const td_thragent_t *ta_p, int *nthread_p);
140static td_err_e
141 (*p_td_ta_tsd_iter) (const td_thragent_t *ta_p, td_key_iter_f *cb, void *cbdata_p);
142static td_err_e
143 (*p_td_ta_thr_iter) (const td_thragent_t *ta_p, td_thr_iter_f *cb, void *cbdata_p, td_thr_state_e state,
144 int ti_pri, sigset_t *ti_sigmask_p, unsigned ti_user_flags);
145static td_err_e
146 (*p_td_thr_validate) (const td_thrhandle_t *th_p);
147static td_err_e
148 (*p_td_thr_tsd) (const td_thrhandle_t *th_p, const thread_key_t key, void **data_pp);
149static td_err_e
150 (*p_td_thr_get_info) (const td_thrhandle_t *th_p, td_thrinfo_t *ti_p);
151static td_err_e
152 (*p_td_thr_getfpregs) (const td_thrhandle_t *th_p, prfpregset_t *fpregset);
153static td_err_e
154 (*p_td_thr_getxregsize) (const td_thrhandle_t *th_p, int *xregsize);
155static td_err_e
156 (*p_td_thr_getxregs) (const td_thrhandle_t *th_p, const caddr_t xregset);
157static td_err_e
158 (*p_td_thr_sigsetmask) (const td_thrhandle_t *th_p, const sigset_t ti_sigmask);
159static td_err_e
160 (*p_td_thr_setprio) (const td_thrhandle_t *th_p, const int ti_pri);
161static td_err_e
162 (*p_td_thr_setsigpending) (const td_thrhandle_t *th_p, const uchar_t ti_pending_flag, const sigset_t ti_pending);
163static td_err_e
164 (*p_td_thr_setfpregs) (const td_thrhandle_t *th_p, const prfpregset_t *fpregset);
165static td_err_e
166 (*p_td_thr_setxregs) (const td_thrhandle_t *th_p, const caddr_t xregset);
167static td_err_e
168 (*p_td_ta_map_id2thr) (const td_thragent_t *ta_p, thread_t tid, td_thrhandle_t *th_p);
169static td_err_e
170 (*p_td_ta_map_lwp2thr) (const td_thragent_t *ta_p, lwpid_t lwpid, td_thrhandle_t *th_p);
171static td_err_e
172 (*p_td_thr_getgregs) (const td_thrhandle_t *th_p, prgregset_t regset);
173static td_err_e
174 (*p_td_thr_setgregs) (const td_thrhandle_t *th_p, const prgregset_t regset);
8fc2b417 175\f
934741a1
SG
176/*
177
178LOCAL FUNCTION
179
180 td_err_string - Convert a thread_db error code to a string
181
182SYNOPSIS
183
184 char * td_err_string (errcode)
185
186DESCRIPTION
187
188 Return the thread_db error string associated with errcode. If errcode
189 is unknown, then return a message.
190
191 */
192
193static char *
194td_err_string (errcode)
195 td_err_e errcode;
196{
197 static struct string_map
198 td_err_table[] = {
199 {TD_OK, "generic \"call succeeded\""},
200 {TD_ERR, "generic error."},
201 {TD_NOTHR, "no thread can be found to satisfy query"},
202 {TD_NOSV, "no synch. variable can be found to satisfy query"},
203 {TD_NOLWP, "no lwp can be found to satisfy query"},
204 {TD_BADPH, "invalid process handle"},
205 {TD_BADTH, "invalid thread handle"},
206 {TD_BADSH, "invalid synchronization handle"},
207 {TD_BADTA, "invalid thread agent"},
208 {TD_BADKEY, "invalid key"},
209 {TD_NOMSG, "td_thr_event_getmsg() called when there was no message"},
210 {TD_NOFPREGS, "FPU register set not available for given thread"},
211 {TD_NOLIBTHREAD, "application not linked with libthread"},
212 {TD_NOEVENT, "requested event is not supported"},
213 {TD_NOCAPAB, "capability not available"},
214 {TD_DBERR, "Debugger service failed"},
215 {TD_NOAPLIC, "Operation not applicable to"},
216 {TD_NOTSD, "No thread specific data for this thread"},
217 {TD_MALLOC, "Malloc failed"},
218 {TD_PARTIALREG, "Only part of register set was writen/read"},
219 {TD_NOXREGS, "X register set not available for given thread"}
220 };
221 const int td_err_size = sizeof td_err_table / sizeof (struct string_map);
222 int i;
223 static char buf[50];
224
225 for (i = 0; i < td_err_size; i++)
226 if (td_err_table[i].num == errcode)
227 return td_err_table[i].str;
228
229 sprintf (buf, "Unknown thread_db error code: %d", errcode);
8fc2b417 230
934741a1
SG
231 return buf;
232}
233\f
234/*
8fc2b417 235
934741a1 236LOCAL FUNCTION
8fc2b417 237
934741a1
SG
238 td_state_string - Convert a thread_db state code to a string
239
240SYNOPSIS
241
242 char * td_state_string (statecode)
243
244DESCRIPTION
245
246 Return the thread_db state string associated with statecode. If
247 statecode is unknown, then return a message.
248
249 */
250
251static char *
252td_state_string (statecode)
253 td_thr_state_e statecode;
254{
255 static struct string_map
256 td_thr_state_table[] = {
257 {TD_THR_ANY_STATE, "any state"},
258 {TD_THR_UNKNOWN, "unknown"},
259 {TD_THR_STOPPED, "stopped"},
260 {TD_THR_RUN, "run"},
261 {TD_THR_ACTIVE, "active"},
262 {TD_THR_ZOMBIE, "zombie"},
263 {TD_THR_SLEEP, "sleep"},
264 {TD_THR_STOPPED_ASLEEP, "stopped asleep"}
265 };
266 const int td_thr_state_table_size = sizeof td_thr_state_table / sizeof (struct string_map);
267 int i;
268 static char buf[50];
269
270 for (i = 0; i < td_thr_state_table_size; i++)
271 if (td_thr_state_table[i].num == statecode)
272 return td_thr_state_table[i].str;
273
274 sprintf (buf, "Unknown thread_db state code: %d", statecode);
275
276 return buf;
277}
278\f
279/*
280
281LOCAL FUNCTION
282
283 thread_to_lwp - Convert a Posix or Solaris thread id to a LWP id.
284
285SYNOPSIS
286
287 int thread_to_lwp (thread_id, default_lwp)
288
289DESCRIPTION
290
291 This function converts a Posix or Solaris thread id to a lightweight
292 process id. If thread_id is non-existent, that's an error. If it's
293 an inactive thread, then we return default_lwp.
294
295NOTES
296
297 This function probably shouldn't call error()...
298
299 */
8fc2b417
SG
300
301static int
302thread_to_lwp (thread_id, default_lwp)
303 int thread_id;
304 int default_lwp;
305{
306 td_thrinfo_t ti;
307 td_thrhandle_t th;
308 td_err_e val;
309 int pid;
310 int lwp;
311
934741a1 312 if (is_lwp (thread_id))
8fc2b417
SG
313 return thread_id; /* It's already an LWP id */
314
315 /* It's a thread. Convert to lwp */
316
934741a1
SG
317 pid = PIDGET (thread_id);
318 thread_id = GET_THREAD(thread_id);
8fc2b417 319
4915acad 320 val = p_td_ta_map_id2thr (main_ta, thread_id, &th);
8fc2b417 321 if (val != TD_OK)
934741a1 322 error ("thread_to_lwp: td_ta_map_id2thr %s", td_err_string (val));
8fc2b417 323
4915acad 324 val = p_td_thr_get_info (&th, &ti);
8fc2b417
SG
325
326 if (val != TD_OK)
934741a1 327 error ("thread_to_lwp: td_thr_get_info: %s", td_err_string (val));
8fc2b417
SG
328
329 if (ti.ti_state != TD_THR_ACTIVE)
330 {
331 if (default_lwp != -1)
332 return default_lwp;
934741a1
SG
333 error ("thread_to_lwp: thread state not active: %s",
334 td_state_string (ti.ti_state));
8fc2b417
SG
335 }
336
934741a1 337 lwp = BUILD_LWP (ti.ti_lid, pid);
8fc2b417
SG
338
339 return lwp;
340}
a50cedad
SG
341\f
342/*
343
344LOCAL FUNCTION
345
346 lwp_to_thread - Convert a LWP id to a Posix or Solaris thread id.
347
348SYNOPSIS
349
350 int lwp_to_thread (lwp_id)
8fc2b417 351
a50cedad
SG
352DESCRIPTION
353
354 This function converts a lightweight process id to a Posix or Solaris
355 thread id. If thread_id is non-existent, that's an error.
356
357NOTES
358
359 This function probably shouldn't call error()...
360
361 */
8fc2b417 362
8fc2b417
SG
363static int
364lwp_to_thread (lwp)
365 int lwp;
366{
367 td_thrinfo_t ti;
368 td_thrhandle_t th;
369 td_err_e val;
370 int pid;
371 int thread_id;
372
934741a1 373 if (is_thread (lwp))
8fc2b417
SG
374 return lwp; /* It's already a thread id */
375
376 /* It's an lwp. Convert it to a thread id. */
377
934741a1
SG
378 pid = PIDGET (lwp);
379 lwp = GET_LWP (lwp);
8fc2b417 380
4915acad 381 val = p_td_ta_map_lwp2thr (main_ta, lwp, &th);
8fc2b417 382 if (val != TD_OK)
934741a1 383 error ("lwp_to_thread: td_thr_get_info: %s.", td_err_string (val));
8fc2b417 384
4915acad 385 val = p_td_thr_get_info (&th, &ti);
8fc2b417
SG
386
387 if (val != TD_OK)
934741a1 388 error ("lwp_to_thread: td_thr_get_info: %s.", td_err_string (val));
8fc2b417 389
934741a1 390 thread_id = BUILD_THREAD (ti.ti_tid, pid);
8fc2b417
SG
391
392 return thread_id;
393}
934741a1 394\f
a50cedad
SG
395/*
396
397LOCAL FUNCTION
398
399 save_inferior_pid - Save inferior_pid on the cleanup list
400 restore_inferior_pid - Restore inferior_pid from the cleanup list
401
402SYNOPSIS
403
404 struct cleanup *save_inferior_pid ()
405 void restore_inferior_pid (int pid)
406
407DESCRIPTION
408
409 These two functions act in unison to restore inferior_pid in
410 case of an error.
411
412NOTES
413
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.
419
420 */
421
422
934741a1
SG
423static struct cleanup *
424save_inferior_pid ()
425{
426 return make_cleanup (restore_inferior_pid, inferior_pid);
427}
8fc2b417 428
934741a1
SG
429static void
430restore_inferior_pid (pid)
431 int pid;
432{
433 inferior_pid = pid;
434}
435\f
a50cedad
SG
436
437/* Most target vector functions from here on actually just pass through to
438 procfs.c, as they don't need to do anything specific for threads. */
439
440
8fc2b417
SG
441/* ARGSUSED */
442static void
443sol_thread_open (arg, from_tty)
444 char *arg;
445 int from_tty;
446{
447 procfs_ops.to_open (arg, from_tty);
448}
449
450/* Attach to process PID, then initialize for debugging it
451 and wait for the trace-trap that results from attaching. */
452
453static void
454sol_thread_attach (args, from_tty)
455 char *args;
456 int from_tty;
457{
458 procfs_ops.to_attach (args, from_tty);
459
460 /* XXX - might want to iterate over all the threads and register them. */
461}
462
463/* Take a program previously attached to and detaches it.
464 The program resumes execution and will no longer stop
465 on signals, etc. We'd better not have left any breakpoints
466 in the program or it'll die when it hits one. For this
467 to work, it may be necessary for the process to have been
468 previously attached. It *might* work if the program was
469 started via the normal ptrace (PTRACE_TRACEME). */
470
471static void
472sol_thread_detach (args, from_tty)
473 char *args;
474 int from_tty;
475{
476 procfs_ops.to_detach (args, from_tty);
477}
478
479/* Resume execution of process PID. If STEP is nozero, then
480 just single step it. If SIGNAL is nonzero, restart it with that
a50cedad
SG
481 signal activated. We may have to convert pid from a thread-id to an LWP id
482 for procfs. */
8fc2b417
SG
483
484static void
485sol_thread_resume (pid, step, signo)
486 int pid;
487 int step;
488 enum target_signal signo;
489{
934741a1 490 struct cleanup *old_chain;
8fc2b417 491
934741a1 492 old_chain = save_inferior_pid ();
8fc2b417
SG
493
494 inferior_pid = thread_to_lwp (inferior_pid, main_ph.pid);
495
496 if (pid != -1)
a50cedad
SG
497 {
498 pid = thread_to_lwp (pid, -2);
499 if (pid == -2) /* Inactive thread */
500 error ("This version of Solaris can't start inactive threads.");
501 }
8fc2b417
SG
502
503 procfs_ops.to_resume (pid, step, signo);
504
934741a1 505 do_cleanups (old_chain);
8fc2b417
SG
506}
507
a50cedad
SG
508/* Wait for any threads to stop. We may have to convert PID from a thread id
509 to a LWP id, and vice versa on the way out. */
8fc2b417
SG
510
511static int
512sol_thread_wait (pid, ourstatus)
513 int pid;
514 struct target_waitstatus *ourstatus;
515{
8fc2b417
SG
516 int rtnval;
517 int save_pid;
934741a1 518 struct cleanup *old_chain;
8fc2b417 519
8fc2b417 520 save_pid = inferior_pid;
934741a1 521 old_chain = save_inferior_pid ();
8fc2b417
SG
522
523 inferior_pid = thread_to_lwp (inferior_pid, main_ph.pid);
524
525 if (pid != -1)
526 pid = thread_to_lwp (pid, -1);
527
528 rtnval = procfs_ops.to_wait (pid, ourstatus);
529
530 if (rtnval != save_pid
531 && !in_thread_list (rtnval))
532 {
533 fprintf_unfiltered (gdb_stderr, "[New %s]\n",
534 target_pid_to_str (rtnval));
535 add_thread (rtnval);
536 }
537
8fc2b417
SG
538 /* During process initialization, we may get here without the thread package
539 being initialized, since that can only happen after we've found the shared
540 libs. */
541
542 /* Map the LWP of interest back to the appropriate thread ID */
543
544 rtnval = lwp_to_thread (rtnval);
545
934741a1
SG
546 do_cleanups (old_chain);
547
8fc2b417
SG
548 return rtnval;
549}
550
551static void
552sol_thread_fetch_registers (regno)
553 int regno;
554{
555 thread_t thread;
556 td_thrhandle_t thandle;
557 td_err_e val;
9b33e492 558 prgregset_t gregset;
8fc2b417 559 prfpregset_t fpregset;
934741a1 560#if 0
8fc2b417
SG
561 int xregsize;
562 caddr_t xregset;
934741a1 563#endif
8fc2b417 564
8fc2b417
SG
565 /* Convert inferior_pid into a td_thrhandle_t */
566
934741a1 567 thread = GET_THREAD (inferior_pid);
8fc2b417
SG
568
569 if (thread == 0)
570 error ("sol_thread_fetch_registers: thread == 0");
571
4915acad 572 val = p_td_ta_map_id2thr (main_ta, thread, &thandle);
8fc2b417 573 if (val != TD_OK)
934741a1
SG
574 error ("sol_thread_fetch_registers: td_ta_map_id2thr: %s",
575 td_err_string (val));
8fc2b417
SG
576
577 /* Get the integer regs */
578
4915acad 579 val = p_td_thr_getgregs (&thandle, gregset);
9b33e492
SG
580 if (val != TD_OK
581 && val != TD_PARTIALREG)
934741a1
SG
582 error ("sol_thread_fetch_registers: td_thr_getgregs %s",
583 td_err_string (val));
8fc2b417 584
9b33e492
SG
585 /* For the sparc, TD_PARTIALREG means that only i0->i7, l0->l7, pc and sp
586 are saved (by a thread context switch). */
587
8fc2b417
SG
588 /* And, now the fp regs */
589
4915acad 590 val = p_td_thr_getfpregs (&thandle, &fpregset);
9b33e492
SG
591 if (val != TD_OK
592 && val != TD_NOFPREGS)
934741a1
SG
593 error ("sol_thread_fetch_registers: td_thr_getfpregs %s",
594 td_err_string (val));
8fc2b417 595
9b33e492
SG
596/* Note that we must call supply_{g fp}regset *after* calling the td routines
597 because the td routines call ps_lget* which affect the values stored in the
598 registers array. */
599
600 supply_gregset (gregset);
601 supply_fpregset (fpregset);
602
8fc2b417
SG
603#if 0
604/* thread_db doesn't seem to handle this right */
605 val = td_thr_getxregsize (&thandle, &xregsize);
606 if (val != TD_OK && val != TD_NOXREGS)
934741a1
SG
607 error ("sol_thread_fetch_registers: td_thr_getxregsize %s",
608 td_err_string (val));
8fc2b417
SG
609
610 if (val == TD_OK)
611 {
612 xregset = alloca (xregsize);
613 val = td_thr_getxregs (&thandle, xregset);
614 if (val != TD_OK)
934741a1
SG
615 error ("sol_thread_fetch_registers: td_thr_getxregs %s",
616 td_err_string (val));
8fc2b417
SG
617 }
618#endif
619}
620
621static void
622sol_thread_store_registers (regno)
623 int regno;
624{
625 thread_t thread;
626 td_thrhandle_t thandle;
627 td_err_e val;
628 prgregset_t regset;
629 prfpregset_t fpregset;
934741a1 630#if 0
8fc2b417
SG
631 int xregsize;
632 caddr_t xregset;
934741a1 633#endif
8fc2b417 634
8fc2b417
SG
635 /* Convert inferior_pid into a td_thrhandle_t */
636
934741a1 637 thread = GET_THREAD (inferior_pid);
8fc2b417 638
4915acad 639 val = p_td_ta_map_id2thr (main_ta, thread, &thandle);
8fc2b417 640 if (val != TD_OK)
934741a1
SG
641 error ("sol_thread_store_registers: td_ta_map_id2thr %s",
642 td_err_string (val));
8fc2b417
SG
643
644 if (regno != -1)
645 { /* Not writing all the regs */
4915acad 646 val = p_td_thr_getgregs (&thandle, regset);
8fc2b417 647 if (val != TD_OK)
934741a1
SG
648 error ("sol_thread_store_registers: td_thr_getgregs %s",
649 td_err_string (val));
4915acad 650 val = p_td_thr_getfpregs (&thandle, &fpregset);
8fc2b417 651 if (val != TD_OK)
934741a1
SG
652 error ("sol_thread_store_registers: td_thr_getfpregs %s",
653 td_err_string (val));
8fc2b417
SG
654
655#if 0
656/* thread_db doesn't seem to handle this right */
657 val = td_thr_getxregsize (&thandle, &xregsize);
658 if (val != TD_OK && val != TD_NOXREGS)
934741a1
SG
659 error ("sol_thread_store_registers: td_thr_getxregsize %s",
660 td_err_string (val));
8fc2b417
SG
661
662 if (val == TD_OK)
663 {
664 xregset = alloca (xregsize);
665 val = td_thr_getxregs (&thandle, xregset);
666 if (val != TD_OK)
934741a1
SG
667 error ("sol_thread_store_registers: td_thr_getxregs %s",
668 td_err_string (val));
8fc2b417
SG
669 }
670#endif
671 }
672
673 fill_gregset (regset, regno);
934741a1 674 fill_fpregset (fpregset, regno);
8fc2b417 675
4915acad 676 val = p_td_thr_setgregs (&thandle, regset);
8fc2b417 677 if (val != TD_OK)
934741a1
SG
678 error ("sol_thread_store_registers: td_thr_setgregs %s",
679 td_err_string (val));
4915acad 680 val = p_td_thr_setfpregs (&thandle, &fpregset);
8fc2b417 681 if (val != TD_OK)
934741a1
SG
682 error ("sol_thread_store_registers: td_thr_setfpregs %s",
683 td_err_string (val));
8fc2b417
SG
684
685#if 0
686/* thread_db doesn't seem to handle this right */
687 val = td_thr_getxregsize (&thandle, &xregsize);
688 if (val != TD_OK && val != TD_NOXREGS)
934741a1
SG
689 error ("sol_thread_store_registers: td_thr_getxregsize %s",
690 td_err_string (val));
8fc2b417
SG
691
692 /* Should probably do something about writing the xregs here, but what are
693 they? */
694#endif
695}
696
697/* Get ready to modify the registers array. On machines which store
698 individual registers, this doesn't need to do anything. On machines
699 which store all the registers in one fell swoop, this makes sure
700 that registers contains all the registers from the program being
701 debugged. */
702
703static void
704sol_thread_prepare_to_store ()
705{
706 procfs_ops.to_prepare_to_store ();
707}
708
709static int
710sol_thread_xfer_memory (memaddr, myaddr, len, dowrite, target)
711 CORE_ADDR memaddr;
712 char *myaddr;
713 int len;
714 int dowrite;
715 struct target_ops *target; /* ignored */
716{
717 int retval;
934741a1 718 struct cleanup *old_chain;
8fc2b417 719
934741a1 720 old_chain = save_inferior_pid ();
8fc2b417 721
934741a1 722 if (is_thread (inferior_pid))
8fc2b417
SG
723 inferior_pid = main_ph.pid; /* It's a thread. Convert to lwp */
724
725 retval = procfs_ops.to_xfer_memory (memaddr, myaddr, len, dowrite, target);
726
934741a1 727 do_cleanups (old_chain);
8fc2b417
SG
728
729 return retval;
730}
731
732/* Print status information about what we're accessing. */
733
734static void
735sol_thread_files_info (ignore)
736 struct target_ops *ignore;
737{
738 procfs_ops.to_files_info (ignore);
739}
740
741static void
742sol_thread_kill_inferior ()
743{
744 procfs_ops.to_kill ();
745}
746
747static void
748sol_thread_notice_signals (pid)
749 int pid;
750{
751 procfs_ops.to_notice_signals (pid);
752}
753
754void target_new_objfile PARAMS ((struct objfile *objfile));
755
756/* Fork an inferior process, and start debugging it with /proc. */
757
758static void
759sol_thread_create_inferior (exec_file, allargs, env)
760 char *exec_file;
761 char *allargs;
762 char **env;
763{
764 procfs_ops.to_create_inferior (exec_file, allargs, env);
765
766 if (sol_thread_active)
767 {
8fc2b417
SG
768 main_ph.pid = inferior_pid; /* Save for xfer_memory */
769
770 push_target (&sol_thread_ops);
771
772 inferior_pid = lwp_to_thread (inferior_pid);
773
774 add_thread (inferior_pid);
775 }
776}
777
778/* This routine is called whenever a new symbol table is read in, or when all
a50cedad
SG
779 symbol tables are removed. libthread_db can only be initialized when it
780 finds the right variables in libthread.so. Since it's a shared library,
781 those variables don't show up until the library gets mapped and the symbol
782 table is read in. */
8fc2b417
SG
783
784void
785sol_thread_new_objfile (objfile)
786 struct objfile *objfile;
787{
788 td_err_e val;
789
790 if (!objfile)
791 {
792 sol_thread_active = 0;
793
794 return;
795 }
796
797 /* Now, initialize the thread debugging library. This needs to be done after
798 the shared libraries are located because it needs information from the
799 user's thread library. */
800
4915acad 801 val = p_td_init ();
8fc2b417 802 if (val != TD_OK)
934741a1 803 error ("target_new_objfile: td_init: %s", td_err_string (val));
8fc2b417 804
4915acad 805 val = p_td_ta_new (&main_ph, &main_ta);
8fc2b417
SG
806 if (val == TD_NOLIBTHREAD)
807 return;
808 else if (val != TD_OK)
934741a1 809 error ("target_new_objfile: td_ta_new: %s", td_err_string (val));
8fc2b417
SG
810
811 sol_thread_active = 1;
812}
813
814/* Clean up after the inferior dies. */
815
816static void
817sol_thread_mourn_inferior ()
818{
819 procfs_ops.to_mourn_inferior ();
820}
821
822/* Mark our target-struct as eligible for stray "run" and "attach" commands. */
a50cedad 823
8fc2b417
SG
824static int
825sol_thread_can_run ()
826{
827 return procfs_suppress_run;
828}
829
a50cedad 830static int
8fc2b417
SG
831sol_thread_alive (pid)
832 int pid;
833{
834 return 1;
835}
836
a50cedad 837static void
8fc2b417
SG
838sol_thread_stop ()
839{
840 procfs_ops.to_stop ();
841}
a50cedad
SG
842\f
843/* These routines implement the lower half of the thread_db interface. Ie: the
844 ps_* routines. */
8fc2b417 845
a50cedad
SG
846/* The next four routines are called by thread_db to tell us to stop and stop
847 a particular process or lwp. Since GDB ensures that these are all stopped
848 by the time we call anything in thread_db, these routines need to do
849 nothing. */
8fc2b417 850
8fc2b417
SG
851ps_err_e
852ps_pstop (const struct ps_prochandle *ph)
853{
8fc2b417
SG
854 return PS_OK;
855}
856
857ps_err_e
858ps_pcontinue (const struct ps_prochandle *ph)
859{
8fc2b417
SG
860 return PS_OK;
861}
862
863ps_err_e
864ps_lstop (const struct ps_prochandle *ph, lwpid_t lwpid)
865{
8fc2b417
SG
866 return PS_OK;
867}
868
869ps_err_e
870ps_lcontinue (const struct ps_prochandle *ph, lwpid_t lwpid)
871{
8fc2b417
SG
872 return PS_OK;
873}
874
875ps_err_e
876ps_pglobal_lookup (const struct ps_prochandle *ph, const char *ld_object_name,
877 const char *ld_symbol_name, paddr_t *ld_symbol_addr)
878{
879 struct minimal_symbol *ms;
880
881 ms = lookup_minimal_symbol (ld_symbol_name, NULL, NULL);
882
883 if (!ms)
884 return PS_NOSYM;
885
886 *ld_symbol_addr = SYMBOL_VALUE_ADDRESS (ms);
887
888 return PS_OK;
889}
890
a50cedad
SG
891/* Common routine for reading and writing memory. */
892
8fc2b417
SG
893static ps_err_e
894rw_common (int dowrite, const struct ps_prochandle *ph, paddr_t addr,
895 char *buf, int size)
896{
934741a1 897 struct cleanup *old_chain;
8fc2b417 898
934741a1 899 old_chain = save_inferior_pid ();
8fc2b417 900
934741a1 901 if (is_thread (inferior_pid))
8fc2b417
SG
902 inferior_pid = main_ph.pid; /* It's a thread. Convert to lwp */
903
904 while (size > 0)
905 {
906 int cc;
907
908 cc = procfs_ops.to_xfer_memory (addr, buf, size, dowrite, &procfs_ops);
909
910 if (cc < 0)
911 {
912 if (dowrite == 0)
913 print_sys_errmsg ("ps_pdread (): read", errno);
914 else
915 print_sys_errmsg ("ps_pdread (): write", errno);
916
934741a1 917 do_cleanups (old_chain);
8fc2b417
SG
918
919 return PS_ERR;
920 }
921 size -= cc;
922 buf += cc;
923 }
924
934741a1 925 do_cleanups (old_chain);
8fc2b417
SG
926
927 return PS_OK;
928}
929
930ps_err_e
931ps_pdread (const struct ps_prochandle *ph, paddr_t addr, char *buf, int size)
932{
933 return rw_common (0, ph, addr, buf, size);
934}
935
936ps_err_e
937ps_pdwrite (const struct ps_prochandle *ph, paddr_t addr, char *buf, int size)
938{
939 return rw_common (1, ph, addr, buf, size);
940}
941
942ps_err_e
943ps_ptread (const struct ps_prochandle *ph, paddr_t addr, char *buf, int size)
944{
945 return rw_common (0, ph, addr, buf, size);
946}
947
948ps_err_e
949ps_ptwrite (const struct ps_prochandle *ph, paddr_t addr, char *buf, int size)
950{
951 return rw_common (1, ph, addr, buf, size);
952}
953
a50cedad
SG
954/* Get integer regs */
955
8fc2b417
SG
956ps_err_e
957ps_lgetregs (const struct ps_prochandle *ph, lwpid_t lwpid,
958 prgregset_t gregset)
959{
934741a1 960 struct cleanup *old_chain;
8fc2b417 961
934741a1 962 old_chain = save_inferior_pid ();
8fc2b417 963
934741a1 964 inferior_pid = BUILD_LWP (lwpid, PIDGET (inferior_pid));
8fc2b417
SG
965
966 procfs_ops.to_fetch_registers (-1);
967 fill_gregset (gregset, -1);
968
934741a1 969 do_cleanups (old_chain);
8fc2b417
SG
970
971 return PS_OK;
972}
973
a50cedad
SG
974/* Set integer regs */
975
8fc2b417
SG
976ps_err_e
977ps_lsetregs (const struct ps_prochandle *ph, lwpid_t lwpid,
978 const prgregset_t gregset)
979{
934741a1 980 struct cleanup *old_chain;
8fc2b417 981
934741a1 982 old_chain = save_inferior_pid ();
8fc2b417 983
934741a1 984 inferior_pid = BUILD_LWP (lwpid, PIDGET (inferior_pid));
8fc2b417
SG
985
986 supply_gregset (gregset);
987 procfs_ops.to_store_registers (-1);
988
934741a1 989 do_cleanups (old_chain);
8fc2b417
SG
990
991 return PS_OK;
992}
993
994void
995ps_plog (const char *fmt, ...)
996{
997 va_list args;
998
999 va_start (args, fmt);
1000
1001 vfprintf_filtered (gdb_stderr, fmt, args);
1002}
1003
a50cedad
SG
1004/* Get size of extra register set. Currently a noop. */
1005
8fc2b417
SG
1006ps_err_e
1007ps_lgetxregsize (const struct ps_prochandle *ph, lwpid_t lwpid, int *xregsize)
1008{
934741a1 1009#if 0
8fc2b417
SG
1010 int lwp_fd;
1011 int regsize;
1012 ps_err_e val;
1013
8fc2b417
SG
1014 val = get_lwp_fd (ph, lwpid, &lwp_fd);
1015 if (val != PS_OK)
1016 return val;
1017
1018 if (ioctl (lwp_fd, PIOCGXREGSIZE, &regsize))
1019 {
1020 if (errno == EINVAL)
1021 return PS_NOFREGS; /* XXX Wrong code, but this is the closest
1022 thing in proc_service.h */
1023
1024 print_sys_errmsg ("ps_lgetxregsize (): PIOCGXREGSIZE", errno);
1025 return PS_ERR;
1026 }
1027#endif
1028
1029 return PS_OK;
1030}
1031
a50cedad
SG
1032/* Get extra register set. Currently a noop. */
1033
8fc2b417
SG
1034ps_err_e
1035ps_lgetxregs (const struct ps_prochandle *ph, lwpid_t lwpid, caddr_t xregset)
1036{
934741a1 1037#if 0
8fc2b417
SG
1038 int lwp_fd;
1039 ps_err_e val;
1040
8fc2b417
SG
1041 val = get_lwp_fd (ph, lwpid, &lwp_fd);
1042 if (val != PS_OK)
1043 return val;
1044
1045 if (ioctl (lwp_fd, PIOCGXREG, xregset))
1046 {
1047 print_sys_errmsg ("ps_lgetxregs (): PIOCGXREG", errno);
1048 return PS_ERR;
1049 }
1050#endif
1051
1052 return PS_OK;
1053}
1054
a50cedad
SG
1055/* Set extra register set. Currently a noop. */
1056
8fc2b417
SG
1057ps_err_e
1058ps_lsetxregs (const struct ps_prochandle *ph, lwpid_t lwpid, caddr_t xregset)
1059{
934741a1 1060#if 0
8fc2b417
SG
1061 int lwp_fd;
1062 ps_err_e val;
1063
8fc2b417
SG
1064 val = get_lwp_fd (ph, lwpid, &lwp_fd);
1065 if (val != PS_OK)
1066 return val;
1067
1068 if (ioctl (lwp_fd, PIOCSXREG, xregset))
1069 {
1070 print_sys_errmsg ("ps_lsetxregs (): PIOCSXREG", errno);
1071 return PS_ERR;
1072 }
1073#endif
1074
1075 return PS_OK;
1076}
1077
a50cedad
SG
1078/* Get floating-point regs. */
1079
8fc2b417
SG
1080ps_err_e
1081ps_lgetfpregs (const struct ps_prochandle *ph, lwpid_t lwpid,
1082 prfpregset_t *fpregset)
1083{
934741a1 1084 struct cleanup *old_chain;
8fc2b417 1085
934741a1 1086 old_chain = save_inferior_pid ();
8fc2b417 1087
934741a1 1088 inferior_pid = BUILD_LWP (lwpid, PIDGET (inferior_pid));
8fc2b417
SG
1089
1090 procfs_ops.to_fetch_registers (-1);
934741a1 1091 fill_fpregset (*fpregset, -1);
8fc2b417 1092
934741a1 1093 do_cleanups (old_chain);
8fc2b417
SG
1094
1095 return PS_OK;
1096}
1097
a50cedad
SG
1098/* Set floating-point regs. */
1099
8fc2b417
SG
1100ps_err_e
1101ps_lsetfpregs (const struct ps_prochandle *ph, lwpid_t lwpid,
1102 const prfpregset_t *fpregset)
1103{
934741a1 1104 struct cleanup *old_chain;
8fc2b417 1105
934741a1 1106 old_chain = save_inferior_pid ();
8fc2b417 1107
934741a1 1108 inferior_pid = BUILD_LWP (lwpid, PIDGET (inferior_pid));
8fc2b417 1109
934741a1 1110 supply_fpregset (*fpregset);
8fc2b417
SG
1111 procfs_ops.to_store_registers (-1);
1112
934741a1 1113 do_cleanups (old_chain);
8fc2b417
SG
1114
1115 return PS_OK;
1116}
1117\f
a50cedad
SG
1118/* Convert a pid to printable form. */
1119
8fc2b417
SG
1120char *
1121solaris_pid_to_str (pid)
1122 int pid;
1123{
1124 static char buf[100];
1125
934741a1 1126 if (is_thread (pid))
8fc2b417
SG
1127 {
1128 int lwp;
1129
1130 lwp = thread_to_lwp (pid, -2);
1131
1132 if (lwp != -2)
934741a1 1133 sprintf (buf, "Thread %d (LWP %d)", GET_THREAD (pid), GET_LWP (lwp));
8fc2b417 1134 else
934741a1 1135 sprintf (buf, "Thread %d ", GET_THREAD (pid));
8fc2b417
SG
1136 }
1137 else
934741a1 1138 sprintf (buf, "LWP %d ", GET_LWP (pid));
8fc2b417
SG
1139
1140 return buf;
1141}
1142\f
1143struct target_ops sol_thread_ops = {
1144 "solaris-threads", /* to_shortname */
1145 "Solaris threads and pthread.", /* to_longname */
1146 "Solaris threads and pthread support.", /* to_doc */
1147 sol_thread_open, /* to_open */
1148 0, /* to_close */
4915acad 1149 sol_thread_attach, /* to_attach */
8fc2b417 1150 sol_thread_detach, /* to_detach */
4915acad
SG
1151 sol_thread_resume, /* to_resume */
1152 sol_thread_wait, /* to_wait */
8fc2b417
SG
1153 sol_thread_fetch_registers, /* to_fetch_registers */
1154 sol_thread_store_registers, /* to_store_registers */
1155 sol_thread_prepare_to_store, /* to_prepare_to_store */
4915acad
SG
1156 sol_thread_xfer_memory, /* to_xfer_memory */
1157 sol_thread_files_info, /* to_files_info */
8fc2b417
SG
1158 memory_insert_breakpoint, /* to_insert_breakpoint */
1159 memory_remove_breakpoint, /* to_remove_breakpoint */
1160 terminal_init_inferior, /* to_terminal_init */
1161 terminal_inferior, /* to_terminal_inferior */
1162 terminal_ours_for_output, /* to_terminal_ours_for_output */
1163 terminal_ours, /* to_terminal_ours */
1164 child_terminal_info, /* to_terminal_info */
1165 sol_thread_kill_inferior, /* to_kill */
1166 0, /* to_load */
1167 0, /* to_lookup_symbol */
1168 sol_thread_create_inferior, /* to_create_inferior */
1169 sol_thread_mourn_inferior, /* to_mourn_inferior */
1170 sol_thread_can_run, /* to_can_run */
1171 sol_thread_notice_signals, /* to_notice_signals */
1172 sol_thread_alive, /* to_thread_alive */
1173 sol_thread_stop, /* to_stop */
1174 process_stratum, /* to_stratum */
1175 0, /* to_next */
1176 1, /* to_has_all_memory */
1177 1, /* to_has_memory */
1178 1, /* to_has_stack */
1179 1, /* to_has_registers */
1180 1, /* to_has_execution */
1181 0, /* sections */
1182 0, /* sections_end */
1183 OPS_MAGIC /* to_magic */
1184};
1185
1186void
1187_initialize_sol_thread ()
1188{
4915acad
SG
1189 void *dlhandle;
1190
1191 dlhandle = dlopen ("libthread_db.so.1", RTLD_NOW);
1192 if (!dlhandle)
1193 goto die;
1194
1195#define resolve(X) \
1196 if (!(p_##X = dlsym (dlhandle, #X))) \
1197 goto die;
1198
1199 resolve (td_log);
1200 resolve (td_ta_new);
1201 resolve (td_ta_delete);
1202 resolve (td_init);
1203 resolve (td_ta_get_ph);
1204 resolve (td_ta_get_nthreads);
1205 resolve (td_ta_tsd_iter);
1206 resolve (td_ta_thr_iter);
1207 resolve (td_thr_validate);
1208 resolve (td_thr_tsd);
1209 resolve (td_thr_get_info);
1210 resolve (td_thr_getfpregs);
1211 resolve (td_thr_getxregsize);
1212 resolve (td_thr_getxregs);
1213 resolve (td_thr_sigsetmask);
1214 resolve (td_thr_setprio);
1215 resolve (td_thr_setsigpending);
1216 resolve (td_thr_setfpregs);
1217 resolve (td_thr_setxregs);
1218 resolve (td_ta_map_id2thr);
1219 resolve (td_ta_map_lwp2thr);
1220 resolve (td_thr_getgregs);
1221 resolve (td_thr_setgregs);
1222
8fc2b417
SG
1223 add_target (&sol_thread_ops);
1224
1225 procfs_suppress_run = 1;
4915acad
SG
1226
1227 return;
1228
1229 die:
1230
1231 fprintf_unfiltered (gdb_stderr, "[GDB will not be able to debug user-mode threads: %s]\n", dlerror ());
1232
1233 if (dlhandle)
1234 dlclose (dlhandle);
1235
1236 return;
8fc2b417 1237}
This page took 0.116989 seconds and 4 git commands to generate.