GDB (API)
/home/stan/gdb/src/gdb/sol-thread.c
Go to the documentation of this file.
00001 /* Solaris threads debugging interface.
00002 
00003    Copyright (C) 1996-2013 Free Software Foundation, Inc.
00004 
00005    This file is part of GDB.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 3 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00019 
00020 /* This module implements a sort of half target that sits between the
00021    machine-independent parts of GDB and the /proc interface (procfs.c)
00022    to provide access to the Solaris user-mode thread implementation.
00023 
00024    Solaris threads are true user-mode threads, which are invoked via
00025    the thr_* and pthread_* (native and POSIX respectivly) interfaces.
00026    These are mostly implemented in user-space, with all thread context
00027    kept in various structures that live in the user's heap.  These
00028    should not be confused with lightweight processes (LWPs), which are
00029    implemented by the kernel, and scheduled without explicit
00030    intervention by the process.
00031 
00032    Just to confuse things a little, Solaris threads (both native and
00033    POSIX) are actually implemented using LWPs.  In general, there are
00034    going to be more threads than LWPs.  There is no fixed
00035    correspondence between a thread and an LWP.  When a thread wants to
00036    run, it gets scheduled onto the first available LWP and can
00037    therefore migrate from one LWP to another as time goes on.  A
00038    sleeping thread may not be associated with an LWP at all!
00039 
00040    To make it possible to mess with threads, Sun provides a library
00041    called libthread_db.so.1 (not to be confused with
00042    libthread_db.so.0, which doesn't have a published interface).  This
00043    interface has an upper part, which it provides, and a lower part
00044    which we provide.  The upper part consists of the td_* routines,
00045    which allow us to find all the threads, query their state, etc...
00046    The lower part consists of all of the ps_*, which are used by the
00047    td_* routines to read/write memory, manipulate LWPs, lookup
00048    symbols, etc...  The ps_* routines actually do most of their work
00049    by calling functions in procfs.c.  */
00050 
00051 #include "defs.h"
00052 #include <thread.h>
00053 #include <proc_service.h>
00054 #include <thread_db.h>
00055 #include "gdbthread.h"
00056 #include "target.h"
00057 #include "inferior.h"
00058 #include <fcntl.h>
00059 #include "gdb_stat.h"
00060 #include <dlfcn.h>
00061 #include "gdbcmd.h"
00062 #include "gdbcore.h"
00063 #include "regcache.h"
00064 #include "solib.h"
00065 #include "symfile.h"
00066 #include "observer.h"
00067 #include "gdb_string.h"
00068 #include "procfs.h"
00069 
00070 struct target_ops sol_thread_ops;
00071 
00072 /* Prototypes for supply_gregset etc.  */
00073 #include "gregset.h"
00074 
00075 /* This struct is defined by us, but mainly used for the proc_service
00076    interface.  We don't have much use for it, except as a handy place
00077    to get a real PID for memory accesses.  */
00078 
00079 struct ps_prochandle
00080 {
00081   ptid_t ptid;
00082 };
00083 
00084 struct string_map
00085 {
00086   int num;
00087   char *str;
00088 };
00089 
00090 static struct ps_prochandle main_ph;
00091 static td_thragent_t *main_ta;
00092 static int sol_thread_active = 0;
00093 
00094 static void init_sol_thread_ops (void);
00095 
00096 /* Default definitions: These must be defined in tm.h if they are to
00097    be shared with a process module such as procfs.  */
00098 
00099 /* Pointers to routines from libthread_db resolved by dlopen().  */
00100 
00101 static void (*p_td_log)(const int on_off);
00102 static td_err_e (*p_td_ta_new)(const struct ps_prochandle *ph_p,
00103                                td_thragent_t **ta_pp);
00104 static td_err_e (*p_td_ta_delete)(td_thragent_t *ta_p);
00105 static td_err_e (*p_td_init)(void);
00106 static td_err_e (*p_td_ta_get_ph)(const td_thragent_t *ta_p,
00107                                   struct ps_prochandle **ph_pp);
00108 static td_err_e (*p_td_ta_get_nthreads)(const td_thragent_t *ta_p,
00109                                         int *nthread_p);
00110 static td_err_e (*p_td_ta_tsd_iter)(const td_thragent_t *ta_p,
00111                                     td_key_iter_f *cb, void *cbdata_p);
00112 static td_err_e (*p_td_ta_thr_iter)(const td_thragent_t *ta_p,
00113                                     td_thr_iter_f *cb, void *cbdata_p,
00114                                     td_thr_state_e state, int ti_pri,
00115                                     sigset_t *ti_sigmask_p,
00116                                     unsigned ti_user_flags);
00117 static td_err_e (*p_td_thr_validate)(const td_thrhandle_t *th_p);
00118 static td_err_e (*p_td_thr_tsd)(const td_thrhandle_t * th_p,
00119                                 const thread_key_t key, void **data_pp);
00120 static td_err_e (*p_td_thr_get_info)(const td_thrhandle_t *th_p,
00121                                      td_thrinfo_t *ti_p);
00122 static td_err_e (*p_td_thr_getfpregs)(const td_thrhandle_t *th_p,
00123                                       prfpregset_t *fpregset);
00124 static td_err_e (*p_td_thr_getxregsize)(const td_thrhandle_t *th_p,
00125                                         int *xregsize);
00126 static td_err_e (*p_td_thr_getxregs)(const td_thrhandle_t *th_p,
00127                                      const caddr_t xregset);
00128 static td_err_e (*p_td_thr_sigsetmask)(const td_thrhandle_t *th_p,
00129                                        const sigset_t ti_sigmask);
00130 static td_err_e (*p_td_thr_setprio)(const td_thrhandle_t *th_p,
00131                                     const int ti_pri);
00132 static td_err_e (*p_td_thr_setsigpending)(const td_thrhandle_t *th_p,
00133                                           const uchar_t ti_pending_flag,
00134                                           const sigset_t ti_pending);
00135 static td_err_e (*p_td_thr_setfpregs)(const td_thrhandle_t *th_p,
00136                                       const prfpregset_t *fpregset);
00137 static td_err_e (*p_td_thr_setxregs)(const td_thrhandle_t *th_p,
00138                                      const caddr_t xregset);
00139 static td_err_e (*p_td_ta_map_id2thr)(const td_thragent_t *ta_p,
00140                                       thread_t tid,
00141                                       td_thrhandle_t *th_p);
00142 static td_err_e (*p_td_ta_map_lwp2thr)(const td_thragent_t *ta_p,
00143                                        lwpid_t lwpid,
00144                                        td_thrhandle_t *th_p);
00145 static td_err_e (*p_td_thr_getgregs)(const td_thrhandle_t *th_p,
00146                                      prgregset_t regset);
00147 static td_err_e (*p_td_thr_setgregs)(const td_thrhandle_t *th_p,
00148                                      const prgregset_t regset);
00149 
00150 
00151 /* Return the libthread_db error string associated with ERRCODE.  If
00152    ERRCODE is unknown, return an appropriate message.  */
00153 
00154 static char *
00155 td_err_string (td_err_e errcode)
00156 {
00157   static struct string_map td_err_table[] =
00158   {
00159     { TD_OK, "generic \"call succeeded\"" },
00160     { TD_ERR, "generic error." },
00161     { TD_NOTHR, "no thread can be found to satisfy query" },
00162     { TD_NOSV, "no synch. variable can be found to satisfy query" },
00163     { TD_NOLWP, "no lwp can be found to satisfy query" },
00164     { TD_BADPH, "invalid process handle" },
00165     { TD_BADTH, "invalid thread handle" },
00166     { TD_BADSH, "invalid synchronization handle" },
00167     { TD_BADTA, "invalid thread agent" },
00168     { TD_BADKEY, "invalid key" },
00169     { TD_NOMSG, "td_thr_event_getmsg() called when there was no message" },
00170     { TD_NOFPREGS, "FPU register set not available for given thread" },
00171     { TD_NOLIBTHREAD, "application not linked with libthread" },
00172     { TD_NOEVENT, "requested event is not supported" },
00173     { TD_NOCAPAB, "capability not available" },
00174     { TD_DBERR, "Debugger service failed" },
00175     { TD_NOAPLIC, "Operation not applicable to" },
00176     { TD_NOTSD, "No thread specific data for this thread" },
00177     { TD_MALLOC, "Malloc failed" },
00178     { TD_PARTIALREG, "Only part of register set was written/read" },
00179     { TD_NOXREGS, "X register set not available for given thread" }
00180   };
00181   const int td_err_size = sizeof td_err_table / sizeof (struct string_map);
00182   int i;
00183   static char buf[50];
00184 
00185   for (i = 0; i < td_err_size; i++)
00186     if (td_err_table[i].num == errcode)
00187       return td_err_table[i].str;
00188 
00189   xsnprintf (buf, sizeof (buf), "Unknown libthread_db error code: %d",
00190              errcode);
00191 
00192   return buf;
00193 }
00194 
00195 /* Return the libthread_db state string assicoated with STATECODE.
00196    If STATECODE is unknown, return an appropriate message.  */
00197 
00198 static char *
00199 td_state_string (td_thr_state_e statecode)
00200 {
00201   static struct string_map td_thr_state_table[] =
00202   {
00203     { TD_THR_ANY_STATE, "any state" },
00204     { TD_THR_UNKNOWN, "unknown" },
00205     { TD_THR_STOPPED, "stopped" },
00206     { TD_THR_RUN, "run" },
00207     { TD_THR_ACTIVE, "active" },
00208     { TD_THR_ZOMBIE, "zombie" },
00209     { TD_THR_SLEEP, "sleep" },
00210     { TD_THR_STOPPED_ASLEEP, "stopped asleep" }
00211   };
00212   const int td_thr_state_table_size =
00213     sizeof td_thr_state_table / sizeof (struct string_map);
00214   int i;
00215   static char buf[50];
00216 
00217   for (i = 0; i < td_thr_state_table_size; i++)
00218     if (td_thr_state_table[i].num == statecode)
00219       return td_thr_state_table[i].str;
00220 
00221   xsnprintf (buf, sizeof (buf), "Unknown libthread_db state code: %d",
00222              statecode);
00223 
00224   return buf;
00225 }
00226 
00227 
00228 /* Convert a POSIX or Solaris thread ID into a LWP ID.  If THREAD_ID
00229    doesn't exist, that's an error.  If it's an inactive thread, return
00230    DEFAULT_LWP.
00231 
00232    NOTE: This function probably shouldn't call error().  */
00233 
00234 static ptid_t
00235 thread_to_lwp (ptid_t thread_id, int default_lwp)
00236 {
00237   td_thrinfo_t ti;
00238   td_thrhandle_t th;
00239   td_err_e val;
00240 
00241   if (ptid_lwp_p (thread_id))
00242     return thread_id;           /* It's already an LWP ID.  */
00243 
00244   /* It's a thread.  Convert to LWP.  */
00245 
00246   val = p_td_ta_map_id2thr (main_ta, ptid_get_tid (thread_id), &th);
00247   if (val == TD_NOTHR)
00248     return pid_to_ptid (-1);    /* Thread must have terminated.  */
00249   else if (val != TD_OK)
00250     error (_("thread_to_lwp: td_ta_map_id2thr %s"), td_err_string (val));
00251 
00252   val = p_td_thr_get_info (&th, &ti);
00253   if (val == TD_NOTHR)
00254     return pid_to_ptid (-1);    /* Thread must have terminated.  */
00255   else if (val != TD_OK)
00256     error (_("thread_to_lwp: td_thr_get_info: %s"), td_err_string (val));
00257 
00258   if (ti.ti_state != TD_THR_ACTIVE)
00259     {
00260       if (default_lwp != -1)
00261         return pid_to_ptid (default_lwp);
00262       error (_("thread_to_lwp: thread state not active: %s"),
00263              td_state_string (ti.ti_state));
00264     }
00265 
00266   return ptid_build (ptid_get_pid (thread_id), ti.ti_lid, 0);
00267 }
00268 
00269 /* Convert an LWP ID into a POSIX or Solaris thread ID.  If LWP_ID
00270    doesn't exists, that's an error.
00271 
00272    NOTE: This function probably shouldn't call error().  */
00273 
00274 static ptid_t
00275 lwp_to_thread (ptid_t lwp)
00276 {
00277   td_thrinfo_t ti;
00278   td_thrhandle_t th;
00279   td_err_e val;
00280 
00281   if (ptid_tid_p (lwp))
00282     return lwp;                 /* It's already a thread ID.  */
00283 
00284   /* It's an LWP.  Convert it to a thread ID.  */
00285 
00286   if (!target_thread_alive (lwp))
00287     return pid_to_ptid (-1);    /* Must be a defunct LPW.  */
00288 
00289   val = p_td_ta_map_lwp2thr (main_ta, ptid_get_lwp (lwp), &th);
00290   if (val == TD_NOTHR)
00291     return pid_to_ptid (-1);    /* Thread must have terminated.  */
00292   else if (val != TD_OK)
00293     error (_("lwp_to_thread: td_ta_map_lwp2thr: %s."), td_err_string (val));
00294 
00295   val = p_td_thr_validate (&th);
00296   if (val == TD_NOTHR)
00297     return lwp;                 /* Unknown to libthread; just return LPW,  */
00298   else if (val != TD_OK)
00299     error (_("lwp_to_thread: td_thr_validate: %s."), td_err_string (val));
00300 
00301   val = p_td_thr_get_info (&th, &ti);
00302   if (val == TD_NOTHR)
00303     return pid_to_ptid (-1);    /* Thread must have terminated.  */
00304   else if (val != TD_OK)
00305     error (_("lwp_to_thread: td_thr_get_info: %s."), td_err_string (val));
00306 
00307   return ptid_build (ptid_get_pid (lwp), 0 , ti.ti_tid);
00308 }
00309 
00310 
00311 /* Most target vector functions from here on actually just pass
00312    through to the layer beneath, as they don't need to do anything
00313    specific for threads.  */
00314 
00315 /* Take a program previously attached to and detaches it.  The program
00316    resumes execution and will no longer stop on signals, etc.  We'd
00317    better not have left any breakpoints in the program or it'll die
00318    when it hits one.  For this to work, it may be necessary for the
00319    process to have been previously attached.  It *might* work if the
00320    program was started via the normal ptrace (PTRACE_TRACEME).  */
00321 
00322 static void
00323 sol_thread_detach (struct target_ops *ops, char *args, int from_tty)
00324 {
00325   struct target_ops *beneath = find_target_beneath (ops);
00326 
00327   sol_thread_active = 0;
00328   inferior_ptid = pid_to_ptid (ptid_get_pid (main_ph.ptid));
00329   unpush_target (ops);
00330   beneath->to_detach (beneath, args, from_tty);
00331 }
00332 
00333 /* Resume execution of process PTID.  If STEP is nozero, then just
00334    single step it.  If SIGNAL is nonzero, restart it with that signal
00335    activated.  We may have to convert PTID from a thread ID to an LWP
00336    ID for procfs.  */
00337 
00338 static void
00339 sol_thread_resume (struct target_ops *ops,
00340                    ptid_t ptid, int step, enum gdb_signal signo)
00341 {
00342   struct cleanup *old_chain;
00343   struct target_ops *beneath = find_target_beneath (ops);
00344 
00345   old_chain = save_inferior_ptid ();
00346 
00347   inferior_ptid = thread_to_lwp (inferior_ptid, ptid_get_pid (main_ph.ptid));
00348   if (ptid_get_pid (inferior_ptid) == -1)
00349     inferior_ptid = procfs_first_available ();
00350 
00351   if (ptid_get_pid (ptid) != -1)
00352     {
00353       ptid_t save_ptid = ptid;
00354 
00355       ptid = thread_to_lwp (ptid, -2);
00356       if (ptid_get_pid (ptid) == -2)            /* Inactive thread.  */
00357         error (_("This version of Solaris can't start inactive threads."));
00358       if (info_verbose && ptid_get_pid (ptid) == -1)
00359         warning (_("Specified thread %ld seems to have terminated"),
00360                  ptid_get_tid (save_ptid));
00361     }
00362 
00363   beneath->to_resume (beneath, ptid, step, signo);
00364 
00365   do_cleanups (old_chain);
00366 }
00367 
00368 /* Wait for any threads to stop.  We may have to convert PTID from a
00369    thread ID to an LWP ID, and vice versa on the way out.  */
00370 
00371 static ptid_t
00372 sol_thread_wait (struct target_ops *ops,
00373                  ptid_t ptid, struct target_waitstatus *ourstatus, int options)
00374 {
00375   ptid_t rtnval;
00376   ptid_t save_ptid;
00377   struct target_ops *beneath = find_target_beneath (ops);
00378   struct cleanup *old_chain;
00379 
00380   save_ptid = inferior_ptid;
00381   old_chain = save_inferior_ptid ();
00382 
00383   inferior_ptid = thread_to_lwp (inferior_ptid, ptid_get_pid (main_ph.ptid));
00384   if (ptid_get_pid (inferior_ptid) == -1)
00385     inferior_ptid = procfs_first_available ();
00386 
00387   if (ptid_get_pid (ptid) != -1)
00388     {
00389       ptid_t save_ptid = ptid;
00390 
00391       ptid = thread_to_lwp (ptid, -2);
00392       if (ptid_get_pid (ptid) == -2)            /* Inactive thread.  */
00393         error (_("This version of Solaris can't start inactive threads."));
00394       if (info_verbose && ptid_get_pid (ptid) == -1)
00395         warning (_("Specified thread %ld seems to have terminated"),
00396                  ptid_get_tid (save_ptid));
00397     }
00398 
00399   rtnval = beneath->to_wait (beneath, ptid, ourstatus, options);
00400 
00401   if (ourstatus->kind != TARGET_WAITKIND_EXITED)
00402     {
00403       /* Map the LWP of interest back to the appropriate thread ID.  */
00404       rtnval = lwp_to_thread (rtnval);
00405       if (ptid_get_pid (rtnval) == -1)
00406         rtnval = save_ptid;
00407 
00408       /* See if we have a new thread.  */
00409       if (ptid_tid_p (rtnval)
00410           && !ptid_equal (rtnval, save_ptid)
00411           && (!in_thread_list (rtnval)
00412               || is_exited (rtnval)))
00413         add_thread (rtnval);
00414     }
00415 
00416   /* During process initialization, we may get here without the thread
00417      package being initialized, since that can only happen after we've
00418      found the shared libs.  */
00419 
00420   do_cleanups (old_chain);
00421 
00422   return rtnval;
00423 }
00424 
00425 static void
00426 sol_thread_fetch_registers (struct target_ops *ops,
00427                             struct regcache *regcache, int regnum)
00428 {
00429   thread_t thread;
00430   td_thrhandle_t thandle;
00431   td_err_e val;
00432   prgregset_t gregset;
00433   prfpregset_t fpregset;
00434   gdb_gregset_t *gregset_p = &gregset;
00435   gdb_fpregset_t *fpregset_p = &fpregset;
00436   struct target_ops *beneath = find_target_beneath (ops);
00437 
00438   if (!ptid_tid_p (inferior_ptid))
00439     {
00440       /* It's an LWP; pass the request on to the layer beneath.  */
00441       beneath->to_fetch_registers (beneath, regcache, regnum);
00442       return;
00443     }
00444 
00445   /* Solaris thread: convert INFERIOR_PTID into a td_thrhandle_t.  */
00446   thread = ptid_get_tid (inferior_ptid);
00447   if (thread == 0)
00448     error (_("sol_thread_fetch_registers: thread == 0"));
00449 
00450   val = p_td_ta_map_id2thr (main_ta, thread, &thandle);
00451   if (val != TD_OK)
00452     error (_("sol_thread_fetch_registers: td_ta_map_id2thr: %s"),
00453            td_err_string (val));
00454 
00455   /* Get the general-purpose registers.  */
00456 
00457   val = p_td_thr_getgregs (&thandle, gregset);
00458   if (val != TD_OK && val != TD_PARTIALREG)
00459     error (_("sol_thread_fetch_registers: td_thr_getgregs %s"),
00460            td_err_string (val));
00461 
00462   /* For SPARC, TD_PARTIALREG means that only %i0...%i7, %l0..%l7, %pc
00463      and %sp are saved (by a thread context switch).  */
00464 
00465   /* And, now the floating-point registers.  */
00466 
00467   val = p_td_thr_getfpregs (&thandle, &fpregset);
00468   if (val != TD_OK && val != TD_NOFPREGS)
00469     error (_("sol_thread_fetch_registers: td_thr_getfpregs %s"),
00470            td_err_string (val));
00471 
00472   /* Note that we must call supply_gregset and supply_fpregset *after*
00473      calling the td routines because the td routines call ps_lget*
00474      which affect the values stored in the registers array.  */
00475 
00476   supply_gregset (regcache, (const gdb_gregset_t *) gregset_p);
00477   supply_fpregset (regcache, (const gdb_fpregset_t *) fpregset_p);
00478 }
00479 
00480 static void
00481 sol_thread_store_registers (struct target_ops *ops,
00482                             struct regcache *regcache, int regnum)
00483 {
00484   thread_t thread;
00485   td_thrhandle_t thandle;
00486   td_err_e val;
00487   prgregset_t gregset;
00488   prfpregset_t fpregset;
00489 
00490   if (!ptid_tid_p (inferior_ptid))
00491     {
00492       struct target_ops *beneath = find_target_beneath (ops);
00493 
00494       /* It's an LWP; pass the request on to the layer beneath.  */
00495       beneath->to_store_registers (beneath, regcache, regnum);
00496       return;
00497     }
00498 
00499   /* Solaris thread: convert INFERIOR_PTID into a td_thrhandle_t.  */
00500   thread = ptid_get_tid (inferior_ptid);
00501 
00502   val = p_td_ta_map_id2thr (main_ta, thread, &thandle);
00503   if (val != TD_OK)
00504     error (_("sol_thread_store_registers: td_ta_map_id2thr %s"),
00505            td_err_string (val));
00506 
00507   if (regnum != -1)
00508     {
00509       /* Not writing all the registers.  */
00510       char old_value[MAX_REGISTER_SIZE];
00511 
00512       /* Save new register value.  */
00513       regcache_raw_collect (regcache, regnum, old_value);
00514 
00515       val = p_td_thr_getgregs (&thandle, gregset);
00516       if (val != TD_OK)
00517         error (_("sol_thread_store_registers: td_thr_getgregs %s"),
00518                td_err_string (val));
00519       val = p_td_thr_getfpregs (&thandle, &fpregset);
00520       if (val != TD_OK)
00521         error (_("sol_thread_store_registers: td_thr_getfpregs %s"),
00522                td_err_string (val));
00523 
00524       /* Restore new register value.  */
00525       regcache_raw_supply (regcache, regnum, old_value);
00526     }
00527 
00528   fill_gregset (regcache, (gdb_gregset_t *) &gregset, regnum);
00529   fill_fpregset (regcache, (gdb_fpregset_t *) &fpregset, regnum);
00530 
00531   val = p_td_thr_setgregs (&thandle, gregset);
00532   if (val != TD_OK)
00533     error (_("sol_thread_store_registers: td_thr_setgregs %s"),
00534            td_err_string (val));
00535   val = p_td_thr_setfpregs (&thandle, &fpregset);
00536   if (val != TD_OK)
00537     error (_("sol_thread_store_registers: td_thr_setfpregs %s"),
00538            td_err_string (val));
00539 }
00540 
00541 /* Perform partial transfers on OBJECT.  See target_read_partial and
00542    target_write_partial for details of each variant.  One, and only
00543    one, of readbuf or writebuf must be non-NULL.  */
00544 
00545 static LONGEST
00546 sol_thread_xfer_partial (struct target_ops *ops, enum target_object object,
00547                           const char *annex, gdb_byte *readbuf,
00548                           const gdb_byte *writebuf,
00549                          ULONGEST offset, LONGEST len)
00550 {
00551   int retval;
00552   struct cleanup *old_chain;
00553   struct target_ops *beneath = find_target_beneath (ops);
00554 
00555   old_chain = save_inferior_ptid ();
00556 
00557   if (ptid_tid_p (inferior_ptid) || !target_thread_alive (inferior_ptid))
00558     {
00559       /* It's either a thread or an LWP that isn't alive.  Any live
00560          LWP will do so use the first available.
00561 
00562          NOTE: We don't need to call switch_to_thread; we're just
00563          reading memory.  */
00564       inferior_ptid = procfs_first_available ();
00565     }
00566 
00567   retval = beneath->to_xfer_partial (beneath, object, annex,
00568                                      readbuf, writebuf, offset, len);
00569 
00570   do_cleanups (old_chain);
00571 
00572   return retval;
00573 }
00574 
00575 static void
00576 check_for_thread_db (void)
00577 {
00578   td_err_e err;
00579   ptid_t ptid;
00580 
00581   /* Do nothing if we couldn't load libthread_db.so.1.  */
00582   if (p_td_ta_new == NULL)
00583     return;
00584 
00585   if (sol_thread_active)
00586     /* Nothing to do.  The thread library was already detected and the
00587        target vector was already activated.  */
00588     return;
00589 
00590   /* Now, initialize libthread_db.  This needs to be done after the
00591      shared libraries are located because it needs information from
00592      the user's thread library.  */
00593 
00594   err = p_td_init ();
00595   if (err != TD_OK)
00596     {
00597       warning (_("sol_thread_new_objfile: td_init: %s"), td_err_string (err));
00598       return;
00599     }
00600 
00601   /* Now attempt to open a connection to the thread library.  */
00602   err = p_td_ta_new (&main_ph, &main_ta);
00603   switch (err)
00604     {
00605     case TD_NOLIBTHREAD:
00606       /* No thread library was detected.  */
00607       break;
00608 
00609     case TD_OK:
00610       printf_unfiltered (_("[Thread debugging using libthread_db enabled]\n"));
00611 
00612       /* The thread library was detected.  Activate the sol_thread target.  */
00613       push_target (&sol_thread_ops);
00614       sol_thread_active = 1;
00615 
00616       main_ph.ptid = inferior_ptid; /* Save for xfer_memory.  */
00617       ptid = lwp_to_thread (inferior_ptid);
00618       if (ptid_get_pid (ptid) != -1)
00619         inferior_ptid = ptid;
00620 
00621       target_find_new_threads ();
00622       break;
00623 
00624     default:
00625       warning (_("Cannot initialize thread debugging library: %s"),
00626                td_err_string (err));
00627       break;
00628     }
00629 }
00630 
00631 /* This routine is called whenever a new symbol table is read in, or
00632    when all symbol tables are removed.  libthread_db can only be
00633    initialized when it finds the right variables in libthread.so.
00634    Since it's a shared library, those variables don't show up until
00635    the library gets mapped and the symbol table is read in.  */
00636 
00637 static void
00638 sol_thread_new_objfile (struct objfile *objfile)
00639 {
00640   if (objfile != NULL)
00641     check_for_thread_db ();
00642 }
00643 
00644 /* Clean up after the inferior dies.  */
00645 
00646 static void
00647 sol_thread_mourn_inferior (struct target_ops *ops)
00648 {
00649   struct target_ops *beneath = find_target_beneath (ops);
00650 
00651   sol_thread_active = 0;
00652 
00653   unpush_target (ops);
00654 
00655   beneath->to_mourn_inferior (beneath);
00656 }
00657 
00658 /* Return true if PTID is still active in the inferior.  */
00659 
00660 static int
00661 sol_thread_alive (struct target_ops *ops, ptid_t ptid)
00662 {
00663   if (ptid_tid_p (ptid))
00664     {
00665       /* It's a (user-level) thread.  */
00666       td_err_e val;
00667       td_thrhandle_t th;
00668       int pid;
00669 
00670       pid = ptid_get_tid (ptid);
00671       if ((val = p_td_ta_map_id2thr (main_ta, pid, &th)) != TD_OK)
00672         return 0;               /* Thread not found.  */
00673       if ((val = p_td_thr_validate (&th)) != TD_OK)
00674         return 0;               /* Thread not valid.  */
00675       return 1;                 /* Known thread.  */
00676     }
00677   else
00678     {
00679       struct target_ops *beneath = find_target_beneath (ops);
00680 
00681       /* It's an LPW; pass the request on to the layer below.  */
00682       return beneath->to_thread_alive (beneath, ptid);
00683     }
00684 }
00685 
00686 
00687 /* These routines implement the lower half of the thread_db interface,
00688    i.e. the ps_* routines.  */
00689 
00690 /* Various versions of <proc_service.h> have slightly different
00691    function prototypes.  In particular, we have
00692 
00693    NEWER                        OLDER
00694    struct ps_prochandle *       const struct ps_prochandle *
00695    void*                        char*
00696    const void*                  char*
00697    int                          size_t
00698 
00699    Which one you have depends on the Solaris version and what patches
00700    you've applied.  On the theory that there are only two major
00701    variants, we have configure check the prototype of ps_pdwrite (),
00702    and use that info to make appropriate typedefs here.  */
00703 
00704 #ifdef PROC_SERVICE_IS_OLD
00705 typedef const struct ps_prochandle *gdb_ps_prochandle_t;
00706 typedef char *gdb_ps_read_buf_t;
00707 typedef char *gdb_ps_write_buf_t;
00708 typedef int gdb_ps_size_t;
00709 typedef psaddr_t gdb_ps_addr_t;
00710 #else
00711 typedef struct ps_prochandle *gdb_ps_prochandle_t;
00712 typedef void *gdb_ps_read_buf_t;
00713 typedef const void *gdb_ps_write_buf_t;
00714 typedef size_t gdb_ps_size_t;
00715 typedef psaddr_t gdb_ps_addr_t;
00716 #endif
00717 
00718 /* The next four routines are called by libthread_db to tell us to
00719    stop and stop a particular process or lwp.  Since GDB ensures that
00720    these are all stopped by the time we call anything in thread_db,
00721    these routines need to do nothing.  */
00722 
00723 /* Process stop.  */
00724 
00725 ps_err_e
00726 ps_pstop (gdb_ps_prochandle_t ph)
00727 {
00728   return PS_OK;
00729 }
00730 
00731 /* Process continue.  */
00732 
00733 ps_err_e
00734 ps_pcontinue (gdb_ps_prochandle_t ph)
00735 {
00736   return PS_OK;
00737 }
00738 
00739 /* LWP stop.  */
00740 
00741 ps_err_e
00742 ps_lstop (gdb_ps_prochandle_t ph, lwpid_t lwpid)
00743 {
00744   return PS_OK;
00745 }
00746 
00747 /* LWP continue.  */
00748 
00749 ps_err_e
00750 ps_lcontinue (gdb_ps_prochandle_t ph, lwpid_t lwpid)
00751 {
00752   return PS_OK;
00753 }
00754 
00755 /* Looks up the symbol LD_SYMBOL_NAME in the debugger's symbol table.  */
00756 
00757 ps_err_e
00758 ps_pglobal_lookup (gdb_ps_prochandle_t ph, const char *ld_object_name,
00759                    const char *ld_symbol_name, gdb_ps_addr_t *ld_symbol_addr)
00760 {
00761   struct minimal_symbol *ms;
00762 
00763   ms = lookup_minimal_symbol (ld_symbol_name, NULL, NULL);
00764   if (!ms)
00765     return PS_NOSYM;
00766 
00767   *ld_symbol_addr = SYMBOL_VALUE_ADDRESS (ms);
00768   return PS_OK;
00769 }
00770 
00771 /* Common routine for reading and writing memory.  */
00772 
00773 static ps_err_e
00774 rw_common (int dowrite, const struct ps_prochandle *ph, gdb_ps_addr_t addr,
00775            gdb_byte *buf, int size)
00776 {
00777   int ret;
00778   struct cleanup *old_chain;
00779 
00780   old_chain = save_inferior_ptid ();
00781 
00782   if (ptid_tid_p (inferior_ptid) || !target_thread_alive (inferior_ptid))
00783     {
00784       /* It's either a thread or an LWP that isn't alive.  Any live
00785          LWP will do so use the first available.
00786 
00787          NOTE: We don't need to call switch_to_thread; we're just
00788          reading memory.  */
00789       inferior_ptid = procfs_first_available ();
00790     }
00791 
00792 #if defined (__sparcv9)
00793   /* For Sparc64 cross Sparc32, make sure the address has not been
00794      accidentally sign-extended (or whatever) to beyond 32 bits.  */
00795   if (bfd_get_arch_size (exec_bfd) == 32)
00796     addr &= 0xffffffff;
00797 #endif
00798 
00799   if (dowrite)
00800     ret = target_write_memory (addr, (gdb_byte *) buf, size);
00801   else
00802     ret = target_read_memory (addr, (gdb_byte *) buf, size);
00803 
00804   do_cleanups (old_chain);
00805 
00806   return (ret == 0 ? PS_OK : PS_ERR);
00807 }
00808 
00809 /* Copies SIZE bytes from target process .data segment to debugger memory.  */
00810 
00811 ps_err_e
00812 ps_pdread (gdb_ps_prochandle_t ph, gdb_ps_addr_t addr,
00813            gdb_ps_read_buf_t buf, gdb_ps_size_t size)
00814 {
00815   return rw_common (0, ph, addr, buf, size);
00816 }
00817 
00818 /* Copies SIZE bytes from debugger memory .data segment to target process.  */
00819 
00820 ps_err_e
00821 ps_pdwrite (gdb_ps_prochandle_t ph, gdb_ps_addr_t addr,
00822             gdb_ps_write_buf_t buf, gdb_ps_size_t size)
00823 {
00824   return rw_common (1, ph, addr, (gdb_byte *) buf, size);
00825 }
00826 
00827 /* Copies SIZE bytes from target process .text segment to debugger memory.  */
00828 
00829 ps_err_e
00830 ps_ptread (gdb_ps_prochandle_t ph, gdb_ps_addr_t addr,
00831            gdb_ps_read_buf_t buf, gdb_ps_size_t size)
00832 {
00833   return rw_common (0, ph, addr, buf, size);
00834 }
00835 
00836 /* Copies SIZE bytes from debugger memory .text segment to target process.  */
00837 
00838 ps_err_e
00839 ps_ptwrite (gdb_ps_prochandle_t ph, gdb_ps_addr_t addr,
00840             gdb_ps_write_buf_t buf, gdb_ps_size_t size)
00841 {
00842   return rw_common (1, ph, addr, (gdb_byte *) buf, size);
00843 }
00844 
00845 /* Get general-purpose registers for LWP.  */
00846 
00847 ps_err_e
00848 ps_lgetregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, prgregset_t gregset)
00849 {
00850   struct cleanup *old_chain;
00851   struct regcache *regcache;
00852 
00853   old_chain = save_inferior_ptid ();
00854 
00855   inferior_ptid = ptid_build (ptid_get_pid (inferior_ptid), lwpid, 0);
00856   regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch ());
00857 
00858   target_fetch_registers (regcache, -1);
00859   fill_gregset (regcache, (gdb_gregset_t *) gregset, -1);
00860 
00861   do_cleanups (old_chain);
00862 
00863   return PS_OK;
00864 }
00865 
00866 /* Set general-purpose registers for LWP.  */
00867 
00868 ps_err_e
00869 ps_lsetregs (gdb_ps_prochandle_t ph, lwpid_t lwpid,
00870              const prgregset_t gregset)
00871 {
00872   struct cleanup *old_chain;
00873   struct regcache *regcache;
00874 
00875   old_chain = save_inferior_ptid ();
00876 
00877   inferior_ptid = ptid_build (ptid_get_pid (inferior_ptid), lwpid, 0);
00878   regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch ());
00879 
00880   supply_gregset (regcache, (const gdb_gregset_t *) gregset);
00881   target_store_registers (regcache, -1);
00882 
00883   do_cleanups (old_chain);
00884 
00885   return PS_OK;
00886 }
00887 
00888 /* Log a message (sends to gdb_stderr).  */
00889 
00890 void
00891 ps_plog (const char *fmt, ...)
00892 {
00893   va_list args;
00894 
00895   va_start (args, fmt);
00896 
00897   vfprintf_filtered (gdb_stderr, fmt, args);
00898 }
00899 
00900 /* Get size of extra register set.  Currently a noop.  */
00901 
00902 ps_err_e
00903 ps_lgetxregsize (gdb_ps_prochandle_t ph, lwpid_t lwpid, int *xregsize)
00904 {
00905   return PS_OK;
00906 }
00907 
00908 /* Get extra register set.  Currently a noop.  */
00909 
00910 ps_err_e
00911 ps_lgetxregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, caddr_t xregset)
00912 {
00913   return PS_OK;
00914 }
00915 
00916 /* Set extra register set.  Currently a noop.  */
00917 
00918 ps_err_e
00919 ps_lsetxregs (gdb_ps_prochandle_t ph, lwpid_t lwpid, caddr_t xregset)
00920 {
00921   return PS_OK;
00922 }
00923 
00924 /* Get floating-point registers for LWP.  */
00925 
00926 ps_err_e
00927 ps_lgetfpregs (gdb_ps_prochandle_t ph, lwpid_t lwpid,
00928                prfpregset_t *fpregset)
00929 {
00930   struct cleanup *old_chain;
00931   struct regcache *regcache;
00932 
00933   old_chain = save_inferior_ptid ();
00934 
00935   inferior_ptid = ptid_build (ptid_get_pid (inferior_ptid), lwpid, 0);
00936   regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch ());
00937 
00938   target_fetch_registers (regcache, -1);
00939   fill_fpregset (regcache, (gdb_fpregset_t *) fpregset, -1);
00940 
00941   do_cleanups (old_chain);
00942 
00943   return PS_OK;
00944 }
00945 
00946 /* Set floating-point regs for LWP.  */
00947 
00948 ps_err_e
00949 ps_lsetfpregs (gdb_ps_prochandle_t ph, lwpid_t lwpid,
00950                const prfpregset_t * fpregset)
00951 {
00952   struct cleanup *old_chain;
00953   struct regcache *regcache;
00954 
00955   old_chain = save_inferior_ptid ();
00956 
00957   inferior_ptid = ptid_build (ptid_get_pid (inferior_ptid), lwpid, 0);
00958   regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch ());
00959 
00960   supply_fpregset (regcache, (const gdb_fpregset_t *) fpregset);
00961   target_store_registers (regcache, -1);
00962 
00963   do_cleanups (old_chain);
00964 
00965   return PS_OK;
00966 }
00967 
00968 #ifdef PR_MODEL_LP64
00969 /* Identify process as 32-bit or 64-bit.  At the moment we're using
00970    BFD to do this.  There might be a more Solaris-specific
00971    (e.g. procfs) method, but this ought to work.  */
00972 
00973 ps_err_e
00974 ps_pdmodel (gdb_ps_prochandle_t ph, int *data_model)
00975 {
00976   if (exec_bfd == 0)
00977     *data_model = PR_MODEL_UNKNOWN;
00978   else if (bfd_get_arch_size (exec_bfd) == 32)
00979     *data_model = PR_MODEL_ILP32;
00980   else
00981     *data_model = PR_MODEL_LP64;
00982 
00983   return PS_OK;
00984 }
00985 #endif /* PR_MODEL_LP64 */
00986 
00987 #if (defined(__i386__) || defined(__x86_64__)) && defined (sun)
00988 
00989 /* Reads the local descriptor table of a LWP.
00990 
00991    This function is necessary on x86-solaris only.  Without it, the loading
00992    of libthread_db would fail because of ps_lgetLDT being undefined.  */
00993 
00994 ps_err_e
00995 ps_lgetLDT (gdb_ps_prochandle_t ph, lwpid_t lwpid,
00996             struct ssd *pldt)
00997 {
00998   /* NOTE: only used on Solaris, therefore OK to refer to procfs.c.  */
00999   struct ssd *ret;
01000 
01001   /* FIXME: can't I get the process ID from the prochandle or
01002      something?  */
01003 
01004   if (ptid_get_pid (inferior_ptid) <= 0 || lwpid <= 0)
01005     return PS_BADLID;
01006 
01007   ret = procfs_find_LDT_entry (ptid_build (ptid_get_pid (inferior_ptid),
01008                                lwpid, 0));
01009   if (ret)
01010     {
01011       memcpy (pldt, ret, sizeof (struct ssd));
01012       return PS_OK;
01013     }
01014   else
01015     /* LDT not found.  */
01016     return PS_ERR;
01017 }
01018 #endif
01019 
01020 
01021 /* Convert PTID to printable form.  */
01022 
01023 static char *
01024 solaris_pid_to_str (struct target_ops *ops, ptid_t ptid)
01025 {
01026   static char buf[100];
01027 
01028   if (ptid_tid_p (ptid))
01029     {
01030       ptid_t lwp;
01031 
01032       lwp = thread_to_lwp (ptid, -2);
01033 
01034       if (ptid_get_pid (lwp) == -1)
01035         xsnprintf (buf, sizeof (buf), "Thread %ld (defunct)",
01036                    ptid_get_tid (ptid));
01037       else if (ptid_get_pid (lwp) != -2)
01038         xsnprintf (buf, sizeof (buf), "Thread %ld (LWP %ld)",
01039                  ptid_get_tid (ptid), ptid_get_lwp (lwp));
01040       else
01041         xsnprintf (buf, sizeof (buf), "Thread %ld        ",
01042                    ptid_get_tid (ptid));
01043     }
01044   else if (ptid_get_lwp (ptid) != 0)
01045     xsnprintf (buf, sizeof (buf), "LWP    %ld        ", ptid_get_lwp (ptid));
01046   else
01047     xsnprintf (buf, sizeof (buf), "process %d    ", ptid_get_pid (ptid));
01048 
01049   return buf;
01050 }
01051 
01052 
01053 /* Worker bee for find_new_threads.  Callback function that gets
01054    called once per user-level thread (i.e. not for LWP's).  */
01055 
01056 static int
01057 sol_find_new_threads_callback (const td_thrhandle_t *th, void *ignored)
01058 {
01059   td_err_e retval;
01060   td_thrinfo_t ti;
01061   ptid_t ptid;
01062 
01063   retval = p_td_thr_get_info (th, &ti);
01064   if (retval != TD_OK)
01065     return -1;
01066 
01067   ptid = ptid_build (ptid_get_pid (inferior_ptid), 0, ti.ti_tid);
01068   if (!in_thread_list (ptid) || is_exited (ptid))
01069     add_thread (ptid);
01070 
01071   return 0;
01072 }
01073 
01074 static void
01075 sol_find_new_threads (struct target_ops *ops)
01076 {
01077   struct target_ops *beneath = find_target_beneath (ops);
01078 
01079   /* First Find any new LWP's.  */
01080   if (beneath->to_find_new_threads != NULL)
01081     beneath->to_find_new_threads (beneath);
01082 
01083   /* Then find any new user-level threads.  */
01084   p_td_ta_thr_iter (main_ta, sol_find_new_threads_callback, (void *) 0,
01085                     TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
01086                     TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
01087 }
01088 
01089 /* Worker bee for the "info sol-thread" command.  This is a callback
01090    function that gets called once for each Solaris user-level thread
01091    (i.e. not for LWPs) in the inferior.  Print anything interesting
01092    that we can think of.  */
01093 
01094 static int
01095 info_cb (const td_thrhandle_t *th, void *s)
01096 {
01097   td_err_e ret;
01098   td_thrinfo_t ti;
01099 
01100   ret = p_td_thr_get_info (th, &ti);
01101   if (ret == TD_OK)
01102     {
01103       printf_filtered ("%s thread #%d, lwp %d, ",
01104                        ti.ti_type == TD_THR_SYSTEM ? "system" : "user  ",
01105                        ti.ti_tid, ti.ti_lid);
01106       switch (ti.ti_state)
01107         {
01108         default:
01109         case TD_THR_UNKNOWN:
01110           printf_filtered ("<unknown state>");
01111           break;
01112         case TD_THR_STOPPED:
01113           printf_filtered ("(stopped)");
01114           break;
01115         case TD_THR_RUN:
01116           printf_filtered ("(run)    ");
01117           break;
01118         case TD_THR_ACTIVE:
01119           printf_filtered ("(active) ");
01120           break;
01121         case TD_THR_ZOMBIE:
01122           printf_filtered ("(zombie) ");
01123           break;
01124         case TD_THR_SLEEP:
01125           printf_filtered ("(asleep) ");
01126           break;
01127         case TD_THR_STOPPED_ASLEEP:
01128           printf_filtered ("(stopped asleep)");
01129           break;
01130         }
01131       /* Print thr_create start function.  */
01132       if (ti.ti_startfunc != 0)
01133         {
01134           const struct bound_minimal_symbol msym
01135             = lookup_minimal_symbol_by_pc (ti.ti_startfunc);
01136 
01137           printf_filtered ("   startfunc=%s",
01138                            msym.minsym
01139                            ? SYMBOL_PRINT_NAME (msym.minsym)
01140                            : paddress (target_gdbarch (), ti.ti_startfunc));
01141         }
01142 
01143       /* If thread is asleep, print function that went to sleep.  */
01144       if (ti.ti_state == TD_THR_SLEEP)
01145         {
01146           const struct bound_minimal_symbol msym
01147             = lookup_minimal_symbol_by_pc (ti.ti_pc);
01148 
01149           printf_filtered ("   sleepfunc=%s",
01150                            msym.minsym
01151                            ? SYMBOL_PRINT_NAME (msym.minsym)
01152                            : paddress (target_gdbarch (), ti.ti_pc));
01153         }
01154 
01155       printf_filtered ("\n");
01156     }
01157   else
01158     warning (_("info sol-thread: failed to get info for thread."));
01159 
01160   return 0;
01161 }
01162 
01163 /* List some state about each Solaris user-level thread in the
01164    inferior.  */
01165 
01166 static void
01167 info_solthreads (char *args, int from_tty)
01168 {
01169   p_td_ta_thr_iter (main_ta, info_cb, args,
01170                     TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
01171                     TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
01172 }
01173 
01174 /* Callback routine used to find a thread based on the TID part of
01175    its PTID.  */
01176 
01177 static int
01178 thread_db_find_thread_from_tid (struct thread_info *thread, void *data)
01179 {
01180   long *tid = (long *) data;
01181 
01182   if (ptid_get_tid (thread->ptid) == *tid)
01183     return 1;
01184 
01185   return 0;
01186 }
01187 
01188 static ptid_t
01189 sol_get_ada_task_ptid (long lwp, long thread)
01190 {
01191   struct thread_info *thread_info =
01192     iterate_over_threads (thread_db_find_thread_from_tid, &thread);
01193 
01194   if (thread_info == NULL)
01195     {
01196       /* The list of threads is probably not up to date.  Find any
01197          thread that is missing from the list, and try again.  */
01198       sol_find_new_threads (&current_target);
01199       thread_info = iterate_over_threads (thread_db_find_thread_from_tid,
01200                                           &thread);
01201     }
01202 
01203   gdb_assert (thread_info != NULL);
01204 
01205   return (thread_info->ptid);
01206 }
01207 
01208 static void
01209 init_sol_thread_ops (void)
01210 {
01211   sol_thread_ops.to_shortname = "solaris-threads";
01212   sol_thread_ops.to_longname = "Solaris threads and pthread.";
01213   sol_thread_ops.to_doc = "Solaris threads and pthread support.";
01214   sol_thread_ops.to_detach = sol_thread_detach;
01215   sol_thread_ops.to_resume = sol_thread_resume;
01216   sol_thread_ops.to_wait = sol_thread_wait;
01217   sol_thread_ops.to_fetch_registers = sol_thread_fetch_registers;
01218   sol_thread_ops.to_store_registers = sol_thread_store_registers;
01219   sol_thread_ops.to_xfer_partial = sol_thread_xfer_partial;
01220   sol_thread_ops.to_mourn_inferior = sol_thread_mourn_inferior;
01221   sol_thread_ops.to_thread_alive = sol_thread_alive;
01222   sol_thread_ops.to_pid_to_str = solaris_pid_to_str;
01223   sol_thread_ops.to_find_new_threads = sol_find_new_threads;
01224   sol_thread_ops.to_stratum = thread_stratum;
01225   sol_thread_ops.to_get_ada_task_ptid = sol_get_ada_task_ptid;
01226   sol_thread_ops.to_magic = OPS_MAGIC;
01227 }
01228 
01229 /* Silence -Wmissing-prototypes.  */
01230 extern void _initialize_sol_thread (void);
01231 
01232 void
01233 _initialize_sol_thread (void)
01234 {
01235   void *dlhandle;
01236 
01237   init_sol_thread_ops ();
01238 
01239   dlhandle = dlopen ("libthread_db.so.1", RTLD_NOW);
01240   if (!dlhandle)
01241     goto die;
01242 
01243 #define resolve(X) \
01244   if (!(p_##X = dlsym (dlhandle, #X))) \
01245     goto die;
01246 
01247   resolve (td_log);
01248   resolve (td_ta_new);
01249   resolve (td_ta_delete);
01250   resolve (td_init);
01251   resolve (td_ta_get_ph);
01252   resolve (td_ta_get_nthreads);
01253   resolve (td_ta_tsd_iter);
01254   resolve (td_ta_thr_iter);
01255   resolve (td_thr_validate);
01256   resolve (td_thr_tsd);
01257   resolve (td_thr_get_info);
01258   resolve (td_thr_getfpregs);
01259   resolve (td_thr_getxregsize);
01260   resolve (td_thr_getxregs);
01261   resolve (td_thr_sigsetmask);
01262   resolve (td_thr_setprio);
01263   resolve (td_thr_setsigpending);
01264   resolve (td_thr_setfpregs);
01265   resolve (td_thr_setxregs);
01266   resolve (td_ta_map_id2thr);
01267   resolve (td_ta_map_lwp2thr);
01268   resolve (td_thr_getgregs);
01269   resolve (td_thr_setgregs);
01270 
01271   complete_target_initialization (&sol_thread_ops);
01272 
01273   add_cmd ("sol-threads", class_maintenance, info_solthreads,
01274            _("Show info on Solaris user threads."), &maintenanceinfolist);
01275 
01276   /* Hook into new_objfile notification.  */
01277   observer_attach_new_objfile (sol_thread_new_objfile);
01278   return;
01279 
01280  die:
01281   fprintf_unfiltered (gdb_stderr, "\
01282 [GDB will not be able to debug user-mode threads: %s]\n", dlerror ());
01283 
01284   if (dlhandle)
01285     dlclose (dlhandle);
01286 
01287   return;
01288 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines