gdb/
[deliverable/binutils-gdb.git] / gdb / dec-thread.c
CommitLineData
4c38e0a4 1/* Copyright (C) 2008, 2009, 2010 Free Software Foundation, Inc.
7a052092
JB
2
3 This file is part of GDB.
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>. */
17
18#include "defs.h"
19#include "command.h"
20#include "gdbcmd.h"
21#include "target.h"
22#include "observer.h"
23#include <sys/procfs.h>
24#include "gregset.h"
25#include "regcache.h"
26#include "inferior.h"
27#include "gdbthread.h"
28
29#include <pthread_debug.h>
30
31/* Print debugging traces if set to non-zero. */
32static int debug_dec_thread = 0;
33
34/* Non-zero if the dec-thread layer is active. */
35static int dec_thread_active = 0;
36
37/* The pthread_debug context. */
38pthreadDebugContext_t debug_context;
39
40/* The dec-thread target_ops structure. */
41static struct target_ops dec_thread_ops;
42
7a052092
JB
43/* Print a debug trace if DEBUG_DEC_THREAD is set (its value is adjusted
44 by the user using "set debug dec-thread ..."). */
45
46static void
47debug (char *format, ...)
48{
49 if (debug_dec_thread)
50 {
51 va_list args;
52
53 va_start (args, format);
54 printf_unfiltered ("DEC Threads: ");
55 vprintf_unfiltered (format, args);
56 printf_unfiltered ("\n");
57 va_end (args);
58 }
59}
60
61/* pthread debug callbacks. */
62
63static int
64suspend_clbk (void *caller_context)
65{
66 return ESUCCESS;
67}
68
69static int
70resume_clbk (void *caller_context)
71{
72 return ESUCCESS;
73}
74
75static int
76hold_clbk (void *caller_context, pthreadDebugKId_t kernel_tid)
77{
78 return ESUCCESS;
79}
80
81static int
82unhold_clbk (void *caller_context, pthreadDebugKId_t kernel_tid)
83{
84 return ESUCCESS;
85}
86
87static int
88read_clbk (void *caller_context, void *address, void *buffer,
89 unsigned long size)
90{
91 int status = target_read_memory ((CORE_ADDR) address, buffer, size);
92
93 if (status != 0)
94 return EINVAL;
95
96 return ESUCCESS;
97}
98
99static int
100write_clbk (void *caller_context, void *address, void *buffer,
101 unsigned long size)
102{
103 int status = target_write_memory ((CORE_ADDR) address, buffer, size);
104
105 if (status != 0)
106 return EINVAL;
107
108 return ESUCCESS;
109}
110
111/* Get integer regs */
112
113static int
114get_reg_clbk(void *caller_context, pthreadDebugGetRegRtn_t regs,
115 pthreadDebugKId_t kernel_tid)
116{
117 debug ("get_reg_clbk");
118
119 /* Not sure that we actually need to do anything in this callback. */
120 return ESUCCESS;
121}
122
123/* Set integer regs */
124
125static int
126set_reg_clbk(void *caller_context, const pthreadDebugRegs_t *regs,
127 pthreadDebugKId_t kernel_tid)
128{
129 debug ("set_reg_clbk");
130
131 /* Not sure that we actually need to do anything in this callback. */
132 return ESUCCESS;
133}
134
135static int
136output_clbk (void *caller_context, char *line)
137{
138 printf_filtered ("%s\n", line);
139 return ESUCCESS;
140}
141
142static int
143error_clbk (void *caller_context, char *line)
144{
145 fprintf_filtered (gdb_stderr, "%s\n", line);
146 return ESUCCESS;
147}
148
149/* Get floating-point regs. */
150
151static int
152get_fpreg_clbk (void *caller_context, pthreadDebugFregs_p fregs,
153 pthreadDebugKId_t kernel_tid)
154{
155 debug ("get_fpreg_clbk");
156
157 /* Not sure that we actually need to do anything in this callback. */
158 return ESUCCESS;
159}
160
161/* Set floating-point regs. */
162
163static int
164set_fpreg_clbk (void *caller_context, const pthreadDebugFregs_t *fregs,
165 pthreadDebugKId_t kernel_tid)
166{
167 debug ("set_fpreg_clbk");
168
169 /* Not sure that we actually need to do anything in this callback. */
170 return ESUCCESS;
171}
172
173static void *
174malloc_clbk (void *caller_context, size_t size)
175{
176 return xmalloc (size);
177}
178
179static void
180free_clbk (void *caller_context, void *address)
181{
182 xfree (address);
183}
184
185static int
186kthdinfo_clbk (pthreadDebugClient_t caller_context,
187 pthreadDebugKId_t kernel_tid,
188 pthreadDebugKThreadInfo_p thread_info)
189{
190 return ENOTSUP;
191}
192
193static int
194speckthd_clbk (pthreadDebugClient_t caller_context,
195 pthreadDebugSpecialType_t type,
196 pthreadDebugKId_t *kernel_tid)
197{
198 return ENOTSUP;
199}
200
201static pthreadDebugCallbacks_t debug_callbacks =
202{
203 PTHREAD_DEBUG_VERSION,
204 (pthreadDebugGetMemRtn_t) read_clbk,
205 (pthreadDebugSetMemRtn_t) write_clbk,
206 suspend_clbk,
207 resume_clbk,
208 kthdinfo_clbk,
209 hold_clbk,
210 unhold_clbk,
211 (pthreadDebugGetFregRtn_t) get_fpreg_clbk,
212 (pthreadDebugSetFregRtn_t) set_fpreg_clbk,
213 (pthreadDebugGetRegRtn_t) get_reg_clbk,
214 (pthreadDebugSetRegRtn_t) set_reg_clbk,
215 (pthreadDebugOutputRtn_t) output_clbk,
216 (pthreadDebugOutputRtn_t) error_clbk,
217 malloc_clbk,
218 free_clbk,
219 speckthd_clbk
220};
221
222/* Activate thread support if appropriate. Do nothing if thread
223 support is already active. */
224
225static void
226enable_dec_thread (void)
227{
228 struct minimal_symbol *msym;
229 void* caller_context;
230 int status;
231
232 /* If already active, nothing more to do. */
233 if (dec_thread_active)
234 return;
235
236 msym = lookup_minimal_symbol ("__pthread_dbg_symtable", NULL, NULL);
237 if (msym == NULL)
238 {
239 debug ("enable_dec_thread: No __pthread_dbg_symtable");
240 return;
241 }
242
243 status = pthreadDebugContextInit (&caller_context, &debug_callbacks,
244 (void *) SYMBOL_VALUE_ADDRESS (msym),
245 &debug_context);
246 if (status != ESUCCESS)
247 {
248 debug ("enable_dec_thread: pthreadDebugContextInit -> %d",
249 status);
250 return;
251 }
252
7a052092
JB
253 push_target (&dec_thread_ops);
254 dec_thread_active = 1;
255
256 debug ("enable_dec_thread: Thread support enabled.");
257}
258
259/* Deactivate thread support. Do nothing is thread support is
260 already inactive. */
261
262static void
263disable_dec_thread (void)
264{
265 if (!dec_thread_active)
266 return;
267
268 pthreadDebugContextDestroy (debug_context);
269 unpush_target (&dec_thread_ops);
270 dec_thread_active = 0;
271}
272
273/* A structure that contains a thread ID and is associated
274 pthreadDebugThreadInfo_t data. */
275
276struct dec_thread_info
277{
278 pthreadDebugId_t thread;
279 pthreadDebugThreadInfo_t info;
280};
281typedef struct dec_thread_info dec_thread_info_s;
282
283/* The list of user threads. */
284
285DEF_VEC_O (dec_thread_info_s);
286VEC(dec_thread_info_s) *dec_thread_list;
287
288/* Release the memory used by the given VECP thread list pointer.
289 Then set *VECP to NULL. */
290
291static void
292free_dec_thread_info_vec (VEC(dec_thread_info_s) **vecp)
293{
294 int i;
295 struct dec_thread_info *item;
296 VEC(dec_thread_info_s) *vec = *vecp;
297
298 for (i = 0; VEC_iterate (dec_thread_info_s, vec, i, item); i++)
299 xfree (item);
300 VEC_free (dec_thread_info_s, vec);
301 *vecp = NULL;
302}
303
304/* Return a thread's ptid given its associated INFO. */
305
306static ptid_t
307ptid_build_from_info (struct dec_thread_info info)
308{
309 int pid = ptid_get_pid (inferior_ptid);
310
311 return ptid_build (pid, 0, (long) info.thread);
312}
313
1596ad23
JB
314/* Return non-zero if PTID is still alive.
315
316 Assumes that DEC_THREAD_LIST is up to date. */
317static int
318dec_thread_ptid_is_alive (ptid_t ptid)
319{
320 pthreadDebugId_t tid = ptid_get_tid (ptid);
321 int i;
322 struct dec_thread_info *info;
323
324 if (tid == 0)
325 /* This is the thread corresponding to the process. This ptid
326 is always alive until the program exits. */
327 return 1;
328
329 /* Search whether an entry with the same tid exists in the dec-thread
330 list of threads. If it does, then the thread is still alive.
331 No match found means that the thread must be dead, now. */
332 for (i = 0; VEC_iterate (dec_thread_info_s, dec_thread_list, i, info); i++)
333 if (info->thread == tid)
334 return 1;
335 return 0;
336}
337
7a052092
JB
338/* Recompute the list of user threads and store the result in
339 DEC_THREAD_LIST. */
340
341static void
342update_dec_thread_list (void)
343{
344 pthreadDebugId_t thread;
345 pthreadDebugThreadInfo_t info;
346 int res;
347
348 free_dec_thread_info_vec (&dec_thread_list);
349 res = pthreadDebugThdSeqInit (debug_context, &thread);
350 while (res == ESUCCESS)
351 {
352
353 res = pthreadDebugThdGetInfo (debug_context, thread, &info);
354 if (res != ESUCCESS)
355 warning (_("unable to get thread info, ignoring thread %ld"),
356 thread);
357 else if (info.kind == PTHREAD_DEBUG_THD_KIND_INITIAL
358 || info.kind == PTHREAD_DEBUG_THD_KIND_NORMAL)
359 {
360 struct dec_thread_info *item =
361 xmalloc (sizeof (struct dec_thread_info));
362
363 item->thread = thread;
364 item->info = info;
365 VEC_safe_push (dec_thread_info_s, dec_thread_list, item);
366 }
367 res = pthreadDebugThdSeqNext (debug_context, &thread);
368 }
369 pthreadDebugThdSeqDestroy (debug_context);
370}
371
372/* A callback to count the number of threads known to GDB. */
373
374static int
375dec_thread_count_gdb_threads (struct thread_info *ignored, void *context)
376{
377 int *count = (int *) context;
378
1596ad23 379 *count = *count + 1;
7a052092
JB
380 return 0;
381}
382
383/* A callback that saves the given thread INFO at the end of an
384 array. The end of the array is given in the CONTEXT and is
385 incremented once the info has been added. */
386
387static int
388dec_thread_add_gdb_thread (struct thread_info *info, void *context)
389{
390 struct thread_info ***listp = (struct thread_info ***) context;
391
392 **listp = info;
1596ad23 393 *listp = *listp + 1;
7a052092
JB
394 return 0;
395}
396
397/* Resynchronize the list of threads known by GDB with the actual
398 list of threads reported by libpthread_debug. */
399
400static void
401resync_thread_list (void)
402{
403 int i;
404 struct dec_thread_info *info;
405 int num_gdb_threads = 0;
406 struct thread_info **gdb_thread_list;
407 struct thread_info **next_thread_info;
408
409 update_dec_thread_list ();
410
411 /* Add new threads. */
412
1596ad23 413 for (i = 0; VEC_iterate (dec_thread_info_s, dec_thread_list, i, info); i++)
7a052092
JB
414 {
415 ptid_t ptid = ptid_build_from_info (*info);
416
417 if (!in_thread_list (ptid))
418 add_thread (ptid);
419 }
420
421 /* Remove threads that no longer exist. To help with the search,
422 we build an array of GDB threads, and then iterate over this
423 array. */
424
425 iterate_over_threads (dec_thread_count_gdb_threads,
426 (void *) &num_gdb_threads);
427 gdb_thread_list = alloca (num_gdb_threads * sizeof (struct thread_info *));
428 next_thread_info = gdb_thread_list;
429 iterate_over_threads (dec_thread_add_gdb_thread, (void *) &next_thread_info);
7a052092 430
1596ad23
JB
431 for (i = 0; i < num_gdb_threads; i++)
432 if (!dec_thread_ptid_is_alive (gdb_thread_list[i]->ptid))
7a052092 433 delete_thread (gdb_thread_list[i]->ptid);
7a052092
JB
434}
435
436/* The "to_detach" method of the dec_thread_ops. */
437
438static void
b254c0b2 439dec_thread_detach (struct target_ops *ops, char *args, int from_tty)
7a052092 440{
b254c0b2
JB
441 struct target_ops *beneath = find_target_beneath (ops);
442
7a052092
JB
443 debug ("dec_thread_detach");
444
445 disable_dec_thread ();
b254c0b2 446 beneath->to_detach (beneath, args, from_tty);
7a052092
JB
447}
448
449/* Return the ptid of the thread that is currently active. */
450
451static ptid_t
452get_active_ptid (void)
453{
454 int i;
455 struct dec_thread_info *info;
456
457 for (i = 0; VEC_iterate (dec_thread_info_s, dec_thread_list, i, info);
458 i++)
459 if (info->info.state == PTHREAD_DEBUG_STATE_RUNNING)
460 return ptid_build_from_info (*info);
461
462 /* No active thread found. This can happen when the program
463 has just exited. */
464 return null_ptid;
465}
466
467/* The "to_wait" method of the dec_thread_ops. */
468
469static ptid_t
117de6a9 470dec_thread_wait (struct target_ops *ops,
61439e34 471 ptid_t ptid, struct target_waitstatus *status, int options)
7a052092
JB
472{
473 ptid_t active_ptid;
b254c0b2 474 struct target_ops *beneath = find_target_beneath (ops);
7a052092
JB
475
476 debug ("dec_thread_wait");
477
61439e34 478 ptid = beneath->to_wait (beneath, ptid, status, options);
7a052092 479
b254c0b2
JB
480 /* The ptid returned by the target beneath us is the ptid of the process.
481 We need to find which thread is currently active and return its ptid. */
7a052092
JB
482 resync_thread_list ();
483 active_ptid = get_active_ptid ();
484 if (ptid_equal (active_ptid, null_ptid))
485 return ptid;
486 return active_ptid;
487}
488
489/* Fetch the general purpose and floating point registers for the given
490 thread TID, and store the result in GREGSET and FPREGSET. Return
491 zero if successful. */
492
493static int
494dec_thread_get_regsets (pthreadDebugId_t tid, gdb_gregset_t *gregset,
495 gdb_fpregset_t *fpregset)
496{
497 int res;
498 pthreadDebugRegs_t regs;
499 pthreadDebugFregs_t fregs;
500
501 res = pthreadDebugThdGetReg (debug_context, tid, &regs);
502 if (res != ESUCCESS)
503 {
b254c0b2 504 debug ("dec_thread_get_regsets: pthreadDebugThdGetReg -> %d", res);
7a052092
JB
505 return -1;
506 }
507 memcpy (gregset->regs, &regs, sizeof (regs));
508
509 res = pthreadDebugThdGetFreg (debug_context, tid, &fregs);
510 if (res != ESUCCESS)
511 {
b254c0b2 512 debug ("dec_thread_get_regsets: pthreadDebugThdGetFreg -> %d", res);
7a052092
JB
513 return -1;
514 }
515 memcpy (fpregset->regs, &fregs, sizeof (fregs));
516
517 return 0;
518}
519
520/* The "to_fetch_registers" method of the dec_thread_ops.
521
522 Because the dec-thread debug API doesn't allow us to fetch
523 only one register, we simply ignore regno and fetch+supply all
524 registers. */
525
526static void
b254c0b2
JB
527dec_thread_fetch_registers (struct target_ops *ops,
528 struct regcache *regcache, int regno)
7a052092
JB
529{
530 pthreadDebugId_t tid = ptid_get_tid (inferior_ptid);
531 gregset_t gregset;
532 fpregset_t fpregset;
533 int res;
534
535 debug ("dec_thread_fetch_registers (tid=%ld, regno=%d)", tid, regno);
536
537
538 if (tid == 0 || ptid_equal (inferior_ptid, get_active_ptid ()))
539 {
b254c0b2
JB
540 struct target_ops *beneath = find_target_beneath (ops);
541
542 beneath->to_fetch_registers (beneath, regcache, regno);
7a052092
JB
543 return;
544 }
545
546 res = dec_thread_get_regsets (tid, &gregset, &fpregset);
547 if (res != 0)
548 return;
549
550 supply_gregset (regcache, &gregset);
551 supply_fpregset (regcache, &fpregset);
552}
553
554/* Store the registers given in GREGSET and FPREGSET into the associated
555 general purpose and floating point registers of thread TID. Return
556 zero if successful. */
557
558static int
559dec_thread_set_regsets (pthreadDebugId_t tid, gdb_gregset_t gregset,
560 gdb_fpregset_t fpregset)
561{
562 int res;
563 pthreadDebugRegs_t regs;
564 pthreadDebugFregs_t fregs;
565
566 memcpy (&regs, gregset.regs, sizeof (regs));
567 res = pthreadDebugThdSetReg (debug_context, tid, &regs);
568 if (res != ESUCCESS)
569 {
b254c0b2 570 debug ("dec_thread_set_regsets: pthreadDebugThdSetReg -> %d", res);
7a052092
JB
571 return -1;
572 }
573
574 memcpy (&fregs, fpregset.regs, sizeof (fregs));
575 res = pthreadDebugThdSetFreg (debug_context, tid, &fregs);
576 if (res != ESUCCESS)
577 {
b254c0b2 578 debug ("dec_thread_set_regsets: pthreadDebugThdSetFreg -> %d", res);
7a052092
JB
579 return -1;
580 }
581
582 return 0;
583}
584
585/* The "to_store_registers" method of the dec_thread_ops.
586
587 Because the dec-thread debug API doesn't allow us to store
588 just one register, we store all the registers. */
589
590static void
b254c0b2
JB
591dec_thread_store_registers (struct target_ops *ops,
592 struct regcache *regcache, int regno)
7a052092
JB
593{
594 pthreadDebugId_t tid = ptid_get_tid (inferior_ptid);
595 gregset_t gregset;
596 fpregset_t fpregset;
597 int res;
598
599 debug ("dec_thread_store_registers (tid=%ld, regno=%d)", tid, regno);
600
601 if (tid == 0 || ptid_equal (inferior_ptid, get_active_ptid ()))
602 {
b254c0b2
JB
603 struct target_ops *beneath = find_target_beneath (ops);
604
605 beneath->to_store_registers (beneath, regcache, regno);
7a052092
JB
606 return;
607 }
608
609 /* FIXME: brobecker/2008-05-28: I wonder if we could simply check
610 in which register set the register is and then only store the
611 registers for that register set, instead of storing both register
612 sets. */
613 fill_gregset (regcache, &gregset, -1);
614 fill_fpregset (regcache, &fpregset, -1);
615
616 res = dec_thread_set_regsets (tid, gregset, fpregset);
617 if (res != 0)
618 warning (_("failed to store registers."));
619}
620
621/* The "to_mourn_inferior" method of the dec_thread_ops. */
622
623static void
b254c0b2 624dec_thread_mourn_inferior (struct target_ops *ops)
7a052092 625{
b254c0b2
JB
626 struct target_ops *beneath = find_target_beneath (ops);
627
7a052092
JB
628 debug ("dec_thread_mourn_inferior");
629
630 disable_dec_thread ();
b254c0b2 631 beneath->to_mourn_inferior (beneath);
7a052092
JB
632}
633
634/* The "to_thread_alive" method of the dec_thread_ops. */
635static int
b254c0b2 636dec_thread_thread_alive (struct target_ops *ops, ptid_t ptid)
7a052092
JB
637{
638 debug ("dec_thread_thread_alive (tid=%ld)", ptid_get_tid (ptid));
639
640 /* The thread list maintained by GDB is up to date, since we update
641 it everytime we stop. So check this list. */
642 return in_thread_list (ptid);
643}
644
645/* The "to_pid_to_str" method of the dec_thread_ops. */
646
647static char *
117de6a9 648dec_thread_pid_to_str (struct target_ops *ops, ptid_t ptid)
7a052092
JB
649{
650 static char *ret = NULL;
651
652 if (ptid_get_tid (ptid) == 0)
b254c0b2
JB
653 {
654 struct target_ops *beneath = find_target_beneath (ops);
655
656 return beneath->to_pid_to_str (beneath, ptid);
657 }
7a052092
JB
658
659 /* Free previous return value; a new one will be allocated by
660 xstrprintf(). */
661 xfree (ret);
662
663 ret = xstrprintf (_("Thread %ld"), ptid_get_tid (ptid));
664 return ret;
665}
666
667/* A "new-objfile" observer. Used to activate/deactivate dec-thread
668 support. */
669
670static void
671dec_thread_new_objfile_observer (struct objfile *objfile)
672{
673 if (objfile != NULL)
674 enable_dec_thread ();
675 else
676 disable_dec_thread ();
677}
678
d36df9c5
JB
679/* The "to_get_ada_task_ptid" method of the dec_thread_ops. */
680
681static ptid_t
682dec_thread_get_ada_task_ptid (long lwp, long thread)
683{
684 int i;
685 struct dec_thread_info *info;
686
687 debug ("dec_thread_get_ada_task_ptid (lwp=0x%lx, thread=0x%lx)",
688 lwp, thread);
689
690 for (i = 0; VEC_iterate (dec_thread_info_s, dec_thread_list, i, info);
691 i++)
692 if (info->info.teb == (pthread_t) thread)
693 return ptid_build_from_info (*info);
694
695 warning (_("Could not find thread id from THREAD = 0x%lx\n"), thread);
696 return inferior_ptid;
697}
698
7a052092
JB
699static void
700init_dec_thread_ops (void)
701{
702 dec_thread_ops.to_shortname = "dec-threads";
703 dec_thread_ops.to_longname = _("DEC threads support");
704 dec_thread_ops.to_doc = _("DEC threads support");
705 dec_thread_ops.to_detach = dec_thread_detach;
706 dec_thread_ops.to_wait = dec_thread_wait;
707 dec_thread_ops.to_fetch_registers = dec_thread_fetch_registers;
708 dec_thread_ops.to_store_registers = dec_thread_store_registers;
709 dec_thread_ops.to_mourn_inferior = dec_thread_mourn_inferior;
710 dec_thread_ops.to_thread_alive = dec_thread_thread_alive;
711 dec_thread_ops.to_pid_to_str = dec_thread_pid_to_str;
712 dec_thread_ops.to_stratum = thread_stratum;
d36df9c5 713 dec_thread_ops.to_get_ada_task_ptid = dec_thread_get_ada_task_ptid;
7a052092
JB
714 dec_thread_ops.to_magic = OPS_MAGIC;
715}
716
717void
718_initialize_dec_thread (void)
719{
720 init_dec_thread_ops ();
721 add_target (&dec_thread_ops);
722
723 observer_attach_new_objfile (dec_thread_new_objfile_observer);
724
725 add_setshow_boolean_cmd ("dec-thread", class_maintenance, &debug_dec_thread,
726 _("Set debugging of DEC threads module."),
727 _("Show debugging of DEC threads module."),
728 _("Enables debugging output (used to debug GDB)."),
729 NULL, NULL,
730 &setdebuglist, &showdebuglist);
731}
This page took 0.216214 seconds and 4 git commands to generate.