Don't check target_info exists noargs in commands.exp
[deliverable/binutils-gdb.git] / gdb / dec-thread.c
CommitLineData
ecd75fc8 1/* Copyright (C) 2008-2014 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
0963b4bd 111/* Get integer regs. */
7a052092
JB
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
0963b4bd 123/* Set integer regs. */
7a052092
JB
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{
3b7344d5 228 struct bound_minimal_symbol msym;
7a052092
JB
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);
3b7344d5 237 if (msym.minsym == NULL)
7a052092
JB
238 {
239 debug ("enable_dec_thread: No __pthread_dbg_symtable");
240 return;
241 }
242
243 status = pthreadDebugContextInit (&caller_context, &debug_callbacks,
3b7344d5 244 (void *) SYMBOL_VALUE_ADDRESS (msym.minsym),
7a052092
JB
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
0963b4bd 259/* Deactivate thread support. Do nothing if thread support is
7a052092
JB
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
44ee4a52 372/* Implement the update_thread_list target_ops method. */
7a052092
JB
373
374static void
44ee4a52 375dec_thread_update_thread_list (struct target_ops *ops)
7a052092
JB
376{
377 int i;
378 struct dec_thread_info *info;
44ee4a52 379 struct thread_info *tp, *tmp;
7a052092
JB
380
381 update_dec_thread_list ();
44ee4a52
PA
382
383 /* Delete GDB-side threads no longer found in dec_thread_list. */
384 ALL_NON_EXITED_THREADS_SAFE (tp, tmp)
385 {
386 for (i = 0; VEC_iterate (dec_thread_info_s, dec_thread_list, i, info); i++)
387 {
388 if (ptid_equal (info->ptid, tp->ptid))
389 break;
390 }
391 if (i == VEC_length (dec_thread_info_s, dec_thread_list))
392 {
393 /* Not found. */
394 delete_thread (tp->ptid);
395 }
396 }
397
398 /* And now add new threads. */
1596ad23 399 for (i = 0; VEC_iterate (dec_thread_info_s, dec_thread_list, i, info); i++)
7a052092
JB
400 {
401 ptid_t ptid = ptid_build_from_info (*info);
402
403 if (!in_thread_list (ptid))
404 add_thread (ptid);
405 }
6fbc7cd8
JB
406}
407
7a052092
JB
408/* The "to_detach" method of the dec_thread_ops. */
409
410static void
52554a0e 411dec_thread_detach (struct target_ops *ops, const char *args, int from_tty)
7a052092 412{
b254c0b2
JB
413 struct target_ops *beneath = find_target_beneath (ops);
414
7a052092
JB
415 debug ("dec_thread_detach");
416
417 disable_dec_thread ();
b254c0b2 418 beneath->to_detach (beneath, args, from_tty);
7a052092
JB
419}
420
421/* Return the ptid of the thread that is currently active. */
422
423static ptid_t
424get_active_ptid (void)
425{
426 int i;
427 struct dec_thread_info *info;
428
429 for (i = 0; VEC_iterate (dec_thread_info_s, dec_thread_list, i, info);
430 i++)
431 if (info->info.state == PTHREAD_DEBUG_STATE_RUNNING)
432 return ptid_build_from_info (*info);
433
434 /* No active thread found. This can happen when the program
435 has just exited. */
436 return null_ptid;
437}
438
439/* The "to_wait" method of the dec_thread_ops. */
440
441static ptid_t
117de6a9 442dec_thread_wait (struct target_ops *ops,
61439e34 443 ptid_t ptid, struct target_waitstatus *status, int options)
7a052092
JB
444{
445 ptid_t active_ptid;
b254c0b2 446 struct target_ops *beneath = find_target_beneath (ops);
7a052092
JB
447
448 debug ("dec_thread_wait");
449
61439e34 450 ptid = beneath->to_wait (beneath, ptid, status, options);
7a052092 451
b254c0b2
JB
452 /* The ptid returned by the target beneath us is the ptid of the process.
453 We need to find which thread is currently active and return its ptid. */
44ee4a52 454 dec_thread_update_thread_list (ops);
7a052092
JB
455 active_ptid = get_active_ptid ();
456 if (ptid_equal (active_ptid, null_ptid))
457 return ptid;
458 return active_ptid;
459}
460
461/* Fetch the general purpose and floating point registers for the given
462 thread TID, and store the result in GREGSET and FPREGSET. Return
463 zero if successful. */
464
465static int
466dec_thread_get_regsets (pthreadDebugId_t tid, gdb_gregset_t *gregset,
467 gdb_fpregset_t *fpregset)
468{
469 int res;
470 pthreadDebugRegs_t regs;
471 pthreadDebugFregs_t fregs;
472
473 res = pthreadDebugThdGetReg (debug_context, tid, &regs);
474 if (res != ESUCCESS)
475 {
b254c0b2 476 debug ("dec_thread_get_regsets: pthreadDebugThdGetReg -> %d", res);
7a052092
JB
477 return -1;
478 }
479 memcpy (gregset->regs, &regs, sizeof (regs));
480
481 res = pthreadDebugThdGetFreg (debug_context, tid, &fregs);
482 if (res != ESUCCESS)
483 {
b254c0b2 484 debug ("dec_thread_get_regsets: pthreadDebugThdGetFreg -> %d", res);
7a052092
JB
485 return -1;
486 }
487 memcpy (fpregset->regs, &fregs, sizeof (fregs));
488
489 return 0;
490}
491
492/* The "to_fetch_registers" method of the dec_thread_ops.
493
494 Because the dec-thread debug API doesn't allow us to fetch
495 only one register, we simply ignore regno and fetch+supply all
496 registers. */
497
498static void
b254c0b2
JB
499dec_thread_fetch_registers (struct target_ops *ops,
500 struct regcache *regcache, int regno)
7a052092
JB
501{
502 pthreadDebugId_t tid = ptid_get_tid (inferior_ptid);
503 gregset_t gregset;
504 fpregset_t fpregset;
505 int res;
506
507 debug ("dec_thread_fetch_registers (tid=%ld, regno=%d)", tid, regno);
508
509
510 if (tid == 0 || ptid_equal (inferior_ptid, get_active_ptid ()))
511 {
b254c0b2
JB
512 struct target_ops *beneath = find_target_beneath (ops);
513
514 beneath->to_fetch_registers (beneath, regcache, regno);
7a052092
JB
515 return;
516 }
517
518 res = dec_thread_get_regsets (tid, &gregset, &fpregset);
519 if (res != 0)
520 return;
521
522 supply_gregset (regcache, &gregset);
523 supply_fpregset (regcache, &fpregset);
524}
525
526/* Store the registers given in GREGSET and FPREGSET into the associated
527 general purpose and floating point registers of thread TID. Return
528 zero if successful. */
529
530static int
531dec_thread_set_regsets (pthreadDebugId_t tid, gdb_gregset_t gregset,
532 gdb_fpregset_t fpregset)
533{
534 int res;
535 pthreadDebugRegs_t regs;
536 pthreadDebugFregs_t fregs;
537
538 memcpy (&regs, gregset.regs, sizeof (regs));
539 res = pthreadDebugThdSetReg (debug_context, tid, &regs);
540 if (res != ESUCCESS)
541 {
b254c0b2 542 debug ("dec_thread_set_regsets: pthreadDebugThdSetReg -> %d", res);
7a052092
JB
543 return -1;
544 }
545
546 memcpy (&fregs, fpregset.regs, sizeof (fregs));
547 res = pthreadDebugThdSetFreg (debug_context, tid, &fregs);
548 if (res != ESUCCESS)
549 {
b254c0b2 550 debug ("dec_thread_set_regsets: pthreadDebugThdSetFreg -> %d", res);
7a052092
JB
551 return -1;
552 }
553
554 return 0;
555}
556
557/* The "to_store_registers" method of the dec_thread_ops.
558
559 Because the dec-thread debug API doesn't allow us to store
560 just one register, we store all the registers. */
561
562static void
b254c0b2
JB
563dec_thread_store_registers (struct target_ops *ops,
564 struct regcache *regcache, int regno)
7a052092
JB
565{
566 pthreadDebugId_t tid = ptid_get_tid (inferior_ptid);
567 gregset_t gregset;
568 fpregset_t fpregset;
569 int res;
570
571 debug ("dec_thread_store_registers (tid=%ld, regno=%d)", tid, regno);
572
573 if (tid == 0 || ptid_equal (inferior_ptid, get_active_ptid ()))
574 {
b254c0b2
JB
575 struct target_ops *beneath = find_target_beneath (ops);
576
577 beneath->to_store_registers (beneath, regcache, regno);
7a052092
JB
578 return;
579 }
580
581 /* FIXME: brobecker/2008-05-28: I wonder if we could simply check
582 in which register set the register is and then only store the
583 registers for that register set, instead of storing both register
584 sets. */
585 fill_gregset (regcache, &gregset, -1);
586 fill_fpregset (regcache, &fpregset, -1);
587
588 res = dec_thread_set_regsets (tid, gregset, fpregset);
589 if (res != 0)
590 warning (_("failed to store registers."));
591}
592
593/* The "to_mourn_inferior" method of the dec_thread_ops. */
594
595static void
b254c0b2 596dec_thread_mourn_inferior (struct target_ops *ops)
7a052092 597{
b254c0b2
JB
598 struct target_ops *beneath = find_target_beneath (ops);
599
7a052092
JB
600 debug ("dec_thread_mourn_inferior");
601
602 disable_dec_thread ();
b254c0b2 603 beneath->to_mourn_inferior (beneath);
7a052092
JB
604}
605
606/* The "to_thread_alive" method of the dec_thread_ops. */
607static int
b254c0b2 608dec_thread_thread_alive (struct target_ops *ops, ptid_t ptid)
7a052092
JB
609{
610 debug ("dec_thread_thread_alive (tid=%ld)", ptid_get_tid (ptid));
611
612 /* The thread list maintained by GDB is up to date, since we update
613 it everytime we stop. So check this list. */
614 return in_thread_list (ptid);
615}
616
617/* The "to_pid_to_str" method of the dec_thread_ops. */
618
619static char *
117de6a9 620dec_thread_pid_to_str (struct target_ops *ops, ptid_t ptid)
7a052092
JB
621{
622 static char *ret = NULL;
623
624 if (ptid_get_tid (ptid) == 0)
b254c0b2
JB
625 {
626 struct target_ops *beneath = find_target_beneath (ops);
627
628 return beneath->to_pid_to_str (beneath, ptid);
629 }
7a052092
JB
630
631 /* Free previous return value; a new one will be allocated by
632 xstrprintf(). */
633 xfree (ret);
634
635 ret = xstrprintf (_("Thread %ld"), ptid_get_tid (ptid));
636 return ret;
637}
638
639/* A "new-objfile" observer. Used to activate/deactivate dec-thread
640 support. */
641
642static void
643dec_thread_new_objfile_observer (struct objfile *objfile)
644{
645 if (objfile != NULL)
646 enable_dec_thread ();
647 else
648 disable_dec_thread ();
649}
650
d36df9c5
JB
651/* The "to_get_ada_task_ptid" method of the dec_thread_ops. */
652
653static ptid_t
1e6b91a4 654dec_thread_get_ada_task_ptid (struct target_ops *self, long lwp, long thread)
d36df9c5
JB
655{
656 int i;
657 struct dec_thread_info *info;
658
8d4fdb12
JB
659 debug ("dec_thread_get_ada_task_ptid (struct target_ops *self,"
660 " lwp=0x%lx, thread=0x%lx)",
d36df9c5
JB
661 lwp, thread);
662
663 for (i = 0; VEC_iterate (dec_thread_info_s, dec_thread_list, i, info);
664 i++)
665 if (info->info.teb == (pthread_t) thread)
666 return ptid_build_from_info (*info);
8d4fdb12 667
b37520b6 668 warning (_("Could not find thread id from THREAD = 0x%lx"), thread);
d36df9c5
JB
669 return inferior_ptid;
670}
671
7a052092
JB
672static void
673init_dec_thread_ops (void)
674{
675 dec_thread_ops.to_shortname = "dec-threads";
676 dec_thread_ops.to_longname = _("DEC threads support");
677 dec_thread_ops.to_doc = _("DEC threads support");
678 dec_thread_ops.to_detach = dec_thread_detach;
679 dec_thread_ops.to_wait = dec_thread_wait;
680 dec_thread_ops.to_fetch_registers = dec_thread_fetch_registers;
681 dec_thread_ops.to_store_registers = dec_thread_store_registers;
682 dec_thread_ops.to_mourn_inferior = dec_thread_mourn_inferior;
683 dec_thread_ops.to_thread_alive = dec_thread_thread_alive;
e8032dde 684 dec_thread_ops.to_update_thread_list = dec_thread_update_thread_list;
7a052092
JB
685 dec_thread_ops.to_pid_to_str = dec_thread_pid_to_str;
686 dec_thread_ops.to_stratum = thread_stratum;
d36df9c5 687 dec_thread_ops.to_get_ada_task_ptid = dec_thread_get_ada_task_ptid;
7a052092
JB
688 dec_thread_ops.to_magic = OPS_MAGIC;
689}
690
691void
692_initialize_dec_thread (void)
693{
694 init_dec_thread_ops ();
12070676 695 complete_target_initialization (&dec_thread_ops);
7a052092
JB
696
697 observer_attach_new_objfile (dec_thread_new_objfile_observer);
698
699 add_setshow_boolean_cmd ("dec-thread", class_maintenance, &debug_dec_thread,
700 _("Set debugging of DEC threads module."),
701 _("Show debugging of DEC threads module."),
702 _("Enables debugging output (used to debug GDB)."),
703 NULL, NULL,
704 &setdebuglist, &showdebuglist);
705}
This page took 0.48827 seconds and 4 git commands to generate.