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