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