* objdump.c (SFILE): Add size field.
[deliverable/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, 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
40 struct 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
58
59
60 static struct target_thread_vector *target_thread_functions;
61
62 int
63 target_find_new_threads ()
64 {
65 int retval = 0;
66 if (target_thread_functions &&
67 target_thread_functions->find_new_threads)
68 retval = (*(target_thread_functions->find_new_threads)) ();
69 return retval; /* no support */
70 }
71
72
73 int
74 target_get_thread_info PARAMS ((
75 gdb_threadref * ref,
76 int selection, /* FIXME: Selection */
77 struct gdb_ext_thread_info * info));
78
79 int
80 target_get_thread_info (ref, selection, info)
81
82 gdb_threadref *ref;
83 int selection;
84 /* FIXME: Selection */
85 struct gdb_ext_thread_info *info;
86
87 {
88 int retval = 0;
89 if (target_thread_functions
90 && target_thread_functions->get_thread_info)
91 retval = (*(target_thread_functions->get_thread_info)) (ref, selection, info);
92 return retval;
93 }
94
95
96 /* It is possible that these bind and unbinf functions implement a
97 stack the interface allows it, but its not implemented that way
98 */
99
100
101 void
102 bind_target_thread_vector (vec)
103 struct target_thread_vector *vec;
104 {
105 target_thread_functions = vec;
106 }
107 /* Prototypes for exported functions. */
108
109 struct target_thread_vector *
110 unbind_target_thread_vector ()
111 {
112 struct target_thread_vector *retval;
113 retval = target_thread_functions;
114 target_thread_functions = 0;
115 return retval;
116 } /* unbind_target_thread-vector */
117
118 void _initialize_thread PARAMS ((void));
119
120
121 /* Prototypes for local functions. */
122 /* If the host has threads, the host machine definition may
123 set this macro. But, for remote thread debugging, it gets more
124 complex and setting macros does not bind to the various target
125 dependent methods well. So, we use the vector target_thread_functions
126 */
127 #if !defined(FIND_NEW_THREADS)
128 #define FIND_NEW_THREADS target_find_new_threads
129 #endif
130
131 static struct thread_info *thread_list = NULL;
132 static int highest_thread_num;
133
134 static void
135 thread_command PARAMS ((char * tidstr, int from_tty));
136 static void
137 prune_threads PARAMS ((void));
138
139 static void
140 switch_to_thread PARAMS ((int pid));
141
142 static struct thread_info *
143 find_thread_id PARAMS ((int num));
144
145 static void
146 info_threads_command PARAMS ((char *, int));
147
148 static void
149 restore_current_thread PARAMS ((int));
150
151 static void
152 thread_apply_all_command PARAMS ((char *, int));
153
154 static void
155 thread_apply_command PARAMS ((char *, int));
156
157 static void info_threads_command PARAMS ((char *, int));
158
159 static void restore_current_thread PARAMS ((int));
160
161 static void thread_apply_all_command PARAMS ((char *, int));
162
163 static void thread_apply_command PARAMS ((char *, int));
164
165 static int thread_alive PARAMS ((struct thread_info *));
166
167 void
168 init_thread_list ()
169 {
170 struct thread_info *tp, *tpnext;
171
172 if (!thread_list)
173 return;
174
175 for (tp = thread_list; tp; tp = tpnext)
176 {
177 tpnext = tp->next;
178 free (tp);
179 }
180
181 thread_list = NULL;
182 highest_thread_num = 0;
183 }
184
185 void
186 add_thread (pid)
187 int pid;
188 {
189 struct thread_info *tp;
190
191 tp = (struct thread_info *) xmalloc (sizeof (struct thread_info));
192
193 tp->pid = pid;
194 tp->num = ++highest_thread_num;
195 tp->prev_pc = 0;
196 tp->prev_func_start = 0;
197 tp->prev_func_name = NULL;
198 tp->step_range_start = 0;
199 tp->step_range_end = 0;
200 tp->step_frame_address =0;
201 tp->step_resume_breakpoint = 0;
202 tp->through_sigtramp_breakpoint = 0;
203 tp->handling_longjmp = 0;
204 tp->trap_expected = 0;
205 tp->another_trap = 0;
206 tp->next = thread_list;
207 thread_list = tp;
208 }
209
210 void
211 delete_thread (pid)
212 int pid;
213 {
214 struct thread_info *tp, *tpprev;
215
216 tpprev = NULL;
217
218 for (tp = thread_list; tp; tpprev = tp, tp = tp->next)
219 if (tp->pid == pid)
220 break;
221
222 if (!tp)
223 return;
224
225 if (tpprev)
226 tpprev->next = tp->next;
227 else
228 thread_list = tp->next;
229
230 free (tp);
231
232 return;
233 }
234
235 static struct thread_info *
236 find_thread_id (num)
237 int num;
238 {
239 struct thread_info *tp;
240
241 for (tp = thread_list; tp; tp = tp->next)
242 if (tp->num == num)
243 return tp;
244
245 return NULL;
246 }
247
248 int
249 valid_thread_id (num)
250 int num;
251 {
252 struct thread_info *tp;
253
254 for (tp = thread_list; tp; tp = tp->next)
255 if (tp->num == num)
256 return 1;
257
258 return 0;
259 }
260
261 int
262 pid_to_thread_id (pid)
263 int pid;
264 {
265 struct thread_info *tp;
266
267 for (tp = thread_list; tp; tp = tp->next)
268 if (tp->pid == pid)
269 return tp->num;
270
271 return 0;
272 }
273
274 int
275 thread_id_to_pid (num)
276 int num;
277 {
278 struct thread_info *thread = find_thread_id (num);
279 if (thread)
280 return thread->pid;
281 else
282 return -1;
283 }
284
285 int
286 in_thread_list (pid)
287 int pid;
288 {
289 struct thread_info *tp;
290
291 for (tp = thread_list; tp; tp = tp->next)
292 if (tp->pid == pid)
293 return 1;
294
295 return 0; /* Never heard of 'im */
296 }
297
298 /* Load infrun state for the thread PID. */
299
300 void load_infrun_state (pid, prev_pc, prev_func_start, prev_func_name,
301 trap_expected, step_resume_breakpoint,
302 through_sigtramp_breakpoint, step_range_start,
303 step_range_end, step_frame_address,
304 handling_longjmp, another_trap)
305 int pid;
306 CORE_ADDR *prev_pc;
307 CORE_ADDR *prev_func_start;
308 char **prev_func_name;
309 int *trap_expected;
310 struct breakpoint **step_resume_breakpoint;
311 struct breakpoint **through_sigtramp_breakpoint;
312 CORE_ADDR *step_range_start;
313 CORE_ADDR *step_range_end;
314 CORE_ADDR *step_frame_address;
315 int *handling_longjmp;
316 int *another_trap;
317 {
318 struct thread_info *tp;
319
320 /* If we can't find the thread, then we're debugging a single threaded
321 process. No need to do anything in that case. */
322 tp = find_thread_id (pid_to_thread_id (pid));
323 if (tp == NULL)
324 return;
325
326 *prev_pc = tp->prev_pc;
327 *prev_func_start = tp->prev_func_start;
328 *prev_func_name = tp->prev_func_name;
329 *step_resume_breakpoint = tp->step_resume_breakpoint;
330 *step_range_start = tp->step_range_start;
331 *step_range_end = tp->step_range_end;
332 *step_frame_address = tp->step_frame_address;
333 *through_sigtramp_breakpoint = tp->through_sigtramp_breakpoint;
334 *handling_longjmp = tp->handling_longjmp;
335 *trap_expected = tp->trap_expected;
336 *another_trap = tp->another_trap;
337 }
338
339 /* Save infrun state for the thread PID. */
340
341 void save_infrun_state (pid, prev_pc, prev_func_start, prev_func_name,
342 trap_expected, step_resume_breakpoint,
343 through_sigtramp_breakpoint, step_range_start,
344 step_range_end, step_frame_address,
345 handling_longjmp, another_trap)
346 int pid;
347 CORE_ADDR prev_pc;
348 CORE_ADDR prev_func_start;
349 char *prev_func_name;
350 int trap_expected;
351 struct breakpoint *step_resume_breakpoint;
352 struct breakpoint *through_sigtramp_breakpoint;
353 CORE_ADDR step_range_start;
354 CORE_ADDR step_range_end;
355 CORE_ADDR step_frame_address;
356 int handling_longjmp;
357 int another_trap;
358 {
359 struct thread_info *tp;
360
361 /* If we can't find the thread, then we're debugging a single-threaded
362 process. Nothing to do in that case. */
363 tp = find_thread_id (pid_to_thread_id (pid));
364 if (tp == NULL)
365 return;
366
367 tp->prev_pc = prev_pc;
368 tp->prev_func_start = prev_func_start;
369 tp->prev_func_name = prev_func_name;
370 tp->step_resume_breakpoint = step_resume_breakpoint;
371 tp->step_range_start = step_range_start;
372 tp->step_range_end = step_range_end;
373 tp->step_frame_address = step_frame_address;
374 tp->through_sigtramp_breakpoint = through_sigtramp_breakpoint;
375 tp->handling_longjmp = handling_longjmp;
376 tp->trap_expected = trap_expected;
377 tp->another_trap = another_trap;
378 }
379
380 /* Return true if TP is an active thread. */
381 static int
382 thread_alive (tp)
383 struct thread_info *tp;
384 {
385 if (tp->pid == -1)
386 return 0;
387 if (! target_thread_alive (tp->pid))
388 {
389 tp->pid = -1; /* Mark it as dead */
390 return 0;
391 }
392 return 1;
393 }
394
395 static void
396 prune_threads ()
397 {
398 struct thread_info *tp, *tpprev, *next;
399
400 tpprev = 0;
401 for (tp = thread_list; tp; tp = next)
402 {
403 next = tp->next;
404 if (!thread_alive (tp))
405 {
406 if (tpprev)
407 tpprev->next = next;
408 else
409 thread_list = next;
410 free (tp);
411 }
412 else
413 tpprev = tp;
414 }
415 }
416
417 /* Print information about currently known threads */
418
419 static void
420 info_threads_command (arg, from_tty)
421 char *arg;
422 int from_tty;
423 {
424 struct thread_info *tp;
425 int current_pid = inferior_pid;
426
427 /* Avoid coredumps which would happen if we tried to access a NULL
428 selected_frame. */
429 if (!target_has_stack) error ("No stack.");
430
431 prune_threads ();
432 #if defined(FIND_NEW_THREADS)
433 FIND_NEW_THREADS ();
434 #endif
435
436 for (tp = thread_list; tp; tp = tp->next)
437 {
438 if (tp->pid == current_pid)
439 printf_filtered ("* ");
440 else
441 printf_filtered (" ");
442
443 printf_filtered ("%d %s ", tp->num, target_pid_to_str (tp->pid));
444
445 switch_to_thread (tp->pid);
446 if (selected_frame)
447 print_stack_frame (selected_frame, -1, 0);
448 else
449 printf_filtered ("[No stack.]\n");
450 }
451
452 switch_to_thread (current_pid);
453 }
454
455 /* Switch from one thread to another. */
456
457 static void
458 switch_to_thread (pid)
459 int pid;
460 {
461 if (pid == inferior_pid)
462 return;
463
464 inferior_pid = pid;
465 flush_cached_frames ();
466 registers_changed ();
467 stop_pc = read_pc();
468 select_frame (get_current_frame (), 0);
469 }
470
471 static void
472 restore_current_thread (pid)
473 int pid;
474 {
475 if (pid != inferior_pid)
476 switch_to_thread (pid);
477 }
478
479 /* Apply a GDB command to a list of threads. List syntax is a whitespace
480 seperated list of numbers, or ranges, or the keyword `all'. Ranges consist
481 of two numbers seperated by a hyphen. Examples:
482
483 thread apply 1 2 7 4 backtrace Apply backtrace cmd to threads 1,2,7,4
484 thread apply 2-7 9 p foo(1) Apply p foo(1) cmd to threads 2->7 & 9
485 thread apply all p x/i $pc Apply x/i $pc cmd to all threads
486 */
487
488 static void
489 thread_apply_all_command (cmd, from_tty)
490 char *cmd;
491 int from_tty;
492 {
493 struct thread_info *tp;
494 struct cleanup *old_chain;
495
496 if (cmd == NULL || *cmd == '\000')
497 error ("Please specify a command following the thread ID list");
498
499 old_chain = make_cleanup ((make_cleanup_func) restore_current_thread,
500 (void *) inferior_pid);
501
502 for (tp = thread_list; tp; tp = tp->next)
503 if (thread_alive (tp))
504 {
505 switch_to_thread (tp->pid);
506 printf_filtered ("\nThread %d (%s):\n", tp->num,
507 target_pid_to_str (inferior_pid));
508 execute_command (cmd, from_tty);
509 }
510 }
511
512 static void
513 thread_apply_command (tidlist, from_tty)
514 char *tidlist;
515 int from_tty;
516 {
517 char *cmd;
518 char *p;
519 struct cleanup *old_chain;
520
521 if (tidlist == NULL || *tidlist == '\000')
522 error ("Please specify a thread ID list");
523
524 for (cmd = tidlist; *cmd != '\000' && !isalpha(*cmd); cmd++);
525
526 if (*cmd == '\000')
527 error ("Please specify a command following the thread ID list");
528
529 old_chain = make_cleanup ((make_cleanup_func) restore_current_thread,
530 (void *) inferior_pid);
531
532 while (tidlist < cmd)
533 {
534 struct thread_info *tp;
535 int start, end;
536
537 start = strtol (tidlist, &p, 10);
538 if (p == tidlist)
539 error ("Error parsing %s", tidlist);
540 tidlist = p;
541
542 while (*tidlist == ' ' || *tidlist == '\t')
543 tidlist++;
544
545 if (*tidlist == '-') /* Got a range of IDs? */
546 {
547 tidlist++; /* Skip the - */
548 end = strtol (tidlist, &p, 10);
549 if (p == tidlist)
550 error ("Error parsing %s", tidlist);
551 tidlist = p;
552
553 while (*tidlist == ' ' || *tidlist == '\t')
554 tidlist++;
555 }
556 else
557 end = start;
558
559 for (; start <= end; start++)
560 {
561 tp = find_thread_id (start);
562
563 if (!tp)
564 warning ("Unknown thread %d.", start);
565 else if (!thread_alive (tp))
566 warning ("Thread %d has terminated.", start);
567 else
568 {
569 switch_to_thread (tp->pid);
570 printf_filtered ("\nThread %d (%s):\n", tp->num,
571 target_pid_to_str (inferior_pid));
572 execute_command (cmd, from_tty);
573 }
574 }
575 }
576 }
577
578 /* Switch to the specified thread. Will dispatch off to thread_apply_command
579 if prefix of arg is `apply'. */
580
581 static void
582 thread_command (tidstr, from_tty)
583 char *tidstr;
584 int from_tty;
585 {
586 int num;
587 struct thread_info *tp;
588
589 if (!tidstr)
590 error ("Please specify a thread ID. Use the \"info threads\" command to\n\
591 see the IDs of currently known threads.");
592
593 num = atoi (tidstr);
594
595 tp = find_thread_id (num);
596
597 if (!tp)
598 error ("Thread ID %d not known. Use the \"info threads\" command to\n\
599 see the IDs of currently known threads.", num);
600
601 if (!thread_alive (tp))
602 error ("Thread ID %d has terminated.\n", num);
603
604 switch_to_thread (tp->pid);
605 if (context_hook)
606 context_hook (num);
607 printf_filtered ("[Switching to %s]\n", target_pid_to_str (inferior_pid));
608 print_stack_frame (selected_frame, selected_frame_level, 1);
609 }
610
611 /* Commands with a prefix of `thread'. */
612 struct cmd_list_element *thread_cmd_list = NULL;
613
614 void
615 _initialize_thread ()
616 {
617 static struct cmd_list_element *thread_apply_list = NULL;
618 extern struct cmd_list_element *cmdlist;
619
620 add_info ("threads", info_threads_command,
621 "IDs of currently known threads.");
622
623 add_prefix_cmd ("thread", class_run, thread_command,
624 "Use this command to switch between threads.\n\
625 The new thread ID must be currently known.", &thread_cmd_list, "thread ", 1,
626 &cmdlist);
627
628 add_prefix_cmd ("apply", class_run, thread_apply_command,
629 "Apply a command to a list of threads.",
630 &thread_apply_list, "apply ", 1, &thread_cmd_list);
631
632 add_cmd ("all", class_run, thread_apply_all_command,
633 "Apply a command to all threads.",
634 &thread_apply_list);
635
636 add_com_alias ("t", "thread", class_run, 1);
637 }
This page took 0.043121 seconds and 4 git commands to generate.