OSDN Git Service

PR 11123
[pf3gnuchains/pf3gnuchains3x.git] / gdb / sol-thread.c
1 /* Solaris threads debugging interface.
2
3    Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
4    2007, 2008, 2009, 2010 Free Software Foundation, Inc.
5
6    This file is part of GDB.
7
8    This program is free software; you can redistribute it and/or modify
9    it under the terms of the GNU General Public License as published by
10    the Free Software Foundation; either version 3 of the License, or
11    (at your option) any later version.
12
13    This program is distributed in the hope that it will be useful,
14    but WITHOUT ANY WARRANTY; without even the implied warranty of
15    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16    GNU General Public License for more details.
17
18    You should have received a copy of the GNU General Public License
19    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
20
21 /* This module implements a sort of half target that sits between the
22    machine-independent parts of GDB and the /proc interface (procfs.c)
23    to provide access to the Solaris user-mode thread implementation.
24
25    Solaris threads are true user-mode threads, which are invoked via
26    the thr_* and pthread_* (native and POSIX respectivly) interfaces.
27    These are mostly implemented in user-space, with all thread context
28    kept in various structures that live in the user's heap.  These
29    should not be confused with lightweight processes (LWPs), which are
30    implemented by the kernel, and scheduled without explicit
31    intervention by the process.
32
33    Just to confuse things a little, Solaris threads (both native and
34    POSIX) are actually implemented using LWPs.  In general, there are
35    going to be more threads than LWPs.  There is no fixed
36    correspondence between a thread and an LWP.  When a thread wants to
37    run, it gets scheduled onto the first available LWP and can
38    therefore migrate from one LWP to another as time goes on.  A
39    sleeping thread may not be associated with an LWP at all!
40
41    To make it possible to mess with threads, Sun provides a library
42    called libthread_db.so.1 (not to be confused with
43    libthread_db.so.0, which doesn't have a published interface).  This
44    interface has an upper part, which it provides, and a lower part
45    which we provide.  The upper part consists of the td_* routines,
46    which allow us to find all the threads, query their state, etc...
47    The lower part consists of all of the ps_*, which are used by the
48    td_* routines to read/write memory, manipulate LWPs, lookup
49    symbols, etc...  The ps_* routines actually do most of their work
50    by calling functions in procfs.c.  */
51
52 #include "defs.h"
53 #include <thread.h>
54 #include <proc_service.h>
55 #include <thread_db.h>
56 #include "gdbthread.h"
57 #include "target.h"
58 #include "inferior.h"
59 #include <fcntl.h>
60 #include "gdb_stat.h"
61 #include <dlfcn.h>
62 #include "gdbcmd.h"
63 #include "gdbcore.h"
64 #include "regcache.h"
65 #include "solib.h"
66 #include "symfile.h"
67 #include "observer.h"
68 #include "gdb_string.h"
69 #include "procfs.h"
70
71 struct target_ops sol_thread_ops;
72
73 extern char *procfs_pid_to_str (struct target_ops *ops, ptid_t ptid);
74
75 /* Prototypes for supply_gregset etc. */
76 #include "gregset.h"
77
78 /* This struct is defined by us, but mainly used for the proc_service
79    interface.  We don't have much use for it, except as a handy place
80    to get a real PID for memory accesses.  */
81
82 struct ps_prochandle
83 {
84   ptid_t ptid;
85 };
86
87 struct string_map
88 {
89   int num;
90   char *str;
91 };
92
93 static struct ps_prochandle main_ph;
94 static td_thragent_t *main_ta;
95 static int sol_thread_active = 0;
96
97 static void init_sol_thread_ops (void);
98
99 /* Default definitions: These must be defined in tm.h if they are to
100    be shared with a process module such as procfs.  */
101
102 #define GET_PID(ptid)           ptid_get_pid (ptid)
103 #define GET_LWP(ptid)           ptid_get_lwp (ptid)
104 #define GET_THREAD(ptid)        ptid_get_tid (ptid)
105
106 #define is_lwp(ptid)            (GET_LWP (ptid) != 0)
107 #define is_thread(ptid)         (GET_THREAD (ptid) != 0)
108
109 #define BUILD_LWP(lwp, pid)     ptid_build (pid, lwp, 0)
110 #define BUILD_THREAD(tid, pid)  ptid_build (pid, 0, tid)
111
112 /* Pointers to routines from libthread_db resolved by dlopen().  */
113
114 static void (*p_td_log)(const int on_off);
115 static td_err_e (*p_td_ta_new)(const struct ps_prochandle *ph_p,
116                                td_thragent_t **ta_pp);
117 static td_err_e (*p_td_ta_delete)(td_thragent_t *ta_p);
118 static td_err_e (*p_td_init)(void);
119 static td_err_e (*p_td_ta_get_ph)(const td_thragent_t *ta_p,
120                                   struct ps_prochandle **ph_pp);
121 static td_err_e (*p_td_ta_get_nthreads)(const td_thragent_t *ta_p,
122                                         int *nthread_p);
123 static td_err_e (*p_td_ta_tsd_iter)(const td_thragent_t *ta_p,
124                                     td_key_iter_f *cb, void *cbdata_p);
125 static td_err_e (*p_td_ta_thr_iter)(const td_thragent_t *ta_p,
126                                     td_thr_iter_f *cb, void *cbdata_p,
127                                     td_thr_state_e state, int ti_pri,
128                                     sigset_t *ti_sigmask_p,
129                                     unsigned ti_user_flags);
130 static td_err_e (*p_td_thr_validate)(const td_thrhandle_t *th_p);
131 static td_err_e (*p_td_thr_tsd)(const td_thrhandle_t * th_p,
132                                 const thread_key_t key, void **data_pp);
133 static td_err_e (*p_td_thr_get_info)(const td_thrhandle_t *th_p,
134                                      td_thrinfo_t *ti_p);
135 static td_err_e (*p_td_thr_getfpregs)(const td_thrhandle_t *th_p,
136                                       prfpregset_t *fpregset);
137 static td_err_e (*p_td_thr_getxregsize)(const td_thrhandle_t *th_p,
138                                         int *xregsize);
139 static td_err_e (*p_td_thr_getxregs)(const td_thrhandle_t *th_p,
140                                      const caddr_t xregset);
141 static td_err_e (*p_td_thr_sigsetmask)(const td_thrhandle_t *th_p,
142                                        const sigset_t ti_sigmask);
143 static td_err_e (*p_td_thr_setprio)(const td_thrhandle_t *th_p,
144                                     const int ti_pri);
145 static td_err_e (*p_td_thr_setsigpending)(const td_thrhandle_t *th_p,
146                                           const uchar_t ti_pending_flag,
147                                           const sigset_t ti_pending);
148 static td_err_e (*p_td_thr_setfpregs)(const td_thrhandle_t *th_p,
149                                       const prfpregset_t *fpregset);
150 static td_err_e (*p_td_thr_setxregs)(const td_thrhandle_t *th_p,
151                                      const caddr_t xregset);
152 static td_err_e (*p_td_ta_map_id2thr)(const td_thragent_t *ta_p,
153                                       thread_t tid,
154                                       td_thrhandle_t *th_p);
155 static td_err_e (*p_td_ta_map_lwp2thr)(const td_thragent_t *ta_p,
156                                        lwpid_t lwpid,
157                                        td_thrhandle_t *th_p);
158 static td_err_e (*p_td_thr_getgregs)(const td_thrhandle_t *th_p,
159                                      prgregset_t regset);
160 static td_err_e (*p_td_thr_setgregs)(const td_thrhandle_t *th_p,
161                                      const prgregset_t regset);
162 \f
163
164 /* Return the libthread_db error string associated with ERRCODE.  If
165    ERRCODE is unknown, return an appropriate message.  */
166
167 static char *
168 td_err_string (td_err_e errcode)
169 {
170   static struct string_map td_err_table[] =
171   {
172     { TD_OK, "generic \"call succeeded\"" },
173     { TD_ERR, "generic error." },
174     { TD_NOTHR, "no thread can be found to satisfy query" },
175     { TD_NOSV, "no synch. variable can be found to satisfy query" },
176     { TD_NOLWP, "no lwp can be found to satisfy query" },
177     { TD_BADPH, "invalid process handle" },
178     { TD_BADTH, "invalid thread handle" },
179     { TD_BADSH, "invalid synchronization handle" },
180     { TD_BADTA, "invalid thread agent" },
181     { TD_BADKEY, "invalid key" },
182     { TD_NOMSG, "td_thr_event_getmsg() called when there was no message" },
183     { TD_NOFPREGS, "FPU register set not available for given thread" },
184     { TD_NOLIBTHREAD, "application not linked with libthread" },
185     { TD_NOEVENT, "requested event is not supported" },
186     { TD_NOCAPAB, "capability not available" },
187     { TD_DBERR, "Debugger service failed" },
188     { TD_NOAPLIC, "Operation not applicable to" },
189     { TD_NOTSD, "No thread specific data for this thread" },
190     { TD_MALLOC, "Malloc failed" },
191     { TD_PARTIALREG, "Only part of register set was written/read" },
192     { TD_NOXREGS, "X register set not available for given thread" }
193   };
194   const int td_err_size = sizeof td_err_table / sizeof (struct string_map);
195   int i;
196   static char buf[50];
197
198   for (i = 0; i < td_err_size; i++)
199     if (td_err_table[i].num == errcode)
200       return td_err_table[i].str;
201
202   sprintf (buf, "Unknown libthread_db error code: %d", errcode);
203
204   return buf;
205 }
206
207 /* Return the the libthread_db state string assicoated with STATECODE.
208    If STATECODE is unknown, return an appropriate message.  */
209
210 static char *
211 td_state_string (td_thr_state_e statecode)
212 {
213   static struct string_map td_thr_state_table[] =
214   {
215     { TD_THR_ANY_STATE, "any state" },
216     { TD_THR_UNKNOWN, "unknown" },
217     { TD_THR_STOPPED, "stopped" },
218     { TD_THR_RUN, "run" },
219     { TD_THR_ACTIVE, "active" },
220     { TD_THR_ZOMBIE, "zombie" },
221     { TD_THR_SLEEP, "sleep" },
222     { TD_THR_STOPPED_ASLEEP, "stopped asleep" }
223   };
224   const int td_thr_state_table_size =
225     sizeof td_thr_state_table / sizeof (struct string_map);
226   int i;
227   static char buf[50];
228
229   for (i = 0; i < td_thr_state_table_size; i++)
230     if (td_thr_state_table[i].num == statecode)
231       return td_thr_state_table[i].str;
232
233   sprintf (buf, "Unknown libthread_db state code: %d", statecode);
234
235   return buf;
236 }
237 \f
238
239 /* Convert a POSIX or Solaris thread ID into a LWP ID.  If THREAD_ID
240    doesn't exist, that's an error.  If it's an inactive thread, return
241    DEFAULT_LWP.
242
243    NOTE: This function probably shouldn't call error().  */
244
245 static ptid_t
246 thread_to_lwp (ptid_t thread_id, int default_lwp)
247 {
248   td_thrinfo_t ti;
249   td_thrhandle_t th;
250   td_err_e val;
251
252   if (is_lwp (thread_id))
253     return thread_id;           /* It's already an LWP ID.  */
254
255   /* It's a thread.  Convert to LWP.  */
256
257   val = p_td_ta_map_id2thr (main_ta, GET_THREAD (thread_id), &th);
258   if (val == TD_NOTHR)
259     return pid_to_ptid (-1);    /* Thread must have terminated.  */
260   else if (val != TD_OK)
261     error (_("thread_to_lwp: td_ta_map_id2thr %s"), td_err_string (val));
262
263   val = p_td_thr_get_info (&th, &ti);
264   if (val == TD_NOTHR)
265     return pid_to_ptid (-1);    /* Thread must have terminated.  */
266   else if (val != TD_OK)
267     error (_("thread_to_lwp: td_thr_get_info: %s"), td_err_string (val));
268
269   if (ti.ti_state != TD_THR_ACTIVE)
270     {
271       if (default_lwp != -1)
272         return pid_to_ptid (default_lwp);
273       error (_("thread_to_lwp: thread state not active: %s"),
274              td_state_string (ti.ti_state));
275     }
276
277   return BUILD_LWP (ti.ti_lid, PIDGET (thread_id));
278 }
279
280 /* Convert an LWP ID into a POSIX or Solaris thread ID.  If LWP_ID
281    doesn't exists, that's an error.
282
283    NOTE: This function probably shouldn't call error().  */
284
285 static ptid_t
286 lwp_to_thread (ptid_t lwp)
287 {
288   td_thrinfo_t ti;
289   td_thrhandle_t th;
290   td_err_e val;
291
292   if (is_thread (lwp))
293     return lwp;                 /* It's already a thread ID.  */
294
295   /* It's an LWP.  Convert it to a thread ID.  */
296
297   if (!target_thread_alive (lwp))
298     return pid_to_ptid (-1);    /* Must be a defunct LPW.  */
299
300   val = p_td_ta_map_lwp2thr (main_ta, GET_LWP (lwp), &th);
301   if (val == TD_NOTHR)
302     return pid_to_ptid (-1);    /* Thread must have terminated.  */
303   else if (val != TD_OK)
304     error (_("lwp_to_thread: td_ta_map_lwp2thr: %s."), td_err_string (val));
305
306   val = p_td_thr_validate (&th);
307   if (val == TD_NOTHR)
308     return lwp;                 /* Unknown to libthread; just return LPW,  */
309   else if (val != TD_OK)
310     error (_("lwp_to_thread: td_thr_validate: %s."), td_err_string (val));
311
312   val = p_td_thr_get_info (&th, &ti);
313   if (val == TD_NOTHR)
314     return pid_to_ptid (-1);    /* Thread must have terminated.  */
315   else if (val != TD_OK)
316     error (_("lwp_to_thread: td_thr_get_info: %s."), td_err_string (val));
317
318   return BUILD_THREAD (ti.ti_tid, PIDGET (lwp));
319 }
320 \f
321
322 /* Most target vector functions from here on actually just pass
323    through to the layer beneath, as they don't need to do anything
324    specific for threads.  */
325
326 /* Take a program previously attached to and detaches it.  The program
327    resumes execution and will no longer stop on signals, etc.  We'd
328    better not have left any breakpoints in the program or it'll die
329    when it hits one.  For this to work, it may be necessary for the
330    process to have been previously attached.  It *might* work if the
331    program was started via the normal ptrace (PTRACE_TRACEME).  */
332
333 static void
334 sol_thread_detach (struct target_ops *ops, char *args, int from_tty)
335 {
336   struct target_ops *beneath = find_target_beneath (ops);
337
338   sol_thread_active = 0;
339   inferior_ptid = pid_to_ptid (PIDGET (main_ph.ptid));
340   unpush_target (ops);
341   beneath->to_detach (beneath, args, from_tty);
342 }
343
344 /* Resume execution of process PTID.  If STEP is nozero, then just
345    single step it.  If SIGNAL is nonzero, restart it with that signal
346    activated.  We may have to convert PTID from a thread ID to an LWP
347    ID for procfs.  */
348
349 static void
350 sol_thread_resume (struct target_ops *ops,
351                    ptid_t ptid, int step, enum target_signal signo)
352 {
353   struct cleanup *old_chain;
354   struct target_ops *beneath = find_target_beneath (ops);
355
356   old_chain = save_inferior_ptid ();
357
358   inferior_ptid = thread_to_lwp (inferior_ptid, PIDGET (main_ph.ptid));
359   if (PIDGET (inferior_ptid) == -1)
360     inferior_ptid = procfs_first_available ();
361
362   if (PIDGET (ptid) != -1)
363     {
364       ptid_t save_ptid = ptid;
365
366       ptid = thread_to_lwp (ptid, -2);
367       if (PIDGET (ptid) == -2)          /* Inactive thread.  */
368         error (_("This version of Solaris can't start inactive threads."));
369       if (info_verbose && PIDGET (ptid) == -1)
370         warning (_("Specified thread %ld seems to have terminated"),
371                  GET_THREAD (save_ptid));
372     }
373
374   beneath->to_resume (beneath, ptid, step, signo);
375
376   do_cleanups (old_chain);
377 }
378
379 /* Wait for any threads to stop.  We may have to convert PTID from a
380    thread ID to an LWP ID, and vice versa on the way out.  */
381
382 static ptid_t
383 sol_thread_wait (struct target_ops *ops,
384                  ptid_t ptid, struct target_waitstatus *ourstatus, int options)
385 {
386   ptid_t rtnval;
387   ptid_t save_ptid;
388   struct target_ops *beneath = find_target_beneath (ops);
389   struct cleanup *old_chain;
390
391   save_ptid = inferior_ptid;
392   old_chain = save_inferior_ptid ();
393
394   inferior_ptid = thread_to_lwp (inferior_ptid, PIDGET (main_ph.ptid));
395   if (PIDGET (inferior_ptid) == -1)
396     inferior_ptid = procfs_first_available ();
397
398   if (PIDGET (ptid) != -1)
399     {
400       ptid_t save_ptid = ptid;
401
402       ptid = thread_to_lwp (ptid, -2);
403       if (PIDGET (ptid) == -2)          /* Inactive thread.  */
404         error (_("This version of Solaris can't start inactive threads."));
405       if (info_verbose && PIDGET (ptid) == -1)
406         warning (_("Specified thread %ld seems to have terminated"),
407                  GET_THREAD (save_ptid));
408     }
409
410   rtnval = beneath->to_wait (beneath, ptid, ourstatus, options);
411
412   if (ourstatus->kind != TARGET_WAITKIND_EXITED)
413     {
414       /* Map the LWP of interest back to the appropriate thread ID.  */
415       rtnval = lwp_to_thread (rtnval);
416       if (PIDGET (rtnval) == -1)
417         rtnval = save_ptid;
418
419       /* See if we have a new thread.  */
420       if (is_thread (rtnval)
421           && !ptid_equal (rtnval, save_ptid)
422           && (!in_thread_list (rtnval)
423               || is_exited (rtnval)))
424         add_thread (rtnval);
425     }
426
427   /* During process initialization, we may get here without the thread
428      package being initialized, since that can only happen after we've
429      found the shared libs.  */
430
431   do_cleanups (old_chain);
432
433   return rtnval;
434 }
435
436 static void
437 sol_thread_fetch_registers (struct target_ops *ops,
438                             struct regcache *regcache, int regnum)
439 {
440   thread_t thread;
441   td_thrhandle_t thandle;
442   td_err_e val;
443   prgregset_t gregset;
444   prfpregset_t fpregset;
445   gdb_gregset_t *gregset_p = &gregset;
446   gdb_fpregset_t *fpregset_p = &fpregset;
447   struct target_ops *beneath = find_target_beneath (ops);
448
449 #if 0
450   int xregsize;
451   caddr_t xregset;
452 #endif
453
454   if (!is_thread (inferior_ptid))
455     {
456       /* It's an LWP; pass the request on to the layer beneath.  */
457       beneath->to_fetch_registers (beneath, regcache, regnum);
458       return;
459     }
460
461   /* Solaris thread: convert INFERIOR_PTID into a td_thrhandle_t.  */
462   thread = GET_THREAD (inferior_ptid);
463   if (thread == 0)
464     error (_("sol_thread_fetch_registers: thread == 0"));
465
466   val = p_td_ta_map_id2thr (main_ta, thread, &thandle);
467   if (val != TD_OK)
468     error (_("sol_thread_fetch_registers: td_ta_map_id2thr: %s"),
469            td_err_string (val));
470
471   /* Get the general-purpose registers.  */
472
473   val = p_td_thr_getgregs (&thandle, gregset);
474   if (val != TD_OK && val != TD_PARTIALREG)
475     error (_("sol_thread_fetch_registers: td_thr_getgregs %s"),
476            td_err_string (val));
477
478   /* For SPARC, TD_PARTIALREG means that only %i0...%i7, %l0..%l7, %pc
479      and %sp are saved (by a thread context switch).  */
480
481   /* And, now the floating-point registers.  */
482
483   val = p_td_thr_getfpregs (&thandle, &fpregset);
484   if (val != TD_OK && val != TD_NOFPREGS)
485     error (_("sol_thread_fetch_registers: td_thr_getfpregs %s"),
486            td_err_string (val));
487
488   /* Note that we must call supply_gregset and supply_fpregset *after*
489      calling the td routines because the td routines call ps_lget*
490      which affect the values stored in the registers array.  */
491
492   supply_gregset (regcache, (const gdb_gregset_t *) gregset_p);
493   supply_fpregset (regcache, (const gdb_fpregset_t *) fpregset_p);
494
495 #if 0
496   /* FIXME: libthread_db doesn't seem to handle this right.  */
497   val = td_thr_getxregsize (&thandle, &xregsize);
498   if (val != TD_OK && val != TD_NOXREGS)
499     error (_("sol_thread_fetch_registers: td_thr_getxregsize %s"),
500            td_err_string (val));
501
502   if (val == TD_OK)
503     {
504       xregset = alloca (xregsize);
505       val = td_thr_getxregs (&thandle, xregset);
506       if (val != TD_OK)
507         error (_("sol_thread_fetch_registers: td_thr_getxregs %s"),
508                td_err_string (val));
509     }
510 #endif
511 }
512
513 static void
514 sol_thread_store_registers (struct target_ops *ops,
515                             struct regcache *regcache, int regnum)
516 {
517   thread_t thread;
518   td_thrhandle_t thandle;
519   td_err_e val;
520   prgregset_t gregset;
521   prfpregset_t fpregset;
522 #if 0
523   int xregsize;
524   caddr_t xregset;
525 #endif
526
527   if (!is_thread (inferior_ptid))
528     {
529       struct target_ops *beneath = find_target_beneath (ops);
530
531       /* It's an LWP; pass the request on to the layer beneath.  */
532       beneath->to_store_registers (beneath, regcache, regnum);
533       return;
534     }
535
536   /* Solaris thread: convert INFERIOR_PTID into a td_thrhandle_t.  */
537   thread = GET_THREAD (inferior_ptid);
538
539   val = p_td_ta_map_id2thr (main_ta, thread, &thandle);
540   if (val != TD_OK)
541     error (_("sol_thread_store_registers: td_ta_map_id2thr %s"),
542            td_err_string (val));
543
544   if (regnum != -1)
545     {
546       /* Not writing all the registers.  */
547       char old_value[MAX_REGISTER_SIZE];
548
549       /* Save new register value.  */
550       regcache_raw_collect (regcache, regnum, old_value);
551
552       val = p_td_thr_getgregs (&thandle, gregset);
553       if (val != TD_OK)
554         error (_("sol_thread_store_registers: td_thr_getgregs %s"),
555                td_err_string (val));
556       val = p_td_thr_getfpregs (&thandle, &fpregset);
557       if (val != TD_OK)
558         error (_("sol_thread_store_registers: td_thr_getfpregs %s"),
559                td_err_string (val));
560
561       /* Restore new register value.  */
562       regcache_raw_supply (regcache, regnum, old_value);
563
564 #if 0
565       /* FIXME: libthread_db doesn't seem to handle this right.  */
566       val = td_thr_getxregsize (&thandle, &xregsize);
567       if (val != TD_OK && val != TD_NOXREGS)
568         error (_("sol_thread_store_registers: td_thr_getxregsize %s"),
569                td_err_string (val));
570
571       if (val == TD_OK)
572         {
573           xregset = alloca (xregsize);
574           val = td_thr_getxregs (&thandle, xregset);
575           if (val != TD_OK)
576             error (_("sol_thread_store_registers: td_thr_getxregs %s"),
577                    td_err_string (val));
578         }
579 #endif
580     }
581
582   fill_gregset (regcache, (gdb_gregset_t *) &gregset, regnum);
583   fill_fpregset (regcache, (gdb_fpregset_t *) &fpregset, regnum);
584
585   val = p_td_thr_setgregs (&thandle, gregset);
586   if (val != TD_OK)
587     error (_("sol_thread_store_registers: td_thr_setgregs %s"),
588            td_err_string (val));
589   val = p_td_thr_setfpregs (&thandle, &fpregset);
590   if (val != TD_OK)
591     error (_("sol_thread_store_registers: td_thr_setfpregs %s"),
592            td_err_string (val));
593
594 #if 0
595   /* FIXME: libthread_db doesn't seem to handle this right.  */
596   val = td_thr_getxregsize (&thandle, &xregsize);
597   if (val != TD_OK && val != TD_NOXREGS)
598     error (_("sol_thread_store_registers: td_thr_getxregsize %s"),
599            td_err_string (val));
600
601   /* ??? Should probably do something about writing the xregs here,
602      but what are they?  */
603 #endif
604 }
605
606 /* Perform partial transfers on OBJECT.  See target_read_partial and
607    target_write_partial for details of each variant.  One, and only
608    one, of readbuf or writebuf must be non-NULL.  */
609
610 static LONGEST
611 sol_thread_xfer_partial (struct target_ops *ops, enum target_object object,
612                           const char *annex, gdb_byte *readbuf,
613                           const gdb_byte *writebuf,
614                          ULONGEST offset, LONGEST len)
615 {
616   int retval;
617   struct cleanup *old_chain;
618   struct target_ops *beneath = find_target_beneath (ops);
619
620   old_chain = save_inferior_ptid ();
621
622   if (is_thread (inferior_ptid) || !target_thread_alive (inferior_ptid))
623     {
624       /* It's either a thread or an LWP that isn't alive.  Any live
625          LWP will do so use the first available.
626
627          NOTE: We don't need to call switch_to_thread; we're just
628          reading memory.  */
629       inferior_ptid = procfs_first_available ();
630     }
631
632   retval = beneath->to_xfer_partial (beneath, object, annex,
633                                      readbuf, writebuf, offset, len);
634
635   do_cleanups (old_chain);
636
637   return retval;
638 }
639
640 static void
641 check_for_thread_db (void)
642 {
643   td_err_e err;
644   ptid_t ptid;
645
646   /* Do nothing if we couldn't load libthread_db.so.1.  */
647   if (p_td_ta_new == NULL)
648     return;
649
650   if (sol_thread_active)
651     /* Nothing to do.  The thread library was already detected and the
652        target vector was already activated.  */
653     return;
654
655   /* Now, initialize libthread_db.  This needs to be done after the
656      shared libraries are located because it needs information from
657      the user's thread library.  */
658
659   err = p_td_init ();
660   if (err != TD_OK)
661     {
662       warning (_("sol_thread_new_objfile: td_init: %s"), td_err_string (err));
663       return;
664     }
665
666   /* Now attempt to open a connection to the thread library.  */
667   err = p_td_ta_new (&main_ph, &main_ta);
668   switch (err)
669     {
670     case TD_NOLIBTHREAD:
671       /* No thread library was detected.  */
672       break;
673
674     case TD_OK:
675       printf_unfiltered (_("[Thread debugging using libthread_db enabled]\n"));
676
677       /* The thread library was detected.  Activate the sol_thread target.  */
678       push_target (&sol_thread_ops);
679       sol_thread_active = 1;
680
681       main_ph.ptid = inferior_ptid; /* Save for xfer_memory.  */
682       ptid = lwp_to_thread (inferior_ptid);
683       if (PIDGET (ptid) != -1)
684         inferior_ptid = ptid;
685
686       target_find_new_threads ();
687       break;
688
689     default:
690       warning (_("Cannot initialize thread debugging library: %s"),
691                td_err_string (err));
692       break;
693     }
694 }
695
696 /* This routine is called whenever a new symbol table is read in, or
697    when all symbol tables are removed.  libthread_db can only be
698    initialized when it finds the right variables in libthread.so.
699    Since it's a shared library, those variables don't show up until
700    the library gets mapped and the symbol table is read in.  */
701
702 static void
703 sol_thread_new_objfile (struct objfile *objfile)
704 {
705   if (objfile != NULL)
706     check_for_thread_db ();
707 }
708
709 /* Clean up after the inferior dies.  */
710
711 static void
712 sol_thread_mourn_inferior (struct target_ops *ops)
713 {
714   struct target_ops *beneath = find_target_beneath (ops);
715
716   sol_thread_active = 0;
717
718   unpush_target (ops);
719
720   beneath->to_mourn_inferior (beneath);
721 }
722
723 /* Return true if PTID is still active in the inferior.  */
724
725 static int
726 sol_thread_alive (struct target_ops *ops, ptid_t ptid)
727 {
728   if (is_thread (ptid))
729     {
730       /* It's a (user-level) thread.  */
731       td_err_e val;
732       td_thrhandle_t th;
733       int pid;
734
735       pid = GET_THREAD (ptid);
736       if ((val = p_td_ta_map_id2thr (main_ta, pid, &th)) != TD_OK)
737         return 0;               /* Thread not found.  */
738       if ((val = p_td_thr_validate (&th)) != TD_OK)
739         return 0;               /* Thread not valid.  */
740       return 1;                 /* Known thread.  */
741     }
742   else
743     {
744       struct target_ops *beneath = find_target_beneath (ops);
745
746       /* It's an LPW; pass the request on to the layer below.  */
747       return beneath->to_thread_alive (beneath, ptid);
748     }
749 }
750
751 \f
752 /* These routines implement the lower half of the thread_db interface,
753    i.e. the ps_* routines.  */
754
755 /* Various versions of <proc_service.h> have slightly different
756    function prototypes.  In particular, we have
757
758    NEWER                        OLDER
759    struct ps_prochandle *       const struct ps_prochandle *
760    void*                        char*
761    const void*                  char*
762    int                          size_t
763
764    Which one you have depends on the Solaris version and what patches
765    you've applied.  On the theory that there are only two major
766    variants, we have configure check the prototype of ps_pdwrite (),
767    and use that info to make appropriate typedefs here. */
768
769 #ifdef PROC_SERVICE_IS_OLD
770 typedef const struct ps_prochandle *gdb_ps_prochandle_t;
771 typedef char *gdb_ps_read_buf_t;
772 typedef char *gdb_ps_write_buf_t;
773 typedef int gdb_ps_size_t;
774 typedef psaddr_t gdb_ps_addr_t;
775 #else
776 typedef struct ps_prochandle *gdb_ps_prochandle_t;
777 typedef void *gdb_ps_read_buf_t;
778 typedef const void *gdb_ps_write_buf_t;
779 typedef size_t gdb_ps_size_t;
780 typedef psaddr_t gdb_ps_addr_t;
781 #endif
782
783 /* The next four routines are called by libthread_db to tell us to
784    stop and stop a particular process or lwp.  Since GDB ensures that
785    these are all stopped by the time we call anything in thread_db,
786    these routines need to do nothing.  */
787
788 /* Process stop.  */
789
790 ps_err_e
791 ps_pstop (gdb_ps_prochandle_t ph)
792 {
793   return PS_OK;
794 }
795
796 /* Process continue.  */
797
798 ps_err_e
799 ps_pcontinue (gdb_ps_prochandle_t ph)
800 {
801   return PS_OK;
802 }
803
804 /* LWP stop.  */
805
806 ps_err_e
807 ps_lstop (gdb_ps_prochandle_t ph, lwpid_t lwpid)
808 {
809   return PS_OK;
810 }
811
812 /* LWP continue.  */
813
814 ps_err_e
815 ps_lcontinue (gdb_ps_prochandle_t ph, lwpid_t lwpid)
816 {
817   return PS_OK;
818 }
819
820 /* Looks up the symbol LD_SYMBOL_NAME in the debugger's symbol table.  */
821
822 ps_err_e
823 ps_pglobal_lookup (gdb_ps_prochandle_t ph, const char *ld_object_name,
824                    const char *ld_symbol_name, gdb_ps_addr_t *ld_symbol_addr)
825 {
826   struct minimal_symbol *ms;
827
828   ms = lookup_minimal_symbol (ld_symbol_name, NULL, NULL);
829   if (!ms)
830     return PS_NOSYM;
831
832   *ld_symbol_addr = SYMBOL_VALUE_ADDRESS (ms);
833   return PS_OK;
834 }
835
836 /* Common routine for reading and writing memory.  */
837
838 static ps_err_e
839 rw_common (int dowrite, const struct ps_prochandle *ph, gdb_ps_addr_t addr,
840            char *buf, int size)
841 {
842   int ret;
843   struct cleanup *old_chain;
844
845   old_chain = save_inferior_ptid ();
846
847   if (is_thread (inferior_ptid) || !target_thread_alive (inferior_ptid))
848     {
849       /* It's either a thread or an LWP that isn't alive.  Any live
850          LWP will do so use the first available.
851
852          NOTE: We don't need to call switch_to_thread; we're just
853          reading memory.  */
854       inferior_ptid = procfs_first_available ();
855     }
856
857 #if defined (__sparcv9)
858   /* For Sparc64 cross Sparc32, make sure the address has not been
859      accidentally sign-extended (or whatever) to beyond 32 bits.  */
860   if (bfd_get_arch_size (exec_bfd) == 32)
861     addr &= 0xffffffff;
862 #endif
863
864   if (dowrite)
865     ret = target_write_memory (addr, buf, size);
866   else
867     ret = target_read_memory (addr, buf, size);
868
869   do_cleanups (old_chain);
870
871   return (ret == 0 ? PS_OK : PS_ERR);
872 }
873
874 /* Copies SIZE bytes from target process .data segment to debugger memory.  */
875
876 ps_err_e
877 ps_pdread (gdb_ps_prochandle_t ph, gdb_ps_addr_t addr,
878            gdb_ps_read_buf_t buf, gdb_ps_size_t size)
879 {
880   return rw_common (0, ph, addr, buf, size);
881 }
882
883 /* Copies SIZE bytes from debugger memory .data segment to target process.  */
884
885 ps_err_e
886 ps_pdwrite (gdb_ps_prochandle_t ph, gdb_ps_addr_t addr,
887             gdb_ps_write_buf_t buf, gdb_ps_size_t size)
888 {
889   return rw_common (1, ph, addr, (char *) buf, size);
890 }
891
892 /* Copies SIZE bytes from target process .text segment to debugger memory.  */
893
894 ps_err_e
895 ps_ptread (gdb_ps_prochandle_t ph, gdb_ps_addr_t addr,
896            gdb_ps_read_buf_t buf, gdb_ps_size_t size)
897 {
898   return rw_common (0, ph, addr, buf, size);
899 }
900
901 /* Copies SIZE bytes from debugger memory .text segment to target process.  */
902
903 ps_err_e
904 ps_ptwrite (gdb_ps_prochandle_t ph, gdb_ps_addr_t addr,
905             gdb_ps_write_buf_t buf, gdb_ps_size_t size)
906 {
907   return rw_common (1, ph, addr, (char *) buf, size);
908 }
909
910 /* Get general-purpose registers for LWP.  */
911
912 ps_err_e
913 ps_lgetregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, prgregset_t gregset)
914 {
915   struct cleanup *old_chain;
916   struct regcache *regcache;
917
918   old_chain = save_inferior_ptid ();
919
920   inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid));
921   regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch);
922
923   target_fetch_registers (regcache, -1);
924   fill_gregset (regcache, (gdb_gregset_t *) gregset, -1);
925
926   do_cleanups (old_chain);
927
928   return PS_OK;
929 }
930
931 /* Set general-purpose registers for LWP.  */
932
933 ps_err_e
934 ps_lsetregs (gdb_ps_prochandle_t ph, lwpid_t lwpid,
935              const prgregset_t gregset)
936 {
937   struct cleanup *old_chain;
938   struct regcache *regcache;
939
940   old_chain = save_inferior_ptid ();
941
942   inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid));
943   regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch);
944
945   supply_gregset (regcache, (const gdb_gregset_t *) gregset);
946   target_store_registers (regcache, -1);
947
948   do_cleanups (old_chain);
949
950   return PS_OK;
951 }
952
953 /* Log a message (sends to gdb_stderr).  */
954
955 void
956 ps_plog (const char *fmt, ...)
957 {
958   va_list args;
959
960   va_start (args, fmt);
961
962   vfprintf_filtered (gdb_stderr, fmt, args);
963 }
964
965 /* Get size of extra register set.  Currently a noop.  */
966
967 ps_err_e
968 ps_lgetxregsize (gdb_ps_prochandle_t ph, lwpid_t lwpid, int *xregsize)
969 {
970 #if 0
971   int lwp_fd;
972   int regsize;
973   ps_err_e val;
974
975   val = get_lwp_fd (ph, lwpid, &lwp_fd);
976   if (val != PS_OK)
977     return val;
978
979   if (ioctl (lwp_fd, PIOCGXREGSIZE, &regsize))
980     {
981       if (errno == EINVAL)
982         return PS_NOFREGS;      /* XXX Wrong code, but this is the closest
983                                    thing in proc_service.h  */
984
985       print_sys_errmsg ("ps_lgetxregsize (): PIOCGXREGSIZE", errno);
986       return PS_ERR;
987     }
988 #endif
989
990   return PS_OK;
991 }
992
993 /* Get extra register set.  Currently a noop.  */
994
995 ps_err_e
996 ps_lgetxregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, caddr_t xregset)
997 {
998 #if 0
999   int lwp_fd;
1000   ps_err_e val;
1001
1002   val = get_lwp_fd (ph, lwpid, &lwp_fd);
1003   if (val != PS_OK)
1004     return val;
1005
1006   if (ioctl (lwp_fd, PIOCGXREG, xregset))
1007     {
1008       print_sys_errmsg ("ps_lgetxregs (): PIOCGXREG", errno);
1009       return PS_ERR;
1010     }
1011 #endif
1012
1013   return PS_OK;
1014 }
1015
1016 /* Set extra register set.  Currently a noop.  */
1017
1018 ps_err_e
1019 ps_lsetxregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, caddr_t xregset)
1020 {
1021 #if 0
1022   int lwp_fd;
1023   ps_err_e val;
1024
1025   val = get_lwp_fd (ph, lwpid, &lwp_fd);
1026   if (val != PS_OK)
1027     return val;
1028
1029   if (ioctl (lwp_fd, PIOCSXREG, xregset))
1030     {
1031       print_sys_errmsg ("ps_lsetxregs (): PIOCSXREG", errno);
1032       return PS_ERR;
1033     }
1034 #endif
1035
1036   return PS_OK;
1037 }
1038
1039 /* Get floating-point registers for LWP.  */
1040
1041 ps_err_e
1042 ps_lgetfpregs (gdb_ps_prochandle_t ph, lwpid_t lwpid,
1043                prfpregset_t *fpregset)
1044 {
1045   struct cleanup *old_chain;
1046   struct regcache *regcache;
1047
1048   old_chain = save_inferior_ptid ();
1049
1050   inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid));
1051   regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch);
1052
1053   target_fetch_registers (regcache, -1);
1054   fill_fpregset (regcache, (gdb_fpregset_t *) fpregset, -1);
1055
1056   do_cleanups (old_chain);
1057
1058   return PS_OK;
1059 }
1060
1061 /* Set floating-point regs for LWP */
1062
1063 ps_err_e
1064 ps_lsetfpregs (gdb_ps_prochandle_t ph, lwpid_t lwpid,
1065                const prfpregset_t * fpregset)
1066 {
1067   struct cleanup *old_chain;
1068   struct regcache *regcache;
1069
1070   old_chain = save_inferior_ptid ();
1071
1072   inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid));
1073   regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch);
1074
1075   supply_fpregset (regcache, (const gdb_fpregset_t *) fpregset);
1076   target_store_registers (regcache, -1);
1077
1078   do_cleanups (old_chain);
1079
1080   return PS_OK;
1081 }
1082
1083 #ifdef PR_MODEL_LP64
1084 /* Identify process as 32-bit or 64-bit.  At the moment we're using
1085    BFD to do this.  There might be a more Solaris-specific
1086    (e.g. procfs) method, but this ought to work.  */
1087
1088 ps_err_e
1089 ps_pdmodel (gdb_ps_prochandle_t ph, int *data_model)
1090 {
1091   if (exec_bfd == 0)
1092     *data_model = PR_MODEL_UNKNOWN;
1093   else if (bfd_get_arch_size (exec_bfd) == 32)
1094     *data_model = PR_MODEL_ILP32;
1095   else
1096     *data_model = PR_MODEL_LP64;
1097
1098   return PS_OK;
1099 }
1100 #endif /* PR_MODEL_LP64 */
1101
1102 #if (defined(__i386__) || defined(__x86_64__)) && defined (sun)
1103
1104 /* Reads the local descriptor table of a LWP.
1105
1106    This function is necessary on x86-solaris only.  Without it, the loading
1107    of libthread_db would fail because of ps_lgetLDT being undefined.  */
1108
1109 ps_err_e
1110 ps_lgetLDT (gdb_ps_prochandle_t ph, lwpid_t lwpid,
1111             struct ssd *pldt)
1112 {
1113   /* NOTE: only used on Solaris, therefore OK to refer to procfs.c.  */
1114   extern struct ssd *procfs_find_LDT_entry (ptid_t);
1115   struct ssd *ret;
1116
1117   /* FIXME: can't I get the process ID from the prochandle or
1118      something?  */
1119
1120   if (PIDGET (inferior_ptid) <= 0 || lwpid <= 0)
1121     return PS_BADLID;
1122
1123   ret = procfs_find_LDT_entry (BUILD_LWP (lwpid, PIDGET (inferior_ptid)));
1124   if (ret)
1125     {
1126       memcpy (pldt, ret, sizeof (struct ssd));
1127       return PS_OK;
1128     }
1129   else
1130     /* LDT not found.  */
1131     return PS_ERR;
1132 }
1133 #endif
1134 \f
1135
1136 /* Convert PTID to printable form.  */
1137
1138 char *
1139 solaris_pid_to_str (struct target_ops *ops, ptid_t ptid)
1140 {
1141   static char buf[100];
1142
1143   if (is_thread (ptid))
1144     {
1145       ptid_t lwp;
1146
1147       lwp = thread_to_lwp (ptid, -2);
1148
1149       if (PIDGET (lwp) == -1)
1150         sprintf (buf, "Thread %ld (defunct)", GET_THREAD (ptid));
1151       else if (PIDGET (lwp) != -2)
1152         sprintf (buf, "Thread %ld (LWP %ld)",
1153                  GET_THREAD (ptid), GET_LWP (lwp));
1154       else
1155         sprintf (buf, "Thread %ld        ", GET_THREAD (ptid));
1156     }
1157   else if (GET_LWP (ptid) != 0)
1158     sprintf (buf, "LWP    %ld        ", GET_LWP (ptid));
1159   else
1160     sprintf (buf, "process %d    ", PIDGET (ptid));
1161
1162   return buf;
1163 }
1164 \f
1165
1166 /* Worker bee for find_new_threads.  Callback function that gets
1167    called once per user-level thread (i.e. not for LWP's).  */
1168
1169 static int
1170 sol_find_new_threads_callback (const td_thrhandle_t *th, void *ignored)
1171 {
1172   td_err_e retval;
1173   td_thrinfo_t ti;
1174   ptid_t ptid;
1175
1176   retval = p_td_thr_get_info (th, &ti);
1177   if (retval != TD_OK)
1178     return -1;
1179
1180   ptid = BUILD_THREAD (ti.ti_tid, PIDGET (inferior_ptid));
1181   if (!in_thread_list (ptid) || is_exited (ptid))
1182     add_thread (ptid);
1183
1184   return 0;
1185 }
1186
1187 static void
1188 sol_find_new_threads (struct target_ops *ops)
1189 {
1190   struct target_ops *beneath = find_target_beneath (ops);
1191
1192   /* First Find any new LWP's.  */
1193   if (beneath->to_find_new_threads != NULL)
1194     beneath->to_find_new_threads (beneath);
1195
1196   /* Then find any new user-level threads.  */
1197   p_td_ta_thr_iter (main_ta, sol_find_new_threads_callback, (void *) 0,
1198                     TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
1199                     TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
1200 }
1201
1202 /* Worker bee for the "info sol-thread" command.  This is a callback
1203    function that gets called once for each Solaris user-level thread
1204    (i.e. not for LWPs) in the inferior.  Print anything interesting
1205    that we can think of.  */
1206
1207 static int
1208 info_cb (const td_thrhandle_t *th, void *s)
1209 {
1210   td_err_e ret;
1211   td_thrinfo_t ti;
1212
1213   ret = p_td_thr_get_info (th, &ti);
1214   if (ret == TD_OK)
1215     {
1216       printf_filtered ("%s thread #%d, lwp %d, ",
1217                        ti.ti_type == TD_THR_SYSTEM ? "system" : "user  ",
1218                        ti.ti_tid, ti.ti_lid);
1219       switch (ti.ti_state)
1220         {
1221         default:
1222         case TD_THR_UNKNOWN:
1223           printf_filtered ("<unknown state>");
1224           break;
1225         case TD_THR_STOPPED:
1226           printf_filtered ("(stopped)");
1227           break;
1228         case TD_THR_RUN:
1229           printf_filtered ("(run)    ");
1230           break;
1231         case TD_THR_ACTIVE:
1232           printf_filtered ("(active) ");
1233           break;
1234         case TD_THR_ZOMBIE:
1235           printf_filtered ("(zombie) ");
1236           break;
1237         case TD_THR_SLEEP:
1238           printf_filtered ("(asleep) ");
1239           break;
1240         case TD_THR_STOPPED_ASLEEP:
1241           printf_filtered ("(stopped asleep)");
1242           break;
1243         }
1244       /* Print thr_create start function.  */
1245       if (ti.ti_startfunc != 0)
1246         {
1247           struct minimal_symbol *msym;
1248           msym = lookup_minimal_symbol_by_pc (ti.ti_startfunc);
1249           if (msym)
1250             printf_filtered ("   startfunc: %s\n",
1251                              SYMBOL_PRINT_NAME (msym));
1252           else
1253             printf_filtered ("   startfunc: %s\n",
1254                              paddress (target_gdbarch, ti.ti_startfunc));
1255         }
1256
1257       /* If thread is asleep, print function that went to sleep.  */
1258       if (ti.ti_state == TD_THR_SLEEP)
1259         {
1260           struct minimal_symbol *msym;
1261           msym = lookup_minimal_symbol_by_pc (ti.ti_pc);
1262           if (msym)
1263             printf_filtered (" - Sleep func: %s\n",
1264                              SYMBOL_PRINT_NAME (msym));
1265           else
1266             printf_filtered (" - Sleep func: %s\n",
1267                              paddress (target_gdbarch, ti.ti_startfunc));
1268         }
1269
1270       /* Wrap up line, if necessary.  */
1271       if (ti.ti_state != TD_THR_SLEEP && ti.ti_startfunc == 0)
1272         printf_filtered ("\n"); /* don't you hate counting newlines? */
1273     }
1274   else
1275     warning (_("info sol-thread: failed to get info for thread."));
1276
1277   return 0;
1278 }
1279
1280 /* List some state about each Solaris user-level thread in the
1281    inferior.  */
1282
1283 static void
1284 info_solthreads (char *args, int from_tty)
1285 {
1286   p_td_ta_thr_iter (main_ta, info_cb, args,
1287                     TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
1288                     TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
1289 }
1290
1291 static void
1292 init_sol_thread_ops (void)
1293 {
1294   sol_thread_ops.to_shortname = "solaris-threads";
1295   sol_thread_ops.to_longname = "Solaris threads and pthread.";
1296   sol_thread_ops.to_doc = "Solaris threads and pthread support.";
1297   sol_thread_ops.to_detach = sol_thread_detach;
1298   sol_thread_ops.to_resume = sol_thread_resume;
1299   sol_thread_ops.to_wait = sol_thread_wait;
1300   sol_thread_ops.to_fetch_registers = sol_thread_fetch_registers;
1301   sol_thread_ops.to_store_registers = sol_thread_store_registers;
1302   sol_thread_ops.to_xfer_partial = sol_thread_xfer_partial;
1303   sol_thread_ops.to_mourn_inferior = sol_thread_mourn_inferior;
1304   sol_thread_ops.to_thread_alive = sol_thread_alive;
1305   sol_thread_ops.to_pid_to_str = solaris_pid_to_str;
1306   sol_thread_ops.to_find_new_threads = sol_find_new_threads;
1307   sol_thread_ops.to_stratum = thread_stratum;
1308   sol_thread_ops.to_magic = OPS_MAGIC;
1309 }
1310
1311 void
1312 _initialize_sol_thread (void)
1313 {
1314   void *dlhandle;
1315
1316   init_sol_thread_ops ();
1317
1318   dlhandle = dlopen ("libthread_db.so.1", RTLD_NOW);
1319   if (!dlhandle)
1320     goto die;
1321
1322 #define resolve(X) \
1323   if (!(p_##X = dlsym (dlhandle, #X))) \
1324     goto die;
1325
1326   resolve (td_log);
1327   resolve (td_ta_new);
1328   resolve (td_ta_delete);
1329   resolve (td_init);
1330   resolve (td_ta_get_ph);
1331   resolve (td_ta_get_nthreads);
1332   resolve (td_ta_tsd_iter);
1333   resolve (td_ta_thr_iter);
1334   resolve (td_thr_validate);
1335   resolve (td_thr_tsd);
1336   resolve (td_thr_get_info);
1337   resolve (td_thr_getfpregs);
1338   resolve (td_thr_getxregsize);
1339   resolve (td_thr_getxregs);
1340   resolve (td_thr_sigsetmask);
1341   resolve (td_thr_setprio);
1342   resolve (td_thr_setsigpending);
1343   resolve (td_thr_setfpregs);
1344   resolve (td_thr_setxregs);
1345   resolve (td_ta_map_id2thr);
1346   resolve (td_ta_map_lwp2thr);
1347   resolve (td_thr_getgregs);
1348   resolve (td_thr_setgregs);
1349
1350   add_target (&sol_thread_ops);
1351
1352   add_cmd ("sol-threads", class_maintenance, info_solthreads,
1353            _("Show info on Solaris user threads."), &maintenanceinfolist);
1354
1355   /* Hook into new_objfile notification.  */
1356   observer_attach_new_objfile (sol_thread_new_objfile);
1357   return;
1358
1359  die:
1360   fprintf_unfiltered (gdb_stderr, "\
1361 [GDB will not be able to debug user-mode threads: %s]\n", dlerror ());
1362
1363   if (dlhandle)
1364     dlclose (dlhandle);
1365
1366   return;
1367 }