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