* sol-thread.c: Cleanup. gcc -Wall fixes. Add prototypes.
[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
8fc2b417
SG
20#include "defs.h"
21
934741a1
SG
22/* Undefine gregset_t and fpregset_t to avoid conflict with defs in xm file. */
23
8fc2b417
SG
24#ifdef gregset_t
25#undef gregset_t
26#endif
27
28#ifdef fpregset_t
29#undef fpregset_t
30#endif
31
934741a1 32#include <thread.h>
8fc2b417
SG
33#include <proc_service.h>
34#include <thread_db.h>
fdfa3315 35#include "gdbthread.h"
8fc2b417
SG
36#include "target.h"
37#include "inferior.h"
38#include <fcntl.h>
39#include <unistd.h>
40#include <sys/stat.h>
41
8fc2b417
SG
42extern struct target_ops sol_thread_ops; /* Forward declaration */
43
44extern int procfs_suppress_run;
934741a1
SG
45extern struct target_ops procfs_ops; /* target vector for procfs.c */
46
47extern void supply_gregset PARAMS ((const prgregset_t));
48extern void fill_gregset PARAMS ((prgregset_t, int));
49extern void supply_fpregset PARAMS ((const prfpregset_t));
50extern void fill_fpregset PARAMS ((prfpregset_t, int));
8fc2b417
SG
51
52struct ps_prochandle
53{
54 pid_t pid;
55};
56
934741a1
SG
57struct string_map
58{
59 int num;
60 char *str;
61};
62
8fc2b417
SG
63static struct ps_prochandle main_ph;
64static td_thragent_t *main_ta;
8fc2b417
SG
65static int sol_thread_active = 0;
66
934741a1
SG
67static struct cleanup * save_inferior_pid PARAMS ((void));
68static void restore_inferior_pid PARAMS ((int pid));
69static char *td_err_string PARAMS ((td_err_e errcode));
70static char *td_state_string PARAMS ((td_thr_state_e statecode));
71static int thread_to_lwp PARAMS ((int thread_id, int default_lwp));
72static void sol_thread_resume PARAMS ((int pid, int step,
73 enum target_signal signo));
74static 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))
8fc2b417 83\f
934741a1
SG
84/*
85
86LOCAL FUNCTION
87
88 td_err_string - Convert a thread_db error code to a string
89
90SYNOPSIS
91
92 char * td_err_string (errcode)
93
94DESCRIPTION
95
96 Return the thread_db error string associated with errcode. If errcode
97 is unknown, then return a message.
98
99 */
100
101static char *
102td_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);
8fc2b417 138
934741a1
SG
139 return buf;
140}
141\f
142/*
8fc2b417 143
934741a1 144LOCAL FUNCTION
8fc2b417 145
934741a1
SG
146 td_state_string - Convert a thread_db state code to a string
147
148SYNOPSIS
149
150 char * td_state_string (statecode)
151
152DESCRIPTION
153
154 Return the thread_db state string associated with statecode. If
155 statecode is unknown, then return a message.
156
157 */
158
159static char *
160td_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
189LOCAL FUNCTION
190
191 thread_to_lwp - Convert a Posix or Solaris thread id to a LWP id.
192
193SYNOPSIS
194
195 int thread_to_lwp (thread_id, default_lwp)
196
197DESCRIPTION
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
203NOTES
204
205 This function probably shouldn't call error()...
206
207 */
8fc2b417
SG
208
209static int
210thread_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
934741a1 220 if (is_lwp (thread_id))
8fc2b417
SG
221 return thread_id; /* It's already an LWP id */
222
223 /* It's a thread. Convert to lwp */
224
934741a1
SG
225 pid = PIDGET (thread_id);
226 thread_id = GET_THREAD(thread_id);
8fc2b417
SG
227
228 val = td_ta_map_id2thr (main_ta, thread_id, &th);
229 if (val != TD_OK)
934741a1 230 error ("thread_to_lwp: td_ta_map_id2thr %s", td_err_string (val));
8fc2b417
SG
231
232 val = td_thr_get_info (&th, &ti);
233
234 if (val != TD_OK)
934741a1 235 error ("thread_to_lwp: td_thr_get_info: %s", td_err_string (val));
8fc2b417
SG
236
237 if (ti.ti_state != TD_THR_ACTIVE)
238 {
239 if (default_lwp != -1)
240 return default_lwp;
934741a1
SG
241 error ("thread_to_lwp: thread state not active: %s",
242 td_state_string (ti.ti_state));
8fc2b417
SG
243 }
244
934741a1 245 lwp = BUILD_LWP (ti.ti_lid, pid);
8fc2b417
SG
246
247 return lwp;
248}
249
250/* Convert an LWP id to a thread. */
251
8fc2b417
SG
252static int
253lwp_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
934741a1 262 if (is_thread (lwp))
8fc2b417
SG
263 return lwp; /* It's already a thread id */
264
265 /* It's an lwp. Convert it to a thread id. */
266
934741a1
SG
267 pid = PIDGET (lwp);
268 lwp = GET_LWP (lwp);
8fc2b417
SG
269
270 val = td_ta_map_lwp2thr (main_ta, lwp, &th);
271 if (val != TD_OK)
934741a1 272 error ("lwp_to_thread: td_thr_get_info: %s.", td_err_string (val));
8fc2b417
SG
273
274 val = td_thr_get_info (&th, &ti);
275
276 if (val != TD_OK)
934741a1 277 error ("lwp_to_thread: td_thr_get_info: %s.", td_err_string (val));
8fc2b417 278
934741a1 279 thread_id = BUILD_THREAD (ti.ti_tid, pid);
8fc2b417
SG
280
281 return thread_id;
282}
934741a1
SG
283\f
284static struct cleanup *
285save_inferior_pid ()
286{
287 return make_cleanup (restore_inferior_pid, inferior_pid);
288}
8fc2b417 289
934741a1
SG
290static void
291restore_inferior_pid (pid)
292 int pid;
293{
294 inferior_pid = pid;
295}
296\f
8fc2b417
SG
297/* ARGSUSED */
298static void
299sol_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
309static void
310sol_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
327static void
328sol_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
339static void
340sol_thread_resume (pid, step, signo)
341 int pid;
342 int step;
343 enum target_signal signo;
344{
934741a1 345 struct cleanup *old_chain;
8fc2b417 346
934741a1 347 old_chain = save_inferior_pid ();
8fc2b417
SG
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
934741a1 356 do_cleanups (old_chain);
8fc2b417
SG
357}
358
359/* Wait for any LWPs to stop */
360
361static int
362sol_thread_wait (pid, ourstatus)
363 int pid;
364 struct target_waitstatus *ourstatus;
365{
8fc2b417
SG
366 int rtnval;
367 int save_pid;
934741a1 368 struct cleanup *old_chain;
8fc2b417
SG
369
370 if (!sol_thread_active)
371 return procfs_ops.to_wait (pid, ourstatus);
372
373 save_pid = inferior_pid;
934741a1 374 old_chain = save_inferior_pid ();
8fc2b417
SG
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
8fc2b417
SG
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
934741a1
SG
399 do_cleanups (old_chain);
400
8fc2b417
SG
401 return rtnval;
402}
403
404static void
405sol_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;
934741a1 413#if 0
8fc2b417
SG
414 int xregsize;
415 caddr_t xregset;
934741a1 416#endif
8fc2b417
SG
417
418 if (!sol_thread_active
934741a1 419 || is_lwp (inferior_pid))
8fc2b417
SG
420 {
421 procfs_ops.to_fetch_registers (regno);
422 return;
423 }
424
425 /* Convert inferior_pid into a td_thrhandle_t */
426
934741a1 427 thread = GET_THREAD (inferior_pid);
8fc2b417
SG
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)
934741a1
SG
434 error ("sol_thread_fetch_registers: td_ta_map_id2thr: %s",
435 td_err_string (val));
8fc2b417
SG
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
934741a1
SG
454 error ("sol_thread_fetch_registers: td_thr_getgregs %s",
455 td_err_string (val));
8fc2b417
SG
456
457 /* And, now the fp regs */
458
459 val = td_thr_getfpregs (&thandle, &fpregset);
460 if (val == TD_OK)
934741a1 461 supply_fpregset (fpregset);
8fc2b417 462 else if (val != TD_NOFPREGS)
934741a1
SG
463 error ("sol_thread_fetch_registers: td_thr_getfpregs %s",
464 td_err_string (val));
8fc2b417
SG
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)
934741a1
SG
470 error ("sol_thread_fetch_registers: td_thr_getxregsize %s",
471 td_err_string (val));
8fc2b417
SG
472
473 if (val == TD_OK)
474 {
475 xregset = alloca (xregsize);
476 val = td_thr_getxregs (&thandle, xregset);
477 if (val != TD_OK)
934741a1
SG
478 error ("sol_thread_fetch_registers: td_thr_getxregs %s",
479 td_err_string (val));
8fc2b417
SG
480 }
481#endif
482}
483
484static void
485sol_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;
934741a1 493#if 0
8fc2b417
SG
494 int xregsize;
495 caddr_t xregset;
934741a1 496#endif
8fc2b417
SG
497
498 if (!sol_thread_active
934741a1 499 || is_lwp (inferior_pid))
8fc2b417
SG
500 {
501 procfs_ops.to_store_registers (regno);
502 return;
503 }
504
505 /* Convert inferior_pid into a td_thrhandle_t */
506
934741a1 507 thread = GET_THREAD (inferior_pid);
8fc2b417
SG
508
509 val = td_ta_map_id2thr (main_ta, thread, &thandle);
510 if (val != TD_OK)
934741a1
SG
511 error ("sol_thread_store_registers: td_ta_map_id2thr %s",
512 td_err_string (val));
8fc2b417
SG
513
514 if (regno != -1)
515 { /* Not writing all the regs */
516 val = td_thr_getgregs (&thandle, regset);
517 if (val != TD_OK)
934741a1
SG
518 error ("sol_thread_store_registers: td_thr_getgregs %s",
519 td_err_string (val));
8fc2b417
SG
520 val = td_thr_getfpregs (&thandle, &fpregset);
521 if (val != TD_OK)
934741a1
SG
522 error ("sol_thread_store_registers: td_thr_getfpregs %s",
523 td_err_string (val));
8fc2b417
SG
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)
934741a1
SG
529 error ("sol_thread_store_registers: td_thr_getxregsize %s",
530 td_err_string (val));
8fc2b417
SG
531
532 if (val == TD_OK)
533 {
534 xregset = alloca (xregsize);
535 val = td_thr_getxregs (&thandle, xregset);
536 if (val != TD_OK)
934741a1
SG
537 error ("sol_thread_store_registers: td_thr_getxregs %s",
538 td_err_string (val));
8fc2b417
SG
539 }
540#endif
541 }
542
543 fill_gregset (regset, regno);
934741a1 544 fill_fpregset (fpregset, regno);
8fc2b417
SG
545
546 val = td_thr_setgregs (&thandle, regset);
547 if (val != TD_OK)
934741a1
SG
548 error ("sol_thread_store_registers: td_thr_setgregs %s",
549 td_err_string (val));
8fc2b417
SG
550 val = td_thr_setfpregs (&thandle, &fpregset);
551 if (val != TD_OK)
934741a1
SG
552 error ("sol_thread_store_registers: td_thr_setfpregs %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_store_registers: td_thr_getxregsize %s",
560 td_err_string (val));
8fc2b417
SG
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
573static void
574sol_thread_prepare_to_store ()
575{
576 procfs_ops.to_prepare_to_store ();
577}
578
579static int
580sol_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;
934741a1 588 struct cleanup *old_chain;
8fc2b417 589
934741a1 590 old_chain = save_inferior_pid ();
8fc2b417 591
934741a1 592 if (is_thread (inferior_pid))
8fc2b417
SG
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
934741a1 597 do_cleanups (old_chain);
8fc2b417
SG
598
599 return retval;
600}
601
602/* Print status information about what we're accessing. */
603
604static void
605sol_thread_files_info (ignore)
606 struct target_ops *ignore;
607{
608 procfs_ops.to_files_info (ignore);
609}
610
611static void
612sol_thread_kill_inferior ()
613{
614 procfs_ops.to_kill ();
615}
616
617static void
618sol_thread_notice_signals (pid)
619 int pid;
620{
621 procfs_ops.to_notice_signals (pid);
622}
623
624void target_new_objfile PARAMS ((struct objfile *objfile));
625
626/* Fork an inferior process, and start debugging it with /proc. */
627
628static void
629sol_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 {
8fc2b417
SG
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
651void
652sol_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)
934741a1 670 error ("target_new_objfile: td_init: %s", td_err_string (val));
8fc2b417
SG
671
672 val = td_ta_new (&main_ph, &main_ta);
673 if (val == TD_NOLIBTHREAD)
674 return;
675 else if (val != TD_OK)
934741a1 676 error ("target_new_objfile: td_ta_new: %s", td_err_string (val));
8fc2b417
SG
677
678 sol_thread_active = 1;
679}
680
681/* Clean up after the inferior dies. */
682
683static void
684sol_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. */
690static int
691sol_thread_can_run ()
692{
693 return procfs_suppress_run;
694}
695
696int
697sol_thread_alive (pid)
698 int pid;
699{
700 return 1;
701}
702
703void
704sol_thread_stop ()
705{
706 procfs_ops.to_stop ();
707}
708
709/* Service routines we must supply to libthread_db */
710
711struct lwp_map
712{
713 struct lwp_map *next;
714 pid_t pid;
715 lwpid_t lwp;
716 int lwpfd;
717};
718
8fc2b417
SG
719ps_err_e
720ps_pstop (const struct ps_prochandle *ph)
721{
8fc2b417
SG
722 return PS_OK;
723}
724
725ps_err_e
726ps_pcontinue (const struct ps_prochandle *ph)
727{
8fc2b417
SG
728 return PS_OK;
729}
730
731ps_err_e
732ps_lstop (const struct ps_prochandle *ph, lwpid_t lwpid)
733{
8fc2b417
SG
734 return PS_OK;
735}
736
737ps_err_e
738ps_lcontinue (const struct ps_prochandle *ph, lwpid_t lwpid)
739{
8fc2b417
SG
740 return PS_OK;
741}
742
743ps_err_e
744ps_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
759static ps_err_e
760rw_common (int dowrite, const struct ps_prochandle *ph, paddr_t addr,
761 char *buf, int size)
762{
934741a1 763 struct cleanup *old_chain;
8fc2b417 764
934741a1 765 old_chain = save_inferior_pid ();
8fc2b417 766
934741a1 767 if (is_thread (inferior_pid))
8fc2b417
SG
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
934741a1 783 do_cleanups (old_chain);
8fc2b417
SG
784
785 return PS_ERR;
786 }
787 size -= cc;
788 buf += cc;
789 }
790
934741a1 791 do_cleanups (old_chain);
8fc2b417
SG
792
793 return PS_OK;
794}
795
796ps_err_e
797ps_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
802ps_err_e
803ps_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
808ps_err_e
809ps_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
814ps_err_e
815ps_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
820ps_err_e
821ps_lgetregs (const struct ps_prochandle *ph, lwpid_t lwpid,
822 prgregset_t gregset)
823{
934741a1 824 struct cleanup *old_chain;
8fc2b417 825
934741a1 826 old_chain = save_inferior_pid ();
8fc2b417 827
934741a1 828 inferior_pid = BUILD_LWP (lwpid, PIDGET (inferior_pid));
8fc2b417
SG
829
830 procfs_ops.to_fetch_registers (-1);
831 fill_gregset (gregset, -1);
832
934741a1 833 do_cleanups (old_chain);
8fc2b417
SG
834
835 return PS_OK;
836}
837
838ps_err_e
839ps_lsetregs (const struct ps_prochandle *ph, lwpid_t lwpid,
840 const prgregset_t gregset)
841{
934741a1 842 struct cleanup *old_chain;
8fc2b417 843
934741a1 844 old_chain = save_inferior_pid ();
8fc2b417 845
934741a1 846 inferior_pid = BUILD_LWP (lwpid, PIDGET (inferior_pid));
8fc2b417
SG
847
848 supply_gregset (gregset);
849 procfs_ops.to_store_registers (-1);
850
934741a1 851 do_cleanups (old_chain);
8fc2b417
SG
852
853 return PS_OK;
854}
855
856void
857ps_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
866ps_err_e
867ps_lgetxregsize (const struct ps_prochandle *ph, lwpid_t lwpid, int *xregsize)
868{
934741a1 869#if 0
8fc2b417
SG
870 int lwp_fd;
871 int regsize;
872 ps_err_e val;
873
8fc2b417
SG
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
892ps_err_e
893ps_lgetxregs (const struct ps_prochandle *ph, lwpid_t lwpid, caddr_t xregset)
894{
934741a1 895#if 0
8fc2b417
SG
896 int lwp_fd;
897 ps_err_e val;
898
8fc2b417
SG
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
913ps_err_e
914ps_lsetxregs (const struct ps_prochandle *ph, lwpid_t lwpid, caddr_t xregset)
915{
934741a1 916#if 0
8fc2b417
SG
917 int lwp_fd;
918 ps_err_e val;
919
8fc2b417
SG
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
934ps_err_e
935ps_lgetfpregs (const struct ps_prochandle *ph, lwpid_t lwpid,
936 prfpregset_t *fpregset)
937{
934741a1 938 struct cleanup *old_chain;
8fc2b417 939
934741a1 940 old_chain = save_inferior_pid ();
8fc2b417 941
934741a1 942 inferior_pid = BUILD_LWP (lwpid, PIDGET (inferior_pid));
8fc2b417
SG
943
944 procfs_ops.to_fetch_registers (-1);
934741a1 945 fill_fpregset (*fpregset, -1);
8fc2b417 946
934741a1 947 do_cleanups (old_chain);
8fc2b417
SG
948
949 return PS_OK;
950}
951
952ps_err_e
953ps_lsetfpregs (const struct ps_prochandle *ph, lwpid_t lwpid,
954 const prfpregset_t *fpregset)
955{
934741a1 956 struct cleanup *old_chain;
8fc2b417 957
934741a1 958 old_chain = save_inferior_pid ();
8fc2b417 959
934741a1 960 inferior_pid = BUILD_LWP (lwpid, PIDGET (inferior_pid));
8fc2b417 961
934741a1 962 supply_fpregset (*fpregset);
8fc2b417
SG
963 procfs_ops.to_store_registers (-1);
964
934741a1 965 do_cleanups (old_chain);
8fc2b417
SG
966
967 return PS_OK;
968}
969\f
970char *
971solaris_pid_to_str (pid)
972 int pid;
973{
974 static char buf[100];
975
934741a1 976 if (is_thread (pid))
8fc2b417
SG
977 {
978 int lwp;
979
980 lwp = thread_to_lwp (pid, -2);
981
982 if (lwp != -2)
934741a1 983 sprintf (buf, "Thread %d (LWP %d)", GET_THREAD (pid), GET_LWP (lwp));
8fc2b417 984 else
934741a1 985 sprintf (buf, "Thread %d ", GET_THREAD (pid));
8fc2b417
SG
986 }
987 else
934741a1 988 sprintf (buf, "LWP %d ", GET_LWP (pid));
8fc2b417
SG
989
990 return buf;
991}
992\f
993struct 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
1036void
1037_initialize_sol_thread ()
1038{
1039 add_target (&sol_thread_ops);
1040
1041 procfs_suppress_run = 1;
1042}
This page took 0.076773 seconds and 4 git commands to generate.