GDB (API)
|
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 (¤t_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 }