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