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