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