* Makefile.in config.in configure configure.in
[deliverable/binutils-gdb.git] / gdb / sol-thread.c
1 /* Low level interface for debugging Solaris threads for GDB, the GNU debugger.
2 Copyright 1996 Free Software Foundation, Inc.
3
4 This file is part of GDB.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
19
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
48 #include "defs.h"
49
50 /* Undefine gregset_t and fpregset_t to avoid conflict with defs in xm file. */
51
52 #ifdef gregset_t
53 #undef gregset_t
54 #endif
55
56 #ifdef fpregset_t
57 #undef fpregset_t
58 #endif
59
60 #include <thread.h>
61 #include <proc_service.h>
62 #include <thread_db.h>
63 #include "gdbthread.h"
64 #include "target.h"
65 #include "inferior.h"
66 #include <fcntl.h>
67 #include <unistd.h>
68 #include <sys/stat.h>
69
70 extern struct target_ops sol_thread_ops; /* Forward declaration */
71
72 extern int procfs_suppress_run;
73 extern struct target_ops procfs_ops; /* target vector for procfs.c */
74
75 /* Note that these prototypes differ slightly from those used in procfs.c
76 for of two reasons. One, we can't use gregset_t, as that's got a whole
77 different meaning under Solaris (also, see above). Two, we can't use the
78 pointer form here as these are actually arrays of ints (for Sparc's at
79 least), and are automatically coerced into pointers to ints when used as
80 parameters. That makes it impossible to avoid a compiler warning when
81 passing pr{g fp}regset_t's from a parameter to an argument of one of
82 these functions. */
83
84 extern void supply_gregset PARAMS ((const prgregset_t));
85 extern void fill_gregset PARAMS ((prgregset_t, int));
86 extern void supply_fpregset PARAMS ((const prfpregset_t));
87 extern void fill_fpregset PARAMS ((prfpregset_t, int));
88
89 /* This struct is defined by us, but mainly used for the proc_service interface.
90 We don't have much use for it, except as a handy place to get a real pid
91 for memory accesses. */
92
93 struct ps_prochandle
94 {
95 pid_t pid;
96 };
97
98 struct string_map
99 {
100 int num;
101 char *str;
102 };
103
104 static struct ps_prochandle main_ph;
105 static td_thragent_t *main_ta;
106 static int sol_thread_active = 0;
107
108 static struct cleanup * save_inferior_pid PARAMS ((void));
109 static void restore_inferior_pid PARAMS ((int pid));
110 static char *td_err_string PARAMS ((td_err_e errcode));
111 static char *td_state_string PARAMS ((td_thr_state_e statecode));
112 static int thread_to_lwp PARAMS ((int thread_id, int default_lwp));
113 static void sol_thread_resume PARAMS ((int pid, int step,
114 enum target_signal signo));
115 static 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))
124 \f
125 /*
126
127 LOCAL FUNCTION
128
129 td_err_string - Convert a thread_db error code to a string
130
131 SYNOPSIS
132
133 char * td_err_string (errcode)
134
135 DESCRIPTION
136
137 Return the thread_db error string associated with errcode. If errcode
138 is unknown, then return a message.
139
140 */
141
142 static char *
143 td_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);
179
180 return buf;
181 }
182 \f
183 /*
184
185 LOCAL FUNCTION
186
187 td_state_string - Convert a thread_db state code to a string
188
189 SYNOPSIS
190
191 char * td_state_string (statecode)
192
193 DESCRIPTION
194
195 Return the thread_db state string associated with statecode. If
196 statecode is unknown, then return a message.
197
198 */
199
200 static char *
201 td_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
230 LOCAL FUNCTION
231
232 thread_to_lwp - Convert a Posix or Solaris thread id to a LWP id.
233
234 SYNOPSIS
235
236 int thread_to_lwp (thread_id, default_lwp)
237
238 DESCRIPTION
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
244 NOTES
245
246 This function probably shouldn't call error()...
247
248 */
249
250 static int
251 thread_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
261 if (is_lwp (thread_id))
262 return thread_id; /* It's already an LWP id */
263
264 /* It's a thread. Convert to lwp */
265
266 pid = PIDGET (thread_id);
267 thread_id = GET_THREAD(thread_id);
268
269 val = td_ta_map_id2thr (main_ta, thread_id, &th);
270 if (val != TD_OK)
271 error ("thread_to_lwp: td_ta_map_id2thr %s", td_err_string (val));
272
273 val = td_thr_get_info (&th, &ti);
274
275 if (val != TD_OK)
276 error ("thread_to_lwp: td_thr_get_info: %s", td_err_string (val));
277
278 if (ti.ti_state != TD_THR_ACTIVE)
279 {
280 if (default_lwp != -1)
281 return default_lwp;
282 error ("thread_to_lwp: thread state not active: %s",
283 td_state_string (ti.ti_state));
284 }
285
286 lwp = BUILD_LWP (ti.ti_lid, pid);
287
288 return lwp;
289 }
290 \f
291 /*
292
293 LOCAL FUNCTION
294
295 lwp_to_thread - Convert a LWP id to a Posix or Solaris thread id.
296
297 SYNOPSIS
298
299 int lwp_to_thread (lwp_id)
300
301 DESCRIPTION
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
306 NOTES
307
308 This function probably shouldn't call error()...
309
310 */
311
312 static int
313 lwp_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
322 if (is_thread (lwp))
323 return lwp; /* It's already a thread id */
324
325 /* It's an lwp. Convert it to a thread id. */
326
327 pid = PIDGET (lwp);
328 lwp = GET_LWP (lwp);
329
330 val = td_ta_map_lwp2thr (main_ta, lwp, &th);
331 if (val != TD_OK)
332 error ("lwp_to_thread: td_thr_get_info: %s.", td_err_string (val));
333
334 val = td_thr_get_info (&th, &ti);
335
336 if (val != TD_OK)
337 error ("lwp_to_thread: td_thr_get_info: %s.", td_err_string (val));
338
339 thread_id = BUILD_THREAD (ti.ti_tid, pid);
340
341 return thread_id;
342 }
343 \f
344 /*
345
346 LOCAL 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
351 SYNOPSIS
352
353 struct cleanup *save_inferior_pid ()
354 void restore_inferior_pid (int pid)
355
356 DESCRIPTION
357
358 These two functions act in unison to restore inferior_pid in
359 case of an error.
360
361 NOTES
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
372 static struct cleanup *
373 save_inferior_pid ()
374 {
375 return make_cleanup (restore_inferior_pid, inferior_pid);
376 }
377
378 static void
379 restore_inferior_pid (pid)
380 int pid;
381 {
382 inferior_pid = pid;
383 }
384 \f
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
390 /* ARGSUSED */
391 static void
392 sol_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
402 static void
403 sol_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
420 static void
421 sol_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
430 signal activated. We may have to convert pid from a thread-id to an LWP id
431 for procfs. */
432
433 static void
434 sol_thread_resume (pid, step, signo)
435 int pid;
436 int step;
437 enum target_signal signo;
438 {
439 struct cleanup *old_chain;
440
441 old_chain = save_inferior_pid ();
442
443 inferior_pid = thread_to_lwp (inferior_pid, main_ph.pid);
444
445 if (pid != -1)
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 }
451
452 procfs_ops.to_resume (pid, step, signo);
453
454 do_cleanups (old_chain);
455 }
456
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. */
459
460 static int
461 sol_thread_wait (pid, ourstatus)
462 int pid;
463 struct target_waitstatus *ourstatus;
464 {
465 int rtnval;
466 int save_pid;
467 struct cleanup *old_chain;
468
469 save_pid = inferior_pid;
470 old_chain = save_inferior_pid ();
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
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
495 do_cleanups (old_chain);
496
497 return rtnval;
498 }
499
500 static void
501 sol_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;
509 #if 0
510 int xregsize;
511 caddr_t xregset;
512 #endif
513
514 /* Convert inferior_pid into a td_thrhandle_t */
515
516 thread = GET_THREAD (inferior_pid);
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)
523 error ("sol_thread_fetch_registers: td_ta_map_id2thr: %s",
524 td_err_string (val));
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
543 error ("sol_thread_fetch_registers: td_thr_getgregs %s",
544 td_err_string (val));
545
546 /* And, now the fp regs */
547
548 val = td_thr_getfpregs (&thandle, &fpregset);
549 if (val == TD_OK)
550 supply_fpregset (fpregset);
551 else if (val != TD_NOFPREGS)
552 error ("sol_thread_fetch_registers: td_thr_getfpregs %s",
553 td_err_string (val));
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)
559 error ("sol_thread_fetch_registers: td_thr_getxregsize %s",
560 td_err_string (val));
561
562 if (val == TD_OK)
563 {
564 xregset = alloca (xregsize);
565 val = td_thr_getxregs (&thandle, xregset);
566 if (val != TD_OK)
567 error ("sol_thread_fetch_registers: td_thr_getxregs %s",
568 td_err_string (val));
569 }
570 #endif
571 }
572
573 static void
574 sol_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;
582 #if 0
583 int xregsize;
584 caddr_t xregset;
585 #endif
586
587 /* Convert inferior_pid into a td_thrhandle_t */
588
589 thread = GET_THREAD (inferior_pid);
590
591 val = td_ta_map_id2thr (main_ta, thread, &thandle);
592 if (val != TD_OK)
593 error ("sol_thread_store_registers: td_ta_map_id2thr %s",
594 td_err_string (val));
595
596 if (regno != -1)
597 { /* Not writing all the regs */
598 val = td_thr_getgregs (&thandle, regset);
599 if (val != TD_OK)
600 error ("sol_thread_store_registers: td_thr_getgregs %s",
601 td_err_string (val));
602 val = td_thr_getfpregs (&thandle, &fpregset);
603 if (val != TD_OK)
604 error ("sol_thread_store_registers: td_thr_getfpregs %s",
605 td_err_string (val));
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)
611 error ("sol_thread_store_registers: td_thr_getxregsize %s",
612 td_err_string (val));
613
614 if (val == TD_OK)
615 {
616 xregset = alloca (xregsize);
617 val = td_thr_getxregs (&thandle, xregset);
618 if (val != TD_OK)
619 error ("sol_thread_store_registers: td_thr_getxregs %s",
620 td_err_string (val));
621 }
622 #endif
623 }
624
625 fill_gregset (regset, regno);
626 fill_fpregset (fpregset, regno);
627
628 val = td_thr_setgregs (&thandle, regset);
629 if (val != TD_OK)
630 error ("sol_thread_store_registers: td_thr_setgregs %s",
631 td_err_string (val));
632 val = td_thr_setfpregs (&thandle, &fpregset);
633 if (val != TD_OK)
634 error ("sol_thread_store_registers: td_thr_setfpregs %s",
635 td_err_string (val));
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)
641 error ("sol_thread_store_registers: td_thr_getxregsize %s",
642 td_err_string (val));
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
655 static void
656 sol_thread_prepare_to_store ()
657 {
658 procfs_ops.to_prepare_to_store ();
659 }
660
661 static int
662 sol_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;
670 struct cleanup *old_chain;
671
672 old_chain = save_inferior_pid ();
673
674 if (is_thread (inferior_pid))
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
679 do_cleanups (old_chain);
680
681 return retval;
682 }
683
684 /* Print status information about what we're accessing. */
685
686 static void
687 sol_thread_files_info (ignore)
688 struct target_ops *ignore;
689 {
690 procfs_ops.to_files_info (ignore);
691 }
692
693 static void
694 sol_thread_kill_inferior ()
695 {
696 procfs_ops.to_kill ();
697 }
698
699 static void
700 sol_thread_notice_signals (pid)
701 int pid;
702 {
703 procfs_ops.to_notice_signals (pid);
704 }
705
706 void target_new_objfile PARAMS ((struct objfile *objfile));
707
708 /* Fork an inferior process, and start debugging it with /proc. */
709
710 static void
711 sol_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 {
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
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. */
735
736 void
737 sol_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)
755 error ("target_new_objfile: td_init: %s", td_err_string (val));
756
757 val = td_ta_new (&main_ph, &main_ta);
758 if (val == TD_NOLIBTHREAD)
759 return;
760 else if (val != TD_OK)
761 error ("target_new_objfile: td_ta_new: %s", td_err_string (val));
762
763 sol_thread_active = 1;
764 }
765
766 /* Clean up after the inferior dies. */
767
768 static void
769 sol_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. */
775
776 static int
777 sol_thread_can_run ()
778 {
779 return procfs_suppress_run;
780 }
781
782 static int
783 sol_thread_alive (pid)
784 int pid;
785 {
786 return 1;
787 }
788
789 static void
790 sol_thread_stop ()
791 {
792 procfs_ops.to_stop ();
793 }
794 \f
795 /* These routines implement the lower half of the thread_db interface. Ie: the
796 ps_* routines. */
797
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. */
802
803 ps_err_e
804 ps_pstop (const struct ps_prochandle *ph)
805 {
806 return PS_OK;
807 }
808
809 ps_err_e
810 ps_pcontinue (const struct ps_prochandle *ph)
811 {
812 return PS_OK;
813 }
814
815 ps_err_e
816 ps_lstop (const struct ps_prochandle *ph, lwpid_t lwpid)
817 {
818 return PS_OK;
819 }
820
821 ps_err_e
822 ps_lcontinue (const struct ps_prochandle *ph, lwpid_t lwpid)
823 {
824 return PS_OK;
825 }
826
827 ps_err_e
828 ps_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
843 /* Common routine for reading and writing memory. */
844
845 static ps_err_e
846 rw_common (int dowrite, const struct ps_prochandle *ph, paddr_t addr,
847 char *buf, int size)
848 {
849 struct cleanup *old_chain;
850
851 old_chain = save_inferior_pid ();
852
853 if (is_thread (inferior_pid))
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
869 do_cleanups (old_chain);
870
871 return PS_ERR;
872 }
873 size -= cc;
874 buf += cc;
875 }
876
877 do_cleanups (old_chain);
878
879 return PS_OK;
880 }
881
882 ps_err_e
883 ps_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
888 ps_err_e
889 ps_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
894 ps_err_e
895 ps_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
900 ps_err_e
901 ps_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
906 /* Get integer regs */
907
908 ps_err_e
909 ps_lgetregs (const struct ps_prochandle *ph, lwpid_t lwpid,
910 prgregset_t gregset)
911 {
912 struct cleanup *old_chain;
913
914 old_chain = save_inferior_pid ();
915
916 inferior_pid = BUILD_LWP (lwpid, PIDGET (inferior_pid));
917
918 procfs_ops.to_fetch_registers (-1);
919 fill_gregset (gregset, -1);
920
921 do_cleanups (old_chain);
922
923 return PS_OK;
924 }
925
926 /* Set integer regs */
927
928 ps_err_e
929 ps_lsetregs (const struct ps_prochandle *ph, lwpid_t lwpid,
930 const prgregset_t gregset)
931 {
932 struct cleanup *old_chain;
933
934 old_chain = save_inferior_pid ();
935
936 inferior_pid = BUILD_LWP (lwpid, PIDGET (inferior_pid));
937
938 supply_gregset (gregset);
939 procfs_ops.to_store_registers (-1);
940
941 do_cleanups (old_chain);
942
943 return PS_OK;
944 }
945
946 void
947 ps_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
956 /* Get size of extra register set. Currently a noop. */
957
958 ps_err_e
959 ps_lgetxregsize (const struct ps_prochandle *ph, lwpid_t lwpid, int *xregsize)
960 {
961 #if 0
962 int lwp_fd;
963 int regsize;
964 ps_err_e val;
965
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
984 /* Get extra register set. Currently a noop. */
985
986 ps_err_e
987 ps_lgetxregs (const struct ps_prochandle *ph, lwpid_t lwpid, caddr_t xregset)
988 {
989 #if 0
990 int lwp_fd;
991 ps_err_e val;
992
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
1007 /* Set extra register set. Currently a noop. */
1008
1009 ps_err_e
1010 ps_lsetxregs (const struct ps_prochandle *ph, lwpid_t lwpid, caddr_t xregset)
1011 {
1012 #if 0
1013 int lwp_fd;
1014 ps_err_e val;
1015
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
1030 /* Get floating-point regs. */
1031
1032 ps_err_e
1033 ps_lgetfpregs (const struct ps_prochandle *ph, lwpid_t lwpid,
1034 prfpregset_t *fpregset)
1035 {
1036 struct cleanup *old_chain;
1037
1038 old_chain = save_inferior_pid ();
1039
1040 inferior_pid = BUILD_LWP (lwpid, PIDGET (inferior_pid));
1041
1042 procfs_ops.to_fetch_registers (-1);
1043 fill_fpregset (*fpregset, -1);
1044
1045 do_cleanups (old_chain);
1046
1047 return PS_OK;
1048 }
1049
1050 /* Set floating-point regs. */
1051
1052 ps_err_e
1053 ps_lsetfpregs (const struct ps_prochandle *ph, lwpid_t lwpid,
1054 const prfpregset_t *fpregset)
1055 {
1056 struct cleanup *old_chain;
1057
1058 old_chain = save_inferior_pid ();
1059
1060 inferior_pid = BUILD_LWP (lwpid, PIDGET (inferior_pid));
1061
1062 supply_fpregset (*fpregset);
1063 procfs_ops.to_store_registers (-1);
1064
1065 do_cleanups (old_chain);
1066
1067 return PS_OK;
1068 }
1069 \f
1070 /* Convert a pid to printable form. */
1071
1072 char *
1073 solaris_pid_to_str (pid)
1074 int pid;
1075 {
1076 static char buf[100];
1077
1078 if (is_thread (pid))
1079 {
1080 int lwp;
1081
1082 lwp = thread_to_lwp (pid, -2);
1083
1084 if (lwp != -2)
1085 sprintf (buf, "Thread %d (LWP %d)", GET_THREAD (pid), GET_LWP (lwp));
1086 else
1087 sprintf (buf, "Thread %d ", GET_THREAD (pid));
1088 }
1089 else
1090 sprintf (buf, "LWP %d ", GET_LWP (pid));
1091
1092 return buf;
1093 }
1094 \f
1095 struct 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
1138 void
1139 _initialize_sol_thread ()
1140 {
1141 add_target (&sol_thread_ops);
1142
1143 procfs_suppress_run = 1;
1144 }
This page took 0.055604 seconds and 4 git commands to generate.