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