* procfs.c (procfs_thread_alive procfs_stop): Make static.
[external/binutils.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 gregset;
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, gregset);
529   if (val != TD_OK
530       && val != TD_PARTIALREG)
531     error ("sol_thread_fetch_registers: td_thr_getgregs %s",
532            td_err_string (val));
533
534   /* For the sparc, TD_PARTIALREG means that only i0->i7, l0->l7, pc and sp
535      are saved (by a thread context switch).  */
536
537   /* And, now the fp regs */
538
539   val = td_thr_getfpregs (&thandle, &fpregset);
540   if (val != TD_OK
541       && val != TD_NOFPREGS)
542     error ("sol_thread_fetch_registers: td_thr_getfpregs %s",
543            td_err_string (val));
544
545 /* Note that we must call supply_{g fp}regset *after* calling the td routines
546    because the td routines call ps_lget* which affect the values stored in the
547    registers array.  */
548
549   supply_gregset (gregset);
550   supply_fpregset (fpregset);
551
552 #if 0
553 /* thread_db doesn't seem to handle this right */
554   val = td_thr_getxregsize (&thandle, &xregsize);
555   if (val != TD_OK && val != TD_NOXREGS)
556     error ("sol_thread_fetch_registers: td_thr_getxregsize %s",
557            td_err_string (val));
558
559   if (val == TD_OK)
560     {
561       xregset = alloca (xregsize);
562       val = td_thr_getxregs (&thandle, xregset);
563       if (val != TD_OK)
564         error ("sol_thread_fetch_registers: td_thr_getxregs %s",
565                td_err_string (val));
566     }
567 #endif
568 }
569
570 static void
571 sol_thread_store_registers (regno)
572      int regno;
573 {
574   thread_t thread;
575   td_thrhandle_t thandle;
576   td_err_e val;
577   prgregset_t regset;
578   prfpregset_t fpregset;
579 #if 0
580   int xregsize;
581   caddr_t xregset;
582 #endif
583
584   /* Convert inferior_pid into a td_thrhandle_t */
585
586   thread = GET_THREAD (inferior_pid);
587
588   val = td_ta_map_id2thr (main_ta, thread, &thandle);
589   if (val != TD_OK)
590     error ("sol_thread_store_registers: td_ta_map_id2thr %s",
591            td_err_string (val));
592
593   if (regno != -1)
594     {                           /* Not writing all the regs */
595       val = td_thr_getgregs (&thandle, regset);
596       if (val != TD_OK)
597         error ("sol_thread_store_registers: td_thr_getgregs %s",
598                td_err_string (val));
599       val = td_thr_getfpregs (&thandle, &fpregset);
600       if (val != TD_OK)
601         error ("sol_thread_store_registers: td_thr_getfpregs %s",
602                td_err_string (val));
603
604 #if 0
605 /* thread_db doesn't seem to handle this right */
606       val = td_thr_getxregsize (&thandle, &xregsize);
607       if (val != TD_OK && val != TD_NOXREGS)
608         error ("sol_thread_store_registers: td_thr_getxregsize %s",
609                td_err_string (val));
610
611       if (val == TD_OK)
612         {
613           xregset = alloca (xregsize);
614           val = td_thr_getxregs (&thandle, xregset);
615           if (val != TD_OK)
616             error ("sol_thread_store_registers: td_thr_getxregs %s",
617                    td_err_string (val));
618         }
619 #endif
620     }
621
622   fill_gregset (regset, regno);
623   fill_fpregset (fpregset, regno);
624
625   val = td_thr_setgregs (&thandle, regset);
626   if (val != TD_OK)
627     error ("sol_thread_store_registers: td_thr_setgregs %s",
628            td_err_string (val));
629   val = td_thr_setfpregs (&thandle, &fpregset);
630   if (val != TD_OK)
631     error ("sol_thread_store_registers: td_thr_setfpregs %s",
632            td_err_string (val));
633
634 #if 0
635 /* thread_db doesn't seem to handle this right */
636   val = td_thr_getxregsize (&thandle, &xregsize);
637   if (val != TD_OK && val != TD_NOXREGS)
638     error ("sol_thread_store_registers: td_thr_getxregsize %s",
639            td_err_string (val));
640
641   /* Should probably do something about writing the xregs here, but what are
642      they? */
643 #endif
644 }
645
646 /* Get ready to modify the registers array.  On machines which store
647    individual registers, this doesn't need to do anything.  On machines
648    which store all the registers in one fell swoop, this makes sure
649    that registers contains all the registers from the program being
650    debugged.  */
651
652 static void
653 sol_thread_prepare_to_store ()
654 {
655   procfs_ops.to_prepare_to_store ();
656 }
657
658 static int
659 sol_thread_xfer_memory (memaddr, myaddr, len, dowrite, target)
660      CORE_ADDR memaddr;
661      char *myaddr;
662      int len;
663      int dowrite;
664      struct target_ops *target; /* ignored */
665 {
666   int retval;
667   struct cleanup *old_chain;
668
669   old_chain = save_inferior_pid ();
670
671   if (is_thread (inferior_pid))
672     inferior_pid = main_ph.pid; /* It's a thread.  Convert to lwp */
673
674   retval = procfs_ops.to_xfer_memory (memaddr, myaddr, len, dowrite, target);
675
676   do_cleanups (old_chain);
677
678   return retval;
679 }
680
681 /* Print status information about what we're accessing.  */
682
683 static void
684 sol_thread_files_info (ignore)
685      struct target_ops *ignore;
686 {
687   procfs_ops.to_files_info (ignore);
688 }
689
690 static void
691 sol_thread_kill_inferior ()
692 {
693   procfs_ops.to_kill ();
694 }
695
696 static void
697 sol_thread_notice_signals (pid)
698      int pid;
699 {
700   procfs_ops.to_notice_signals (pid);
701 }
702
703 void target_new_objfile PARAMS ((struct objfile *objfile));
704
705 /* Fork an inferior process, and start debugging it with /proc.  */
706
707 static void
708 sol_thread_create_inferior (exec_file, allargs, env)
709      char *exec_file;
710      char *allargs;
711      char **env;
712 {
713   procfs_ops.to_create_inferior (exec_file, allargs, env);
714
715   if (sol_thread_active)
716     {
717       main_ph.pid = inferior_pid; /* Save for xfer_memory */
718
719       push_target (&sol_thread_ops);
720
721       inferior_pid = lwp_to_thread (inferior_pid);
722
723       add_thread (inferior_pid);
724     }
725 }
726
727 /* This routine is called whenever a new symbol table is read in, or when all
728    symbol tables are removed.  libthread_db can only be initialized when it
729    finds the right variables in libthread.so.  Since it's a shared library,
730    those variables don't show up until the library gets mapped and the symbol
731    table is read in.  */
732
733 void
734 sol_thread_new_objfile (objfile)
735      struct objfile *objfile;
736 {
737   td_err_e val;
738
739   if (!objfile)
740     {
741       sol_thread_active = 0;
742
743       return;
744     }
745
746   /* Now, initialize the thread debugging library.  This needs to be done after
747      the shared libraries are located because it needs information from the
748      user's thread library.  */
749
750   val = td_init ();
751   if (val != TD_OK)
752     error ("target_new_objfile: td_init: %s", td_err_string (val));
753
754   val = td_ta_new (&main_ph, &main_ta);
755   if (val == TD_NOLIBTHREAD)
756     return;
757   else if (val != TD_OK)
758     error ("target_new_objfile: td_ta_new: %s", td_err_string (val));
759
760   sol_thread_active = 1;
761 }
762
763 /* Clean up after the inferior dies.  */
764
765 static void
766 sol_thread_mourn_inferior ()
767 {
768   procfs_ops.to_mourn_inferior ();
769 }
770
771 /* Mark our target-struct as eligible for stray "run" and "attach" commands.  */
772
773 static int
774 sol_thread_can_run ()
775 {
776   return procfs_suppress_run;
777 }
778
779 static int
780 sol_thread_alive (pid)
781      int pid;
782 {
783   return 1;
784 }
785
786 static void
787 sol_thread_stop ()
788 {
789   procfs_ops.to_stop ();
790 }
791 \f
792 /* These routines implement the lower half of the thread_db interface.  Ie: the
793    ps_* routines.  */
794
795 /* The next four routines are called by thread_db to tell us to stop and stop
796    a particular process or lwp.  Since GDB ensures that these are all stopped
797    by the time we call anything in thread_db, these routines need to do
798    nothing.  */
799
800 ps_err_e
801 ps_pstop (const struct ps_prochandle *ph)
802 {
803   return PS_OK;
804 }
805
806 ps_err_e
807 ps_pcontinue (const struct ps_prochandle *ph)
808 {
809   return PS_OK;
810 }
811
812 ps_err_e
813 ps_lstop (const struct ps_prochandle *ph, lwpid_t lwpid)
814 {
815   return PS_OK;
816 }
817
818 ps_err_e
819 ps_lcontinue (const struct ps_prochandle *ph, lwpid_t lwpid)
820 {
821   return PS_OK;
822 }
823
824 ps_err_e
825 ps_pglobal_lookup (const struct ps_prochandle *ph, const char *ld_object_name,
826                    const char *ld_symbol_name, paddr_t *ld_symbol_addr)
827 {
828   struct minimal_symbol *ms;
829
830   ms = lookup_minimal_symbol (ld_symbol_name, NULL, NULL);
831
832   if (!ms)
833     return PS_NOSYM;
834
835   *ld_symbol_addr = SYMBOL_VALUE_ADDRESS (ms);
836
837   return PS_OK;
838 }
839
840 /* Common routine for reading and writing memory.  */
841
842 static ps_err_e
843 rw_common (int dowrite, const struct ps_prochandle *ph, paddr_t addr,
844            char *buf, int size)
845 {
846   struct cleanup *old_chain;
847
848   old_chain = save_inferior_pid ();
849
850   if (is_thread (inferior_pid))
851     inferior_pid = main_ph.pid; /* It's a thread.  Convert to lwp */
852
853   while (size > 0)
854     {
855       int cc;
856
857       cc = procfs_ops.to_xfer_memory (addr, buf, size, dowrite, &procfs_ops);
858
859       if (cc < 0)
860         {
861           if (dowrite == 0)
862             print_sys_errmsg ("ps_pdread (): read", errno);
863           else
864             print_sys_errmsg ("ps_pdread (): write", errno);
865
866           do_cleanups (old_chain);
867
868           return PS_ERR;
869         }
870       size -= cc;
871       buf += cc;
872     }
873
874   do_cleanups (old_chain);
875
876   return PS_OK;
877 }
878
879 ps_err_e
880 ps_pdread (const struct ps_prochandle *ph, paddr_t addr, char *buf, int size)
881 {
882   return rw_common (0, ph, addr, buf, size);
883 }
884
885 ps_err_e
886 ps_pdwrite (const struct ps_prochandle *ph, paddr_t addr, char *buf, int size)
887 {
888   return rw_common (1, ph, addr, buf, size);
889 }
890
891 ps_err_e
892 ps_ptread (const struct ps_prochandle *ph, paddr_t addr, char *buf, int size)
893 {
894   return rw_common (0, ph, addr, buf, size);
895 }
896
897 ps_err_e
898 ps_ptwrite (const struct ps_prochandle *ph, paddr_t addr, char *buf, int size)
899 {
900   return rw_common (1, ph, addr, buf, size);
901 }
902
903 /* Get integer regs */
904
905 ps_err_e
906 ps_lgetregs (const struct ps_prochandle *ph, lwpid_t lwpid,
907              prgregset_t gregset)
908 {
909   struct cleanup *old_chain;
910
911   old_chain = save_inferior_pid ();
912
913   inferior_pid = BUILD_LWP (lwpid, PIDGET (inferior_pid));
914   
915   procfs_ops.to_fetch_registers (-1);
916   fill_gregset (gregset, -1);
917
918   do_cleanups (old_chain);
919
920   return PS_OK;
921 }
922
923 /* Set integer regs */
924
925 ps_err_e
926 ps_lsetregs (const struct ps_prochandle *ph, lwpid_t lwpid,
927              const prgregset_t gregset)
928 {
929   struct cleanup *old_chain;
930
931   old_chain = save_inferior_pid ();
932
933   inferior_pid = BUILD_LWP (lwpid, PIDGET (inferior_pid));
934   
935   supply_gregset (gregset);
936   procfs_ops.to_store_registers (-1);
937
938   do_cleanups (old_chain);
939
940   return PS_OK;
941 }
942
943 void
944 ps_plog (const char *fmt, ...)
945 {
946   va_list args;
947
948   va_start (args, fmt);
949
950   vfprintf_filtered (gdb_stderr, fmt, args);
951 }
952
953 /* Get size of extra register set.  Currently a noop.  */
954
955 ps_err_e
956 ps_lgetxregsize (const struct ps_prochandle *ph, lwpid_t lwpid, int *xregsize)
957 {
958 #if 0
959   int lwp_fd;
960   int regsize;
961   ps_err_e val;
962
963   val = get_lwp_fd (ph, lwpid, &lwp_fd);
964   if (val != PS_OK)
965     return val;
966
967   if (ioctl (lwp_fd, PIOCGXREGSIZE, &regsize))
968     {
969       if (errno == EINVAL)
970         return PS_NOFREGS;      /* XXX Wrong code, but this is the closest
971                                    thing in proc_service.h  */
972
973       print_sys_errmsg ("ps_lgetxregsize (): PIOCGXREGSIZE", errno);
974       return PS_ERR;
975     }
976 #endif
977
978   return PS_OK;
979 }
980
981 /* Get extra register set.  Currently a noop.  */
982
983 ps_err_e
984 ps_lgetxregs (const struct ps_prochandle *ph, lwpid_t lwpid, caddr_t xregset)
985 {
986 #if 0
987   int lwp_fd;
988   ps_err_e val;
989
990   val = get_lwp_fd (ph, lwpid, &lwp_fd);
991   if (val != PS_OK)
992     return val;
993
994   if (ioctl (lwp_fd, PIOCGXREG, xregset))
995     {
996       print_sys_errmsg ("ps_lgetxregs (): PIOCGXREG", errno);
997       return PS_ERR;
998     }
999 #endif
1000
1001   return PS_OK;
1002 }
1003
1004 /* Set extra register set.  Currently a noop.  */
1005
1006 ps_err_e
1007 ps_lsetxregs (const struct ps_prochandle *ph, lwpid_t lwpid, caddr_t xregset)
1008 {
1009 #if 0
1010   int lwp_fd;
1011   ps_err_e val;
1012
1013   val = get_lwp_fd (ph, lwpid, &lwp_fd);
1014   if (val != PS_OK)
1015     return val;
1016
1017   if (ioctl (lwp_fd, PIOCSXREG, xregset))
1018     {
1019       print_sys_errmsg ("ps_lsetxregs (): PIOCSXREG", errno);
1020       return PS_ERR;
1021     }
1022 #endif
1023
1024   return PS_OK;
1025 }
1026
1027 /* Get floating-point regs.  */
1028
1029 ps_err_e
1030 ps_lgetfpregs (const struct ps_prochandle *ph, lwpid_t lwpid,
1031                prfpregset_t *fpregset)
1032 {
1033   struct cleanup *old_chain;
1034
1035   old_chain = save_inferior_pid ();
1036
1037   inferior_pid = BUILD_LWP (lwpid, PIDGET (inferior_pid));
1038
1039   procfs_ops.to_fetch_registers (-1);
1040   fill_fpregset (*fpregset, -1);
1041
1042   do_cleanups (old_chain);
1043
1044   return PS_OK;
1045 }
1046
1047 /* Set floating-point regs.  */
1048
1049 ps_err_e
1050 ps_lsetfpregs (const struct ps_prochandle *ph, lwpid_t lwpid,
1051                const prfpregset_t *fpregset)
1052 {
1053   struct cleanup *old_chain;
1054
1055   old_chain = save_inferior_pid ();
1056
1057   inferior_pid = BUILD_LWP (lwpid, PIDGET (inferior_pid));
1058   
1059   supply_fpregset (*fpregset);
1060   procfs_ops.to_store_registers (-1);
1061
1062   do_cleanups (old_chain);
1063
1064   return PS_OK;
1065 }
1066 \f
1067 /* Convert a pid to printable form. */
1068
1069 char *
1070 solaris_pid_to_str (pid)
1071      int pid;
1072 {
1073   static char buf[100];
1074
1075   if (is_thread (pid))
1076     {
1077       int lwp;
1078
1079       lwp = thread_to_lwp (pid, -2);
1080
1081       if (lwp != -2)
1082         sprintf (buf, "Thread %d (LWP %d)", GET_THREAD (pid), GET_LWP (lwp));
1083       else
1084         sprintf (buf, "Thread %d        ", GET_THREAD (pid));
1085     }
1086   else
1087     sprintf (buf, "LWP    %d        ", GET_LWP (pid));
1088
1089   return buf;
1090 }
1091 \f
1092 struct target_ops sol_thread_ops = {
1093   "solaris-threads",            /* to_shortname */
1094   "Solaris threads and pthread.", /* to_longname */
1095   "Solaris threads and pthread support.", /* to_doc */
1096   sol_thread_open,              /* to_open */
1097   0,                            /* to_close */
1098   sol_thread_attach,                    /* to_attach */
1099   sol_thread_detach,            /* to_detach */
1100   sol_thread_resume,                    /* to_resume */
1101   sol_thread_wait,                      /* to_wait */
1102   sol_thread_fetch_registers,   /* to_fetch_registers */
1103   sol_thread_store_registers,   /* to_store_registers */
1104   sol_thread_prepare_to_store,  /* to_prepare_to_store */
1105   sol_thread_xfer_memory,               /* to_xfer_memory */
1106   sol_thread_files_info,                /* to_files_info */
1107   memory_insert_breakpoint,     /* to_insert_breakpoint */
1108   memory_remove_breakpoint,     /* to_remove_breakpoint */
1109   terminal_init_inferior,       /* to_terminal_init */
1110   terminal_inferior,            /* to_terminal_inferior */
1111   terminal_ours_for_output,     /* to_terminal_ours_for_output */
1112   terminal_ours,                /* to_terminal_ours */
1113   child_terminal_info,          /* to_terminal_info */
1114   sol_thread_kill_inferior,     /* to_kill */
1115   0,                            /* to_load */
1116   0,                            /* to_lookup_symbol */
1117   sol_thread_create_inferior,   /* to_create_inferior */
1118   sol_thread_mourn_inferior,    /* to_mourn_inferior */
1119   sol_thread_can_run,           /* to_can_run */
1120   sol_thread_notice_signals,    /* to_notice_signals */
1121   sol_thread_alive,             /* to_thread_alive */
1122   sol_thread_stop,              /* to_stop */
1123   process_stratum,              /* to_stratum */
1124   0,                            /* to_next */
1125   1,                            /* to_has_all_memory */
1126   1,                            /* to_has_memory */
1127   1,                            /* to_has_stack */
1128   1,                            /* to_has_registers */
1129   1,                            /* to_has_execution */
1130   0,                            /* sections */
1131   0,                            /* sections_end */
1132   OPS_MAGIC                     /* to_magic */
1133 };
1134
1135 void
1136 _initialize_sol_thread ()
1137 {
1138   add_target (&sol_thread_ops);
1139
1140   procfs_suppress_run = 1;
1141 }