2002-02-19 Daniel Jacobowitz <drow@mvista.com>
[deliverable/binutils-gdb.git] / gdb / thread-db.c
CommitLineData
fb0e1ba7 1/* libthread_db assisted debugging support, generic parts.
4e052eda 2 Copyright 1999, 2000, 2001 Free Software Foundation, Inc.
fb0e1ba7
MK
3
4 This file is part of GDB.
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21#include "defs.h"
22
23#include "gdb_assert.h"
24#include <dlfcn.h>
25#include "gdb_proc_service.h"
26#include "gdb_thread_db.h"
27
bda9cb72 28#include "bfd.h"
fb0e1ba7
MK
29#include "gdbthread.h"
30#include "inferior.h"
bda9cb72
MK
31#include "symfile.h"
32#include "objfiles.h"
fb0e1ba7 33#include "target.h"
4e052eda 34#include "regcache.h"
fb0e1ba7
MK
35
36#ifndef LIBTHREAD_DB_SO
37#define LIBTHREAD_DB_SO "libthread_db.so.1"
38#endif
39
40/* If we're running on Linux, we must explicitly attach to any new threads. */
41
42/* FIXME: There is certainly some room for improvements:
43 - Cache LWP ids.
44 - Bypass libthread_db when fetching or storing registers for
45 threads bound to a LWP. */
46
47/* This module's target vector. */
48static struct target_ops thread_db_ops;
49
50/* The target vector that we call for things this module can't handle. */
51static struct target_ops *target_beneath;
52
53/* Pointer to the next function on the objfile event chain. */
540af400 54static void (*target_new_objfile_chain) (struct objfile *objfile);
fb0e1ba7
MK
55
56/* Non-zero if we're using this module's target vector. */
57static int using_thread_db;
58
c194fbe1
MK
59/* Non-zero if we have to keep this module's target vector active
60 across re-runs. */
bda9cb72
MK
61static int keep_thread_db;
62
fb0e1ba7
MK
63/* Non-zero if we have determined the signals used by the threads
64 library. */
65static int thread_signals;
66static sigset_t thread_stop_set;
67static sigset_t thread_print_set;
68
69/* Structure that identifies the child process for the
70 <proc_service.h> interface. */
71static struct ps_prochandle proc_handle;
72
73/* Connection to the libthread_db library. */
74static td_thragent_t *thread_agent;
75
76/* Pointers to the libthread_db functions. */
77
78static td_err_e (*td_init_p) (void);
79
80static td_err_e (*td_ta_new_p) (struct ps_prochandle *ps, td_thragent_t **ta);
81static td_err_e (*td_ta_map_id2thr_p) (const td_thragent_t *ta, thread_t pt,
82 td_thrhandle_t *__th);
83static td_err_e (*td_ta_map_lwp2thr_p) (const td_thragent_t *ta, lwpid_t lwpid,
84 td_thrhandle_t *th);
85static td_err_e (*td_ta_thr_iter_p) (const td_thragent_t *ta,
86 td_thr_iter_f *callback,
87 void *cbdata_p, td_thr_state_e state,
88 int ti_pri, sigset_t *ti_sigmask_p,
89 unsigned int ti_user_flags);
90static td_err_e (*td_ta_event_addr_p) (const td_thragent_t *ta,
91 td_event_e event, td_notify_t *ptr);
92static td_err_e (*td_ta_set_event_p) (const td_thragent_t *ta,
93 td_thr_events_t *event);
94static td_err_e (*td_ta_event_getmsg_p) (const td_thragent_t *ta,
95 td_event_msg_t *msg);
96
97static td_err_e (*td_thr_validate_p) (const td_thrhandle_t *th);
98static td_err_e (*td_thr_get_info_p) (const td_thrhandle_t *th,
99 td_thrinfo_t *infop);
100static td_err_e (*td_thr_getfpregs_p) (const td_thrhandle_t *th,
101 gdb_prfpregset_t *regset);
102static td_err_e (*td_thr_getgregs_p) (const td_thrhandle_t *th,
103 prgregset_t gregs);
104static td_err_e (*td_thr_setfpregs_p) (const td_thrhandle_t *th,
105 const gdb_prfpregset_t *fpregs);
106static td_err_e (*td_thr_setgregs_p) (const td_thrhandle_t *th,
107 prgregset_t gregs);
108static td_err_e (*td_thr_event_enable_p) (const td_thrhandle_t *th, int event);
109
110/* Location of the thread creation event breakpoint. The code at this
111 location in the child process will be called by the pthread library
112 whenever a new thread is created. By setting a special breakpoint
113 at this location, GDB can detect when a new thread is created. We
114 obtain this location via the td_ta_event_addr call. */
115static CORE_ADDR td_create_bp_addr;
116
117/* Location of the thread death event breakpoint. */
118static CORE_ADDR td_death_bp_addr;
119
120/* Prototypes for local functions. */
bda9cb72 121static void thread_db_find_new_threads (void);
fb0e1ba7
MK
122\f
123
124/* Building process ids. */
125
ca6724c1
KB
126#define GET_PID(ptid) ptid_get_pid (ptid)
127#define GET_LWP(ptid) ptid_get_lwp (ptid)
128#define GET_THREAD(ptid) ptid_get_tid (ptid)
fb0e1ba7 129
ca6724c1
KB
130#define is_lwp(ptid) (GET_LWP (ptid) != 0)
131#define is_thread(ptid) (GET_THREAD (ptid) != 0)
fb0e1ba7 132
ca6724c1
KB
133#define BUILD_LWP(lwp, pid) ptid_build (pid, lwp, 0)
134#define BUILD_THREAD(tid, pid) ptid_build (pid, 0, tid)
fb0e1ba7
MK
135\f
136
137struct private_thread_info
138{
139 /* Cached LWP id. Must come first, see lin-lwp.c. */
140 lwpid_t lwpid;
141};
fb0e1ba7 142\f
21bf60fe 143
fb0e1ba7
MK
144static char *
145thread_db_err_str (td_err_e err)
146{
147 static char buf[64];
148
149 switch (err)
150 {
151 case TD_OK:
152 return "generic 'call succeeded'";
153 case TD_ERR:
154 return "generic error";
155 case TD_NOTHR:
156 return "no thread to satisfy query";
157 case TD_NOSV:
158 return "no sync handle to satisfy query";
159 case TD_NOLWP:
160 return "no LWP to satisfy query";
161 case TD_BADPH:
162 return "invalid process handle";
163 case TD_BADTH:
164 return "invalid thread handle";
165 case TD_BADSH:
166 return "invalid synchronization handle";
167 case TD_BADTA:
168 return "invalid thread agent";
169 case TD_BADKEY:
170 return "invalid key";
171 case TD_NOMSG:
172 return "no event message for getmsg";
173 case TD_NOFPREGS:
174 return "FPU register set not available";
175 case TD_NOLIBTHREAD:
176 return "application not linked with libthread";
177 case TD_NOEVENT:
178 return "requested event is not supported";
179 case TD_NOCAPAB:
180 return "capability not available";
181 case TD_DBERR:
182 return "debugger service failed";
183 case TD_NOAPLIC:
184 return "operation not applicable to";
185 case TD_NOTSD:
186 return "no thread-specific data for this thread";
187 case TD_MALLOC:
188 return "malloc failed";
189 case TD_PARTIALREG:
190 return "only part of register set was written/read";
191 case TD_NOXREGS:
192 return "X register set not available for this thread";
193 default:
194 snprintf (buf, sizeof (buf), "unknown thread_db error '%d'", err);
195 return buf;
196 }
197}
198
199static char *
200thread_db_state_str (td_thr_state_e state)
201{
202 static char buf[64];
203
204 switch (state)
205 {
206 case TD_THR_STOPPED:
207 return "stopped by debugger";
208 case TD_THR_RUN:
209 return "runnable";
210 case TD_THR_ACTIVE:
211 return "active";
212 case TD_THR_ZOMBIE:
213 return "zombie";
214 case TD_THR_SLEEP:
215 return "sleeping";
216 case TD_THR_STOPPED_ASLEEP:
217 return "stopped by debugger AND blocked";
218 default:
219 snprintf (buf, sizeof (buf), "unknown thread_db state %d", state);
220 return buf;
221 }
222}
223\f
224
225/* Convert between user-level thread ids and LWP ids. */
226
39f77062
KB
227static ptid_t
228thread_from_lwp (ptid_t ptid)
fb0e1ba7
MK
229{
230 td_thrinfo_t ti;
231 td_thrhandle_t th;
232 td_err_e err;
233
39f77062
KB
234 if (GET_LWP (ptid) == 0)
235 ptid = BUILD_LWP (GET_PID (ptid), GET_PID (ptid));
fb0e1ba7 236
39f77062 237 gdb_assert (is_lwp (ptid));
fb0e1ba7 238
39f77062 239 err = td_ta_map_lwp2thr_p (thread_agent, GET_LWP (ptid), &th);
fb0e1ba7
MK
240 if (err != TD_OK)
241 error ("Cannot find user-level thread for LWP %d: %s",
39f77062 242 GET_LWP (ptid), thread_db_err_str (err));
fb0e1ba7
MK
243
244 err = td_thr_get_info_p (&th, &ti);
245 if (err != TD_OK)
246 error ("Cannot get thread info: %s", thread_db_err_str (err));
247
39f77062 248 return BUILD_THREAD (ti.ti_tid, GET_PID (ptid));
fb0e1ba7
MK
249}
250
39f77062
KB
251static ptid_t
252lwp_from_thread (ptid_t ptid)
fb0e1ba7
MK
253{
254 td_thrinfo_t ti;
255 td_thrhandle_t th;
256 td_err_e err;
257
21bf60fe 258 if (!is_thread (ptid))
39f77062 259 return ptid;
fb0e1ba7 260
39f77062 261 err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (ptid), &th);
fb0e1ba7
MK
262 if (err != TD_OK)
263 error ("Cannot find thread %ld: %s",
39f77062 264 (long) GET_THREAD (ptid), thread_db_err_str (err));
fb0e1ba7
MK
265
266 err = td_thr_get_info_p (&th, &ti);
267 if (err != TD_OK)
268 error ("Cannot get thread info: %s", thread_db_err_str (err));
269
39f77062 270 return BUILD_LWP (ti.ti_lid, GET_PID (ptid));
fb0e1ba7
MK
271}
272\f
273
274void
275thread_db_init (struct target_ops *target)
276{
277 target_beneath = target;
278}
279
280static int
281thread_db_load (void)
282{
283 void *handle;
284 td_err_e err;
285
286 handle = dlopen (LIBTHREAD_DB_SO, RTLD_NOW);
287 if (handle == NULL)
288 return 0;
289
290 /* Initialize pointers to the dynamic library functions we will use.
291 Essential functions first. */
292
293 td_init_p = dlsym (handle, "td_init");
294 if (td_init_p == NULL)
295 return 0;
296
297 td_ta_new_p = dlsym (handle, "td_ta_new");
298 if (td_ta_new_p == NULL)
299 return 0;
300
301 td_ta_map_id2thr_p = dlsym (handle, "td_ta_map_id2thr");
302 if (td_ta_map_id2thr_p == NULL)
303 return 0;
304
305 td_ta_map_lwp2thr_p = dlsym (handle, "td_ta_map_lwp2thr");
306 if (td_ta_map_lwp2thr_p == NULL)
307 return 0;
308
309 td_ta_thr_iter_p = dlsym (handle, "td_ta_thr_iter");
310 if (td_ta_thr_iter_p == NULL)
311 return 0;
312
313 td_thr_validate_p = dlsym (handle, "td_thr_validate");
314 if (td_thr_validate_p == NULL)
315 return 0;
316
317 td_thr_get_info_p = dlsym (handle, "td_thr_get_info");
318 if (td_thr_get_info_p == NULL)
319 return 0;
320
321 td_thr_getfpregs_p = dlsym (handle, "td_thr_getfpregs");
322 if (td_thr_getfpregs_p == NULL)
323 return 0;
324
325 td_thr_getgregs_p = dlsym (handle, "td_thr_getgregs");
326 if (td_thr_getgregs_p == NULL)
327 return 0;
328
329 td_thr_setfpregs_p = dlsym (handle, "td_thr_setfpregs");
330 if (td_thr_setfpregs_p == NULL)
331 return 0;
332
333 td_thr_setgregs_p = dlsym (handle, "td_thr_setgregs");
334 if (td_thr_setgregs_p == NULL)
335 return 0;
336
337 /* Initialize the library. */
338 err = td_init_p ();
339 if (err != TD_OK)
340 {
341 warning ("Cannot initialize libthread_db: %s", thread_db_err_str (err));
342 return 0;
343 }
344
345 /* These are not essential. */
346 td_ta_event_addr_p = dlsym (handle, "td_ta_event_addr");
347 td_ta_set_event_p = dlsym (handle, "td_ta_set_event");
348 td_ta_event_getmsg_p = dlsym (handle, "td_ta_event_getmsg");
349 td_thr_event_enable_p = dlsym (handle, "td_thr_event_enable");
350
351 return 1;
352}
353
354static void
355enable_thread_event_reporting (void)
356{
357 td_thr_events_t events;
358 td_notify_t notify;
359 td_err_e err;
360
361 /* We cannot use the thread event reporting facility if these
362 functions aren't available. */
363 if (td_ta_event_addr_p == NULL || td_ta_set_event_p == NULL
364 || td_ta_event_getmsg_p == NULL || td_thr_event_enable_p == NULL)
365 return;
366
367 /* Set the process wide mask saying which events we're interested in. */
368 td_event_emptyset (&events);
369 td_event_addset (&events, TD_CREATE);
370#if 0
371 /* FIXME: kettenis/2000-04-23: The event reporting facility is
372 broken for TD_DEATH events in glibc 2.1.3, so don't enable it for
373 now. */
374 td_event_addset (&events, TD_DEATH);
375#endif
376
377 err = td_ta_set_event_p (thread_agent, &events);
378 if (err != TD_OK)
379 {
380 warning ("Unable to set global thread event mask: %s",
381 thread_db_err_str (err));
382 return;
383 }
384
385 /* Delete previous thread event breakpoints, if any. */
386 remove_thread_event_breakpoints ();
387
388 /* Get address for thread creation breakpoint. */
389 err = td_ta_event_addr_p (thread_agent, TD_CREATE, &notify);
390 if (err != TD_OK)
391 {
392 warning ("Unable to get location for thread creation breakpoint: %s",
393 thread_db_err_str (err));
394 return;
395 }
396
397 /* Set up the breakpoint. */
398 td_create_bp_addr = (CORE_ADDR) notify.u.bptaddr;
399 create_thread_event_breakpoint (td_create_bp_addr);
400
401 /* Get address for thread death breakpoint. */
402 err = td_ta_event_addr_p (thread_agent, TD_DEATH, &notify);
403 if (err != TD_OK)
404 {
936742ab 405 warning ("Unable to get location for thread death breakpoint: %s",
fb0e1ba7
MK
406 thread_db_err_str (err));
407 return;
408 }
409
410 /* Set up the breakpoint. */
411 td_death_bp_addr = (CORE_ADDR) notify.u.bptaddr;
412 create_thread_event_breakpoint (td_death_bp_addr);
413}
414
415static void
416disable_thread_event_reporting (void)
417{
418 td_thr_events_t events;
419
420 /* Set the process wide mask saying we aren't interested in any
421 events anymore. */
422 td_event_emptyset (&events);
423 td_ta_set_event_p (thread_agent, &events);
424
425 /* Delete thread event breakpoints, if any. */
426 remove_thread_event_breakpoints ();
427 td_create_bp_addr = 0;
428 td_death_bp_addr = 0;
429}
430
431static void
432check_thread_signals (void)
433{
434#ifdef GET_THREAD_SIGNALS
21bf60fe 435 if (!thread_signals)
fb0e1ba7
MK
436 {
437 sigset_t mask;
438 int i;
439
440 GET_THREAD_SIGNALS (&mask);
441 sigemptyset (&thread_stop_set);
442 sigemptyset (&thread_print_set);
443
b9569773 444 for (i = 1; i < NSIG; i++)
fb0e1ba7
MK
445 {
446 if (sigismember (&mask, i))
447 {
448 if (signal_stop_update (target_signal_from_host (i), 0))
449 sigaddset (&thread_stop_set, i);
450 if (signal_print_update (target_signal_from_host (i), 0))
451 sigaddset (&thread_print_set, i);
452 thread_signals = 1;
453 }
454 }
455 }
456#endif
457}
458
459static void
460disable_thread_signals (void)
461{
462#ifdef GET_THREAD_SIGNALS
463 if (thread_signals)
464 {
465 int i;
466
b9569773 467 for (i = 1; i < NSIG; i++)
fb0e1ba7
MK
468 {
469 if (sigismember (&thread_stop_set, i))
470 signal_stop_update (target_signal_from_host (i), 1);
471 if (sigismember (&thread_print_set, i))
472 signal_print_update (target_signal_from_host (i), 1);
473 }
474
475 thread_signals = 0;
476 }
477#endif
478}
479
fb0e1ba7
MK
480static void
481thread_db_new_objfile (struct objfile *objfile)
482{
483 td_err_e err;
484
5bbd998e
MS
485 /* Don't attempt to use thread_db on targets which can not run
486 (core files). */
487 if (objfile == NULL || !target_has_execution)
bda9cb72
MK
488 {
489 /* All symbols have been discarded. If the thread_db target is
c194fbe1 490 active, deactivate it now. */
bda9cb72 491 if (using_thread_db)
c194fbe1
MK
492 {
493 gdb_assert (proc_handle.pid == 0);
494 unpush_target (&thread_db_ops);
495 using_thread_db = 0;
496 }
497
498 keep_thread_db = 0;
bda9cb72
MK
499
500 goto quit;
501 }
502
fb0e1ba7
MK
503 if (using_thread_db)
504 /* Nothing to do. The thread library was already detected and the
505 target vector was already activated. */
506 goto quit;
507
bda9cb72
MK
508 /* Initialize the structure that identifies the child process. Note
509 that at this point there is no guarantee that we actually have a
510 child process. */
39f77062 511 proc_handle.pid = GET_PID (inferior_ptid);
fb0e1ba7 512
bda9cb72 513 /* Now attempt to open a connection to the thread library. */
fb0e1ba7
MK
514 err = td_ta_new_p (&proc_handle, &thread_agent);
515 switch (err)
516 {
517 case TD_NOLIBTHREAD:
bda9cb72 518 /* No thread library was detected. */
fb0e1ba7
MK
519 break;
520
521 case TD_OK:
bda9cb72
MK
522 /* The thread library was detected. Activate the thread_db target. */
523 push_target (&thread_db_ops);
524 using_thread_db = 1;
525
526 /* If the thread library was detected in the main symbol file
527 itself, we assume that the program was statically linked
528 against the thread library and well have to keep this
529 module's target vector activated until forever... Well, at
530 least until all symbols have been discarded anyway (see
531 above). */
532 if (objfile == symfile_objfile)
533 {
534 gdb_assert (proc_handle.pid == 0);
535 keep_thread_db = 1;
536 }
537
538 /* We can only poke around if there actually is a child process.
539 If there is no child process alive, postpone the steps below
540 until one has been created. */
541 if (proc_handle.pid != 0)
542 {
543 enable_thread_event_reporting ();
544 thread_db_find_new_threads ();
545 }
fb0e1ba7
MK
546 break;
547
548 default:
549 warning ("Cannot initialize thread debugging library: %s",
550 thread_db_err_str (err));
551 break;
552 }
553
554 quit:
540af400
MS
555 if (target_new_objfile_chain)
556 target_new_objfile_chain (objfile);
fb0e1ba7
MK
557}
558
559static void
39f77062 560attach_thread (ptid_t ptid, const td_thrhandle_t *th_p,
fb0e1ba7
MK
561 const td_thrinfo_t *ti_p, int verbose)
562{
563 struct thread_info *tp;
564 td_err_e err;
565
566 check_thread_signals ();
567
568 if (verbose)
39f77062 569 printf_unfiltered ("[New %s]\n", target_pid_to_str (ptid));
fb0e1ba7
MK
570
571 /* Add the thread to GDB's thread list. */
39f77062 572 tp = add_thread (ptid);
fb0e1ba7
MK
573 tp->private = xmalloc (sizeof (struct private_thread_info));
574 tp->private->lwpid = ti_p->ti_lid;
575
21bf60fe
MK
576 if (ti_p->ti_state == TD_THR_UNKNOWN || ti_p->ti_state == TD_THR_ZOMBIE)
577 return; /* A zombie thread -- do not attach. */
5fd913cc 578
fb0e1ba7
MK
579 /* Under Linux, we have to attach to each and every thread. */
580#ifdef ATTACH_LWP
c194fbe1 581 ATTACH_LWP (BUILD_LWP (ti_p->ti_lid, GET_PID (ptid)), 0);
fb0e1ba7
MK
582#endif
583
584 /* Enable thread event reporting for this thread. */
585 err = td_thr_event_enable_p (th_p, 1);
586 if (err != TD_OK)
587 error ("Cannot enable thread event reporting for %s: %s",
39f77062 588 target_pid_to_str (ptid), thread_db_err_str (err));
fb0e1ba7
MK
589}
590
c194fbe1
MK
591static void
592thread_db_attach (char *args, int from_tty)
593{
594 target_beneath->to_attach (args, from_tty);
595
596 /* Destroy thread info; it's no longer valid. */
597 init_thread_list ();
598
599 /* The child process is now the actual multi-threaded
600 program. Snatch its process ID... */
601 proc_handle.pid = GET_PID (inferior_ptid);
602
603 /* ...and perform the remaining initialization steps. */
604 enable_thread_event_reporting ();
605 thread_db_find_new_threads();
606}
607
fb0e1ba7 608static void
39f77062 609detach_thread (ptid_t ptid, int verbose)
fb0e1ba7
MK
610{
611 if (verbose)
39f77062 612 printf_unfiltered ("[%s exited]\n", target_pid_to_str (ptid));
fb0e1ba7
MK
613}
614
615static void
616thread_db_detach (char *args, int from_tty)
617{
618 disable_thread_event_reporting ();
c194fbe1
MK
619
620 /* There's no need to save & restore inferior_ptid here, since the
621 inferior is supposed to be survive this function call. */
622 inferior_ptid = lwp_from_thread (inferior_ptid);
623
624 /* Forget about the child's process ID. We shouldn't need it
625 anymore. */
626 proc_handle.pid = 0;
fb0e1ba7
MK
627
628 target_beneath->to_detach (args, from_tty);
629}
630
631static void
39f77062 632thread_db_resume (ptid_t ptid, int step, enum target_signal signo)
fb0e1ba7 633{
39f77062 634 struct cleanup *old_chain = save_inferior_ptid ();
fb0e1ba7 635
39f77062
KB
636 if (GET_PID (ptid) == -1)
637 inferior_ptid = lwp_from_thread (inferior_ptid);
638 else if (is_thread (ptid))
639 ptid = lwp_from_thread (ptid);
fb0e1ba7 640
39f77062 641 target_beneath->to_resume (ptid, step, signo);
fb0e1ba7
MK
642
643 do_cleanups (old_chain);
644}
645
646/* Check if PID is currently stopped at the location of a thread event
647 breakpoint location. If it is, read the event message and act upon
648 the event. */
649
650static void
39f77062 651check_event (ptid_t ptid)
fb0e1ba7
MK
652{
653 td_event_msg_t msg;
654 td_thrinfo_t ti;
655 td_err_e err;
656 CORE_ADDR stop_pc;
657
658 /* Bail out early if we're not at a thread event breakpoint. */
39f77062 659 stop_pc = read_pc_pid (ptid) - DECR_PC_AFTER_BREAK;
fb0e1ba7
MK
660 if (stop_pc != td_create_bp_addr && stop_pc != td_death_bp_addr)
661 return;
662
663 err = td_ta_event_getmsg_p (thread_agent, &msg);
664 if (err != TD_OK)
665 {
666 if (err == TD_NOMSG)
667 return;
668
669 error ("Cannot get thread event message: %s", thread_db_err_str (err));
670 }
671
672 err = td_thr_get_info_p (msg.th_p, &ti);
673 if (err != TD_OK)
674 error ("Cannot get thread info: %s", thread_db_err_str (err));
675
39f77062 676 ptid = BUILD_THREAD (ti.ti_tid, GET_PID (ptid));
fb0e1ba7
MK
677
678 switch (msg.event)
679 {
680 case TD_CREATE:
681#if 0
682 /* FIXME: kettenis/2000-08-26: Since we use td_ta_event_getmsg,
683 there is no guarantee that the breakpoint will match the
684 event. Should we use td_thr_event_getmsg instead? */
685
686 if (stop_pc != td_create_bp_addr)
687 error ("Thread creation event doesn't match breakpoint.");
688#endif
689
540af400
MS
690 /* We may already know about this thread, for instance when the
691 user has issued the `info threads' command before the SIGTRAP
692 for hitting the thread creation breakpoint was reported. */
21bf60fe 693 if (!in_thread_list (ptid))
39f77062 694 attach_thread (ptid, msg.th_p, &ti, 1);
fb0e1ba7
MK
695 return;
696
697 case TD_DEATH:
698#if 0
699 /* FIXME: See TD_CREATE. */
700
701 if (stop_pc != td_death_bp_addr)
702 error ("Thread death event doesn't match breakpoint.");
703#endif
704
21bf60fe 705 if (!in_thread_list (ptid))
fb0e1ba7
MK
706 error ("Spurious thread death event.");
707
39f77062 708 detach_thread (ptid, 1);
fb0e1ba7
MK
709 return;
710
711 default:
712 error ("Spurious thread event.");
713 }
714}
715
39f77062
KB
716static ptid_t
717thread_db_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
fb0e1ba7 718{
39f77062 719 extern ptid_t trap_ptid;
fb0e1ba7 720
39f77062
KB
721 if (GET_PID (ptid) != -1 && is_thread (ptid))
722 ptid = lwp_from_thread (ptid);
fb0e1ba7 723
39f77062 724 ptid = target_beneath->to_wait (ptid, ourstatus);
fb0e1ba7 725
bda9cb72
MK
726 if (proc_handle.pid == 0)
727 /* The current child process isn't the actual multi-threaded
728 program yet, so don't try to do any special thread-specific
729 post-processing and bail out early. */
39f77062 730 return ptid;
bda9cb72 731
fb0e1ba7 732 if (ourstatus->kind == TARGET_WAITKIND_EXITED)
39f77062 733 return pid_to_ptid (-1);
fb0e1ba7
MK
734
735 if (ourstatus->kind == TARGET_WAITKIND_STOPPED
736 && ourstatus->value.sig == TARGET_SIGNAL_TRAP)
737 /* Check for a thread event. */
39f77062 738 check_event (ptid);
fb0e1ba7 739
39f77062
KB
740 if (!ptid_equal (trap_ptid, null_ptid))
741 trap_ptid = thread_from_lwp (trap_ptid);
fb0e1ba7 742
39f77062 743 return thread_from_lwp (ptid);
fb0e1ba7
MK
744}
745
746static int
747thread_db_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int write,
e5da8f38 748 struct mem_attrib *attrib,
fb0e1ba7
MK
749 struct target_ops *target)
750{
39f77062 751 struct cleanup *old_chain = save_inferior_ptid ();
fb0e1ba7
MK
752 int xfer;
753
39f77062 754 if (is_thread (inferior_ptid))
fb0e1ba7
MK
755 {
756 /* FIXME: This seems to be necessary to make sure breakpoints
757 are removed. */
21bf60fe 758 if (!target_thread_alive (inferior_ptid))
39f77062 759 inferior_ptid = pid_to_ptid (GET_PID (inferior_ptid));
fb0e1ba7 760 else
39f77062 761 inferior_ptid = lwp_from_thread (inferior_ptid);
fb0e1ba7
MK
762 }
763
e5da8f38 764 xfer = target_beneath->to_xfer_memory (memaddr, myaddr, len, write, attrib, target);
fb0e1ba7
MK
765
766 do_cleanups (old_chain);
767 return xfer;
768}
769
770static void
771thread_db_fetch_registers (int regno)
772{
773 td_thrhandle_t th;
774 prgregset_t gregset;
775 gdb_prfpregset_t fpregset;
776 td_err_e err;
777
21bf60fe 778 if (!is_thread (inferior_ptid))
fb0e1ba7
MK
779 {
780 /* Pass the request to the target beneath us. */
781 target_beneath->to_fetch_registers (regno);
782 return;
783 }
784
39f77062 785 err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (inferior_ptid), &th);
fb0e1ba7
MK
786 if (err != TD_OK)
787 error ("Cannot find thread %ld: %s",
39f77062 788 (long) GET_THREAD (inferior_ptid), thread_db_err_str (err));
fb0e1ba7
MK
789
790 err = td_thr_getgregs_p (&th, gregset);
791 if (err != TD_OK)
792 error ("Cannot fetch general-purpose registers for thread %ld: %s",
39f77062 793 (long) GET_THREAD (inferior_ptid), thread_db_err_str (err));
fb0e1ba7
MK
794
795 err = td_thr_getfpregs_p (&th, &fpregset);
796 if (err != TD_OK)
797 error ("Cannot get floating-point registers for thread %ld: %s",
39f77062 798 (long) GET_THREAD (inferior_ptid), thread_db_err_str (err));
fb0e1ba7
MK
799
800 /* Note that we must call supply_gregset after calling the thread_db
801 routines because the thread_db routines call ps_lgetgregs and
802 friends which clobber GDB's register cache. */
803 supply_gregset ((gdb_gregset_t *) gregset);
804 supply_fpregset (&fpregset);
805}
806
807static void
808thread_db_store_registers (int regno)
809{
810 td_thrhandle_t th;
811 prgregset_t gregset;
812 gdb_prfpregset_t fpregset;
813 td_err_e err;
814
21bf60fe 815 if (!is_thread (inferior_ptid))
fb0e1ba7
MK
816 {
817 /* Pass the request to the target beneath us. */
818 target_beneath->to_store_registers (regno);
819 return;
820 }
821
39f77062 822 err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (inferior_ptid), &th);
fb0e1ba7
MK
823 if (err != TD_OK)
824 error ("Cannot find thread %ld: %s",
39f77062 825 (long) GET_THREAD (inferior_ptid), thread_db_err_str (err));
fb0e1ba7
MK
826
827 if (regno != -1)
828 {
829 char raw[MAX_REGISTER_RAW_SIZE];
830
831 read_register_gen (regno, raw);
832 thread_db_fetch_registers (-1);
833 supply_register (regno, raw);
834 }
835
836 fill_gregset ((gdb_gregset_t *) gregset, -1);
837 fill_fpregset (&fpregset, -1);
838
839 err = td_thr_setgregs_p (&th, gregset);
840 if (err != TD_OK)
841 error ("Cannot store general-purpose registers for thread %ld: %s",
39f77062 842 (long) GET_THREAD (inferior_ptid), thread_db_err_str (err));
fb0e1ba7
MK
843 err = td_thr_setfpregs_p (&th, &fpregset);
844 if (err != TD_OK)
845 error ("Cannot store floating-point registers for thread %ld: %s",
39f77062 846 (long) GET_THREAD (inferior_ptid), thread_db_err_str (err));
fb0e1ba7
MK
847}
848
849static void
850thread_db_kill (void)
851{
c194fbe1
MK
852 /* There's no need to save & restore inferior_ptid here, since the
853 inferior isn't supposed to survive this function call. */
854 inferior_ptid = lwp_from_thread (inferior_ptid);
fb0e1ba7
MK
855 target_beneath->to_kill ();
856}
857
858static void
859thread_db_create_inferior (char *exec_file, char *allargs, char **env)
860{
21bf60fe 861 if (!keep_thread_db)
c194fbe1
MK
862 {
863 unpush_target (&thread_db_ops);
864 using_thread_db = 0;
865 }
866
bda9cb72
MK
867 target_beneath->to_create_inferior (exec_file, allargs, env);
868}
fb0e1ba7 869
bda9cb72 870static void
39f77062 871thread_db_post_startup_inferior (ptid_t ptid)
bda9cb72
MK
872{
873 if (proc_handle.pid == 0)
874 {
875 /* The child process is now the actual multi-threaded
876 program. Snatch its process ID... */
39f77062 877 proc_handle.pid = GET_PID (ptid);
fb0e1ba7 878
bda9cb72
MK
879 /* ...and perform the remaining initialization steps. */
880 enable_thread_event_reporting ();
21bf60fe 881 thread_db_find_new_threads ();
bda9cb72 882 }
fb0e1ba7
MK
883}
884
885static void
886thread_db_mourn_inferior (void)
887{
888 remove_thread_event_breakpoints ();
c194fbe1
MK
889
890 /* Forget about the child's process ID. We shouldn't need it
891 anymore. */
892 proc_handle.pid = 0;
fb0e1ba7
MK
893
894 target_beneath->to_mourn_inferior ();
895}
896
897static int
39f77062 898thread_db_thread_alive (ptid_t ptid)
fb0e1ba7 899{
5fd913cc 900 td_thrhandle_t th;
21bf60fe
MK
901 td_thrinfo_t ti;
902 td_err_e err;
5fd913cc 903
39f77062 904 if (is_thread (ptid))
fb0e1ba7 905 {
39f77062 906 err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (ptid), &th);
fb0e1ba7
MK
907 if (err != TD_OK)
908 return 0;
909
910 err = td_thr_validate_p (&th);
911 if (err != TD_OK)
912 return 0;
913
5fd913cc
MS
914 err = td_thr_get_info_p (&th, &ti);
915 if (err != TD_OK)
916 return 0;
917
21bf60fe
MK
918 if (ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE)
919 return 0; /* A zombie thread. */
5fd913cc 920
fb0e1ba7
MK
921 return 1;
922 }
923
924 if (target_beneath->to_thread_alive)
39f77062 925 return target_beneath->to_thread_alive (ptid);
fb0e1ba7
MK
926
927 return 0;
928}
929
930static int
931find_new_threads_callback (const td_thrhandle_t *th_p, void *data)
932{
933 td_thrinfo_t ti;
934 td_err_e err;
39f77062 935 ptid_t ptid;
fb0e1ba7
MK
936
937 err = td_thr_get_info_p (th_p, &ti);
938 if (err != TD_OK)
939 error ("Cannot get thread info: %s", thread_db_err_str (err));
940
21bf60fe
MK
941 if (ti.ti_state == TD_THR_UNKNOWN || ti.ti_state == TD_THR_ZOMBIE)
942 return 0; /* A zombie -- ignore. */
5fd913cc 943
39f77062 944 ptid = BUILD_THREAD (ti.ti_tid, GET_PID (inferior_ptid));
fb0e1ba7 945
21bf60fe 946 if (!in_thread_list (ptid))
39f77062 947 attach_thread (ptid, th_p, &ti, 1);
fb0e1ba7
MK
948
949 return 0;
950}
951
952static void
953thread_db_find_new_threads (void)
954{
955 td_err_e err;
956
957 /* Iterate over all user-space threads to discover new threads. */
958 err = td_ta_thr_iter_p (thread_agent, find_new_threads_callback, NULL,
959 TD_THR_ANY_STATE, TD_THR_LOWEST_PRIORITY,
960 TD_SIGNO_MASK, TD_THR_ANY_USER_FLAGS);
961 if (err != TD_OK)
962 error ("Cannot find new threads: %s", thread_db_err_str (err));
963}
964
965static char *
39f77062 966thread_db_pid_to_str (ptid_t ptid)
fb0e1ba7 967{
39f77062 968 if (is_thread (ptid))
fb0e1ba7
MK
969 {
970 static char buf[64];
971 td_thrhandle_t th;
972 td_thrinfo_t ti;
973 td_err_e err;
974
39f77062 975 err = td_ta_map_id2thr_p (thread_agent, GET_THREAD (ptid), &th);
fb0e1ba7
MK
976 if (err != TD_OK)
977 error ("Cannot find thread %ld: %s",
39f77062 978 (long) GET_THREAD (ptid), thread_db_err_str (err));
fb0e1ba7
MK
979
980 err = td_thr_get_info_p (&th, &ti);
981 if (err != TD_OK)
982 error ("Cannot get thread info for thread %ld: %s",
39f77062 983 (long) GET_THREAD (ptid), thread_db_err_str (err));
fb0e1ba7
MK
984
985 if (ti.ti_state == TD_THR_ACTIVE && ti.ti_lid != 0)
986 {
987 snprintf (buf, sizeof (buf), "Thread %ld (LWP %d)",
988 (long) ti.ti_tid, ti.ti_lid);
989 }
990 else
991 {
992 snprintf (buf, sizeof (buf), "Thread %ld (%s)",
993 (long) ti.ti_tid, thread_db_state_str (ti.ti_state));
994 }
995
996 return buf;
997 }
998
39f77062
KB
999 if (target_beneath->to_pid_to_str (ptid))
1000 return target_beneath->to_pid_to_str (ptid);
fb0e1ba7 1001
39f77062 1002 return normal_pid_to_str (ptid);
fb0e1ba7
MK
1003}
1004
1005static void
1006init_thread_db_ops (void)
1007{
1008 thread_db_ops.to_shortname = "multi-thread";
1009 thread_db_ops.to_longname = "multi-threaded child process.";
1010 thread_db_ops.to_doc = "Threads and pthreads support.";
c194fbe1 1011 thread_db_ops.to_attach = thread_db_attach;
fb0e1ba7
MK
1012 thread_db_ops.to_detach = thread_db_detach;
1013 thread_db_ops.to_resume = thread_db_resume;
1014 thread_db_ops.to_wait = thread_db_wait;
1015 thread_db_ops.to_fetch_registers = thread_db_fetch_registers;
1016 thread_db_ops.to_store_registers = thread_db_store_registers;
1017 thread_db_ops.to_xfer_memory = thread_db_xfer_memory;
1018 thread_db_ops.to_kill = thread_db_kill;
1019 thread_db_ops.to_create_inferior = thread_db_create_inferior;
bda9cb72 1020 thread_db_ops.to_post_startup_inferior = thread_db_post_startup_inferior;
fb0e1ba7
MK
1021 thread_db_ops.to_mourn_inferior = thread_db_mourn_inferior;
1022 thread_db_ops.to_thread_alive = thread_db_thread_alive;
1023 thread_db_ops.to_find_new_threads = thread_db_find_new_threads;
1024 thread_db_ops.to_pid_to_str = thread_db_pid_to_str;
1025 thread_db_ops.to_stratum = thread_stratum;
1026 thread_db_ops.to_has_thread_control = tc_schedlock;
1027 thread_db_ops.to_magic = OPS_MAGIC;
1028}
1029
1030void
1031_initialize_thread_db (void)
1032{
1033 /* Only initialize the module if we can load libthread_db. */
1034 if (thread_db_load ())
1035 {
1036 init_thread_db_ops ();
1037 add_target (&thread_db_ops);
1038
1039 /* Add ourselves to objfile event chain. */
540af400 1040 target_new_objfile_chain = target_new_objfile_hook;
fb0e1ba7
MK
1041 target_new_objfile_hook = thread_db_new_objfile;
1042 }
1043}
This page took 0.176425 seconds and 4 git commands to generate.