import gdb-1999-07-07 post reformat
[deliverable/binutils-gdb.git] / gdb / thread.c
CommitLineData
c906108c
SS
1/* Multi-process/thread control for GDB, the GNU debugger.
2 Copyright 1986, 1987, 1988, 1993, 1998
3
4 Contributed by Lynx Real-Time Systems, Inc. Los Gatos, CA.
5 Free Software Foundation, Inc.
6
7This file is part of GDB.
8
9This program is free software; you can redistribute it and/or modify
10it under the terms of the GNU General Public License as published by
11the Free Software Foundation; either version 2 of the License, or
12(at your option) any later version.
13
14This program is distributed in the hope that it will be useful,
15but WITHOUT ANY WARRANTY; without even the implied warranty of
16MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17GNU General Public License for more details.
18
19You should have received a copy of the GNU General Public License
20along with this program; if not, write to the Free Software
21Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
22
23#include "defs.h"
24#include "symtab.h"
25#include "frame.h"
26#include "inferior.h"
27#include "environ.h"
28#include "value.h"
29#include "target.h"
30#include "gdbthread.h"
31#include "command.h"
32#include "gdbcmd.h"
33
34#include <ctype.h>
35#include <sys/types.h>
36#include <signal.h>
37
38/*#include "lynxos-core.h"*/
39
40struct thread_info
41{
42 struct thread_info *next;
43 int pid; /* Actual process id */
44 int num; /* Convenient handle */
45 CORE_ADDR prev_pc; /* State from wait_for_inferior */
46 CORE_ADDR prev_func_start;
47 char *prev_func_name;
48 struct breakpoint *step_resume_breakpoint;
49 struct breakpoint *through_sigtramp_breakpoint;
50 CORE_ADDR step_range_start;
51 CORE_ADDR step_range_end;
52 CORE_ADDR step_frame_address;
53 int trap_expected;
54 int handling_longjmp;
55 int another_trap;
56
57 /* This is set TRUE when a catchpoint of a shared library event
58 triggers. Since we don't wish to leave the inferior in the
59 solib hook when we report the event, we step the inferior
60 back to user code before stopping and reporting the event.
61 */
62 int stepping_through_solib_after_catch;
63
64 /* When stepping_through_solib_after_catch is TRUE, this is a
65 list of the catchpoints that should be reported as triggering
66 when we finally do stop stepping.
67 */
68 bpstat stepping_through_solib_catchpoints;
69
70 /* This is set to TRUE when this thread is in a signal handler
71 trampoline and we're single-stepping through it */
72 int stepping_through_sigtramp;
73
74};
75
76/* Prototypes for exported functions. */
77
78void _initialize_thread PARAMS ((void));
79
80/* Prototypes for local functions. */
81
c906108c
SS
82static struct thread_info *thread_list = NULL;
83static int highest_thread_num;
84
85static struct thread_info * find_thread_id PARAMS ((int num));
86
87static void thread_command PARAMS ((char * tidstr, int from_tty));
88static void thread_apply_all_command PARAMS ((char *, int));
89static int thread_alive PARAMS ((struct thread_info *));
90static void info_threads_command PARAMS ((char *, int));
91static void thread_apply_command PARAMS ((char *, int));
92static void restore_current_thread PARAMS ((int));
93static void switch_to_thread PARAMS ((int pid));
94static void prune_threads PARAMS ((void));
c906108c
SS
95
96void
97init_thread_list ()
98{
99 struct thread_info *tp, *tpnext;
100
101 if (!thread_list)
102 return;
103
104 for (tp = thread_list; tp; tp = tpnext)
105 {
106 tpnext = tp->next;
107 free (tp);
108 }
109
110 thread_list = NULL;
111 highest_thread_num = 0;
112}
113
114void
115add_thread (pid)
116 int pid;
117{
118 struct thread_info *tp;
119
120 tp = (struct thread_info *) xmalloc (sizeof (struct thread_info));
121
122 tp->pid = pid;
123 tp->num = ++highest_thread_num;
124 tp->prev_pc = 0;
125 tp->prev_func_start = 0;
126 tp->prev_func_name = NULL;
127 tp->step_range_start = 0;
128 tp->step_range_end = 0;
129 tp->step_frame_address =0;
130 tp->step_resume_breakpoint = 0;
131 tp->through_sigtramp_breakpoint = 0;
132 tp->handling_longjmp = 0;
133 tp->trap_expected = 0;
134 tp->another_trap = 0;
135 tp->stepping_through_solib_after_catch = 0;
136 tp->stepping_through_solib_catchpoints = NULL;
137 tp->stepping_through_sigtramp = 0;
138 tp->next = thread_list;
139 thread_list = tp;
140}
141
142void
143delete_thread (pid)
144 int pid;
145{
146 struct thread_info *tp, *tpprev;
147
148 tpprev = NULL;
149
150 for (tp = thread_list; tp; tpprev = tp, tp = tp->next)
151 if (tp->pid == pid)
152 break;
153
154 if (!tp)
155 return;
156
157 if (tpprev)
158 tpprev->next = tp->next;
159 else
160 thread_list = tp->next;
161
162 free (tp);
163
164 return;
165}
166
167static struct thread_info *
168find_thread_id (num)
169 int num;
170{
171 struct thread_info *tp;
172
173 for (tp = thread_list; tp; tp = tp->next)
174 if (tp->num == num)
175 return tp;
176
177 return NULL;
178}
179
180int
181valid_thread_id (num)
182 int num;
183{
184 struct thread_info *tp;
185
186 for (tp = thread_list; tp; tp = tp->next)
187 if (tp->num == num)
188 return 1;
189
190 return 0;
191}
192
193int
194pid_to_thread_id (pid)
195 int pid;
196{
197 struct thread_info *tp;
198
199 for (tp = thread_list; tp; tp = tp->next)
200 if (tp->pid == pid)
201 return tp->num;
202
203 return 0;
204}
205
206int
207thread_id_to_pid (num)
208 int num;
209{
210 struct thread_info *thread = find_thread_id (num);
211 if (thread)
212 return thread->pid;
213 else
214 return -1;
215}
216
217int
218in_thread_list (pid)
219 int pid;
220{
221 struct thread_info *tp;
222
223 for (tp = thread_list; tp; tp = tp->next)
224 if (tp->pid == pid)
225 return 1;
226
227 return 0; /* Never heard of 'im */
228}
229
230/* Load infrun state for the thread PID. */
231
232void load_infrun_state (pid, prev_pc, prev_func_start, prev_func_name,
233 trap_expected, step_resume_breakpoint,
234 through_sigtramp_breakpoint, step_range_start,
235 step_range_end, step_frame_address,
236 handling_longjmp, another_trap,
237 stepping_through_solib_after_catch,
238 stepping_through_solib_catchpoints,
239 stepping_through_sigtramp)
240 int pid;
241 CORE_ADDR *prev_pc;
242 CORE_ADDR *prev_func_start;
243 char **prev_func_name;
244 int *trap_expected;
245 struct breakpoint **step_resume_breakpoint;
246 struct breakpoint **through_sigtramp_breakpoint;
247 CORE_ADDR *step_range_start;
248 CORE_ADDR *step_range_end;
249 CORE_ADDR *step_frame_address;
250 int *handling_longjmp;
251 int *another_trap;
252 int * stepping_through_solib_after_catch;
253 bpstat * stepping_through_solib_catchpoints;
254 int * stepping_through_sigtramp;
255{
256 struct thread_info *tp;
257
258 /* If we can't find the thread, then we're debugging a single threaded
259 process. No need to do anything in that case. */
260 tp = find_thread_id (pid_to_thread_id (pid));
261 if (tp == NULL)
262 return;
263
264 *prev_pc = tp->prev_pc;
265 *prev_func_start = tp->prev_func_start;
266 *prev_func_name = tp->prev_func_name;
267 *step_resume_breakpoint = tp->step_resume_breakpoint;
268 *step_range_start = tp->step_range_start;
269 *step_range_end = tp->step_range_end;
270 *step_frame_address = tp->step_frame_address;
271 *through_sigtramp_breakpoint = tp->through_sigtramp_breakpoint;
272 *handling_longjmp = tp->handling_longjmp;
273 *trap_expected = tp->trap_expected;
274 *another_trap = tp->another_trap;
275 *stepping_through_solib_after_catch = tp->stepping_through_solib_after_catch;
276 *stepping_through_solib_catchpoints = tp->stepping_through_solib_catchpoints;
277 *stepping_through_sigtramp = tp->stepping_through_sigtramp;
278}
279
280/* Save infrun state for the thread PID. */
281
282void save_infrun_state (pid, prev_pc, prev_func_start, prev_func_name,
283 trap_expected, step_resume_breakpoint,
284 through_sigtramp_breakpoint, step_range_start,
285 step_range_end, step_frame_address,
286 handling_longjmp, another_trap,
287 stepping_through_solib_after_catch,
288 stepping_through_solib_catchpoints,
289 stepping_through_sigtramp)
290 int pid;
291 CORE_ADDR prev_pc;
292 CORE_ADDR prev_func_start;
293 char *prev_func_name;
294 int trap_expected;
295 struct breakpoint *step_resume_breakpoint;
296 struct breakpoint *through_sigtramp_breakpoint;
297 CORE_ADDR step_range_start;
298 CORE_ADDR step_range_end;
299 CORE_ADDR step_frame_address;
300 int handling_longjmp;
301 int another_trap;
302 int stepping_through_solib_after_catch;
303 bpstat stepping_through_solib_catchpoints;
304 int stepping_through_sigtramp;
305{
306 struct thread_info *tp;
307
308 /* If we can't find the thread, then we're debugging a single-threaded
309 process. Nothing to do in that case. */
310 tp = find_thread_id (pid_to_thread_id (pid));
311 if (tp == NULL)
312 return;
313
314 tp->prev_pc = prev_pc;
315 tp->prev_func_start = prev_func_start;
316 tp->prev_func_name = prev_func_name;
317 tp->step_resume_breakpoint = step_resume_breakpoint;
318 tp->step_range_start = step_range_start;
319 tp->step_range_end = step_range_end;
320 tp->step_frame_address = step_frame_address;
321 tp->through_sigtramp_breakpoint = through_sigtramp_breakpoint;
322 tp->handling_longjmp = handling_longjmp;
323 tp->trap_expected = trap_expected;
324 tp->another_trap = another_trap;
325 tp->stepping_through_solib_after_catch = stepping_through_solib_after_catch;
326 tp->stepping_through_solib_catchpoints = stepping_through_solib_catchpoints;
327 tp->stepping_through_sigtramp = stepping_through_sigtramp;
328}
329
330/* Return true if TP is an active thread. */
331static int
332thread_alive (tp)
333 struct thread_info *tp;
334{
335 if (tp->pid == -1)
336 return 0;
337 if (! target_thread_alive (tp->pid))
338 {
339 tp->pid = -1; /* Mark it as dead */
340 return 0;
341 }
342 return 1;
343}
344
345static void
346prune_threads ()
347{
348 struct thread_info *tp, *tpprev, *next;
349
350 tpprev = 0;
351 for (tp = thread_list; tp; tp = next)
352 {
353 next = tp->next;
354 if (!thread_alive (tp))
355 {
356 if (tpprev)
357 tpprev->next = next;
358 else
359 thread_list = next;
360 free (tp);
361 }
362 else
363 tpprev = tp;
364 }
365}
366
367/* Print information about currently known threads
368 *
369 * Note: this has the drawback that it _really_ switches
370 * threads, which frees the frame cache. A no-side
371 * effects info-threads command would be nicer.
372 */
373
374static void
375info_threads_command (arg, from_tty)
376 char *arg;
377 int from_tty;
378{
379 struct thread_info *tp;
380 int current_pid;
381 struct frame_info *cur_frame;
382 int saved_frame_level = selected_frame_level;
383 int counter;
384
385 /* Avoid coredumps which would happen if we tried to access a NULL
386 selected_frame. */
387 if (!target_has_stack) error ("No stack.");
388
389 prune_threads ();
b83266a0 390 target_find_new_threads ();
c906108c
SS
391 current_pid = inferior_pid;
392 for (tp = thread_list; tp; tp = tp->next)
393 {
394 if (tp->pid == current_pid)
395 printf_filtered ("* ");
396 else
397 printf_filtered (" ");
398
399#ifdef HPUXHPPA
400 printf_filtered ("%d %s ", tp->num, target_tid_to_str (tp->pid));
401#else
402 printf_filtered ("%d %s ", tp->num, target_pid_to_str (tp->pid));
403#endif
404 switch_to_thread (tp->pid);
405 if (selected_frame)
406 print_only_stack_frame (selected_frame, -1, 0);
407 else
408 printf_filtered ("[No stack.]\n");
409 }
410
411 switch_to_thread (current_pid);
412
413 /* Code below copied from "up_silently_base" in "stack.c".
414 * It restores the frame set by the user before the "info threads"
415 * command. We have finished the info-threads display by switching
416 * back to the current thread. That switch has put us at the top
417 * of the stack (leaf frame).
418 */
419 counter = saved_frame_level;
420 cur_frame = find_relative_frame(selected_frame, &counter);
421 if (counter != 0)
422 {
423 /* Ooops, can't restore, tell user where we are. */
424 warning ("Couldn't restore frame in current thread, at frame 0");
425 print_stack_frame (selected_frame, -1, 0);
426 }
427 else
428 {
429 select_frame(cur_frame, saved_frame_level);
430 }
431
432 /* re-show current frame. */
433 show_stack_frame(cur_frame);
434}
435
436/* Switch from one thread to another. */
437
438static void
439switch_to_thread (pid)
440 int pid;
441{
442 if (pid == inferior_pid)
443 return;
444
445 inferior_pid = pid;
446 flush_cached_frames ();
447 registers_changed ();
448 stop_pc = read_pc();
449 select_frame (get_current_frame (), 0);
450}
451
452static void
453restore_current_thread (pid)
454 int pid;
455{
456 if (pid != inferior_pid)
457 {
458 switch_to_thread (pid);
459 print_stack_frame( get_current_frame(), 0, -1);
460 }
461}
462
463/* Apply a GDB command to a list of threads. List syntax is a whitespace
464 seperated list of numbers, or ranges, or the keyword `all'. Ranges consist
465 of two numbers seperated by a hyphen. Examples:
466
467 thread apply 1 2 7 4 backtrace Apply backtrace cmd to threads 1,2,7,4
468 thread apply 2-7 9 p foo(1) Apply p foo(1) cmd to threads 2->7 & 9
469 thread apply all p x/i $pc Apply x/i $pc cmd to all threads
470*/
471
472static void
473thread_apply_all_command (cmd, from_tty)
474 char *cmd;
475 int from_tty;
476{
477 struct thread_info *tp;
478 struct cleanup *old_chain;
479
480 if (cmd == NULL || *cmd == '\000')
481 error ("Please specify a command following the thread ID list");
482
483 old_chain = make_cleanup ((make_cleanup_func) restore_current_thread,
484 (void *) inferior_pid);
485
486 for (tp = thread_list; tp; tp = tp->next)
487 if (thread_alive (tp))
488 {
489 switch_to_thread (tp->pid);
490#ifdef HPUXHPPA
491 printf_filtered ("\nThread %d (%s):\n",
492 tp->num,
493 target_tid_to_str (inferior_pid));
494#else
495 printf_filtered ("\nThread %d (%s):\n", tp->num,
496 target_pid_to_str (inferior_pid));
497#endif
498 execute_command (cmd, from_tty);
499 }
500}
501
502static void
503thread_apply_command (tidlist, from_tty)
504 char *tidlist;
505 int from_tty;
506{
507 char *cmd;
508 char *p;
509 struct cleanup *old_chain;
510
511 if (tidlist == NULL || *tidlist == '\000')
512 error ("Please specify a thread ID list");
513
514 for (cmd = tidlist; *cmd != '\000' && !isalpha(*cmd); cmd++);
515
516 if (*cmd == '\000')
517 error ("Please specify a command following the thread ID list");
518
519 old_chain = make_cleanup ((make_cleanup_func) restore_current_thread,
520 (void *) inferior_pid);
521
522 while (tidlist < cmd)
523 {
524 struct thread_info *tp;
525 int start, end;
526
527 start = strtol (tidlist, &p, 10);
528 if (p == tidlist)
529 error ("Error parsing %s", tidlist);
530 tidlist = p;
531
532 while (*tidlist == ' ' || *tidlist == '\t')
533 tidlist++;
534
535 if (*tidlist == '-') /* Got a range of IDs? */
536 {
537 tidlist++; /* Skip the - */
538 end = strtol (tidlist, &p, 10);
539 if (p == tidlist)
540 error ("Error parsing %s", tidlist);
541 tidlist = p;
542
543 while (*tidlist == ' ' || *tidlist == '\t')
544 tidlist++;
545 }
546 else
547 end = start;
548
549 for (; start <= end; start++)
550 {
551 tp = find_thread_id (start);
552
553 if (!tp)
554 warning ("Unknown thread %d.", start);
555 else if (!thread_alive (tp))
556 warning ("Thread %d has terminated.", start);
557 else
558 {
559 switch_to_thread (tp->pid);
560#ifdef HPUXHPPA
561 printf_filtered ("\nThread %d (%s):\n", tp->num,
562 target_tid_to_str (inferior_pid));
563#else
564 printf_filtered ("\nThread %d (%s):\n", tp->num,
565 target_pid_to_str (inferior_pid));
566#endif
567 execute_command (cmd, from_tty);
568 }
569 }
570 }
571}
572
573/* Switch to the specified thread. Will dispatch off to thread_apply_command
574 if prefix of arg is `apply'. */
575
576static void
577thread_command (tidstr, from_tty)
578 char *tidstr;
579 int from_tty;
580{
581 int num;
582 struct thread_info *tp;
583
584 if (!tidstr)
585 {
586 /* Don't generate an error, just say which thread is current. */
587 if (target_has_stack)
588 printf_filtered ("[Current thread is %d (%s)]\n",
589 pid_to_thread_id(inferior_pid),
590#if defined(HPUXHPPA)
591 target_tid_to_str(inferior_pid)
592#else
593 target_pid_to_str(inferior_pid)
594#endif
595 );
596 else
597 error ("No stack.");
598 return;
599 }
600 num = atoi (tidstr);
601
602 tp = find_thread_id (num);
603
604 if (!tp)
605 error ("Thread ID %d not known. Use the \"info threads\" command to\n\
606see the IDs of currently known threads.", num);
607
608 if (!thread_alive (tp))
609 error ("Thread ID %d has terminated.\n", num);
610
611 switch_to_thread (tp->pid);
612
613 if (context_hook)
614 context_hook (num);
615
616 printf_filtered ("[Switching to thread %d (%s)]\n",
617 pid_to_thread_id (inferior_pid),
618#if defined(HPUXHPPA)
619 target_tid_to_str (inferior_pid)
620#else
621 target_pid_to_str (inferior_pid)
622#endif
623 );
624 print_stack_frame (selected_frame, selected_frame_level, 1);
625}
626
627/* Commands with a prefix of `thread'. */
628struct cmd_list_element *thread_cmd_list = NULL;
629
630void
631_initialize_thread ()
632{
633 static struct cmd_list_element *thread_apply_list = NULL;
c906108c
SS
634
635 add_info ("threads", info_threads_command,
636 "IDs of currently known threads.");
637
638 add_prefix_cmd ("thread", class_run, thread_command,
639 "Use this command to switch between threads.\n\
640The new thread ID must be currently known.", &thread_cmd_list, "thread ", 1,
641 &cmdlist);
642
643 add_prefix_cmd ("apply", class_run, thread_apply_command,
644 "Apply a command to a list of threads.",
645 &thread_apply_list, "apply ", 1, &thread_cmd_list);
646
647 add_cmd ("all", class_run, thread_apply_all_command,
648 "Apply a command to all threads.",
649 &thread_apply_list);
650
651 if (!xdb_commands)
652 add_com_alias ("t", "thread", class_run, 1);
653}
This page took 0.051826 seconds and 4 git commands to generate.