* gdb.server/ext-run.exp: Relax regexp for init program.
[deliverable/binutils-gdb.git] / gdb / linux-fork.c
CommitLineData
ac264b3b
MS
1/* GNU/Linux native-dependent code for debugging multiple forks.
2
9b254dd1 3 Copyright (C) 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
ac264b3b
MS
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
a9762ec7 9 the Free Software Foundation; either version 3 of the License, or
ac264b3b
MS
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
a9762ec7 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
ac264b3b
MS
19
20#include "defs.h"
21#include "inferior.h"
22#include "regcache.h"
23#include "gdbcmd.h"
24#include "infcall.h"
3e3b026f 25#include "objfiles.h"
791b663b 26#include "gdb_assert.h"
ac264b3b
MS
27#include "gdb_string.h"
28#include "linux-fork.h"
f973ed9c 29#include "linux-nat.h"
ac264b3b
MS
30
31#include <sys/ptrace.h>
3c61c145 32#include "gdb_wait.h"
ac264b3b 33#include <sys/param.h>
91c06669 34#include "gdb_dirent.h"
ac264b3b
MS
35#include <ctype.h>
36
37struct fork_info *fork_list;
38static int highest_fork_num;
39
40/* Prevent warning from -Wmissing-prototypes. */
41extern void _initialize_linux_fork (void);
42
43int detach_fork = 1; /* Default behavior is to detach
44 newly forked processes (legacy). */
45
46/* Fork list data structure: */
47struct fork_info
48{
49 struct fork_info *next;
50 ptid_t ptid;
51 int num; /* Convenient handle (GDB fork id) */
52 struct regcache *savedregs; /* Convenient for info fork, saves
53 having to actually switch contexts. */
54 int clobber_regs; /* True if we should restore saved regs. */
55 ULONGEST pc; /* PC for info fork. */
56 off_t *filepos; /* Set of open file descriptors' offsets. */
57 int maxfd;
58};
59
60/* Fork list methods: */
61
62extern int
63forks_exist_p (void)
64{
65 return (fork_list != NULL);
66}
67
68/* Add a fork to internal fork list.
69 Called from linux child_follow_fork. */
70
71extern struct fork_info *
72add_fork (pid_t pid)
73{
74 struct fork_info *fp;
75
56aac7e8 76 if (fork_list == NULL && pid != PIDGET (inferior_ptid))
ac264b3b
MS
77 {
78 /* Special case -- if this is the first fork in the list
79 (the list is hitherto empty), and if this new fork is
80 NOT the current inferior_ptid, then add inferior_ptid
81 first, as a special zeroeth fork id. */
82 highest_fork_num = -1;
83 add_fork (PIDGET (inferior_ptid)); /* safe recursion */
84 }
85
86 fp = XZALLOC (struct fork_info);
f973ed9c 87 fp->ptid = ptid_build (pid, pid, 0);
ac264b3b
MS
88 fp->num = ++highest_fork_num;
89 fp->next = fork_list;
90 fork_list = fp;
91 return fp;
92}
93
94static void
95free_fork (struct fork_info *fp)
96{
97 /* Notes on step-resume breakpoints: since this is a concern for
98 threads, let's convince ourselves that it's not a concern for
99 forks. There are two ways for a fork_info to be created. First,
100 by the checkpoint command, in which case we're at a gdb prompt
101 and there can't be any step-resume breakpoint. Second, by a fork
102 in the user program, in which case we *may* have stepped into the
103 fork call, but regardless of whether we follow the parent or the
104 child, we will return to the same place and the step-resume
105 breakpoint, if any, will take care of itself as usual. And
106 unlike threads, we do not save a private copy of the step-resume
107 breakpoint -- so we're OK. */
108
109 if (fp)
110 {
111 if (fp->savedregs)
112 regcache_xfree (fp->savedregs);
113 if (fp->filepos)
114 xfree (fp->filepos);
115 xfree (fp);
116 }
117}
118
119static void
120delete_fork (ptid_t ptid)
121{
122 struct fork_info *fp, *fpprev;
123
124 fpprev = NULL;
125
126 for (fp = fork_list; fp; fpprev = fp, fp = fp->next)
127 if (ptid_equal (fp->ptid, ptid))
128 break;
129
130 if (!fp)
131 return;
132
133 if (fpprev)
134 fpprev->next = fp->next;
135 else
136 fork_list = fp->next;
137
138 free_fork (fp);
139
140 /* Special case: if there is now only one process in the list,
141 and if it is (hopefully!) the current inferior_ptid, then
142 remove it, leaving the list empty -- we're now down to the
143 default case of debugging a single process. */
144 if (fork_list != NULL && fork_list->next == NULL &&
145 ptid_equal (fork_list->ptid, inferior_ptid))
146 {
147 /* Last fork -- delete from list and handle as solo process
148 (should be a safe recursion). */
149 delete_fork (inferior_ptid);
150 }
151}
152
153/* Find a fork_info by matching PTID. */
154static struct fork_info *
155find_fork_ptid (ptid_t ptid)
156{
157 struct fork_info *fp;
158
159 for (fp = fork_list; fp; fp = fp->next)
160 if (ptid_equal (fp->ptid, ptid))
161 return fp;
162
163 return NULL;
164}
165
166/* Find a fork_info by matching ID. */
167static struct fork_info *
168find_fork_id (int num)
169{
170 struct fork_info *fp;
171
172 for (fp = fork_list; fp; fp = fp->next)
173 if (fp->num == num)
174 return fp;
175
176 return NULL;
177}
178
179/* Find a fork_info by matching pid. */
180extern struct fork_info *
181find_fork_pid (pid_t pid)
182{
183 struct fork_info *fp;
184
185 for (fp = fork_list; fp; fp = fp->next)
186 if (pid == ptid_get_pid (fp->ptid))
187 return fp;
188
189 return NULL;
190}
191
192static ptid_t
193fork_id_to_ptid (int num)
194{
195 struct fork_info *fork = find_fork_id (num);
196 if (fork)
197 return fork->ptid;
198 else
199 return pid_to_ptid (-1);
200}
201
202static void
203init_fork_list (void)
204{
205 struct fork_info *fp, *fpnext;
206
207 if (!fork_list)
208 return;
209
210 for (fp = fork_list; fp; fp = fpnext)
211 {
212 fpnext = fp->next;
7f9f62ba 213 delete_inferior (ptid_get_pid (fp->ptid));
ac264b3b
MS
214 free_fork (fp);
215 }
216
217 fork_list = NULL;
218}
219
220/* Fork list <-> gdb interface. */
221
222/* Utility function for fork_load/fork_save.
223 Calls lseek in the (current) inferior process. */
224
225static off_t
226call_lseek (int fd, off_t offset, int whence)
227{
228 char exp[80];
229
230 snprintf (&exp[0], sizeof (exp), "lseek (%d, %ld, %d)",
231 fd, (long) offset, whence);
232 return (off_t) parse_and_eval_long (&exp[0]);
233}
234
235/* Load infrun state for the fork PTID. */
236
237static void
238fork_load_infrun_state (struct fork_info *fp)
239{
240 extern void nullify_last_target_wait_ptid ();
241 int i;
242
791b663b
DJ
243 inferior_ptid = fp->ptid;
244
f973ed9c
DJ
245 linux_nat_switch_fork (inferior_ptid);
246
ac264b3b 247 if (fp->savedregs && fp->clobber_regs)
594f7785 248 regcache_cpy (get_current_regcache (), fp->savedregs);
ac264b3b 249
791b663b
DJ
250 registers_changed ();
251 reinit_frame_cache ();
252
791b663b 253 stop_pc = read_pc ();
ac264b3b
MS
254 nullify_last_target_wait_ptid ();
255
256 /* Now restore the file positions of open file descriptors. */
257 if (fp->filepos)
258 {
259 for (i = 0; i <= fp->maxfd; i++)
260 if (fp->filepos[i] != (off_t) -1)
261 call_lseek (i, fp->filepos[i], SEEK_SET);
262 /* NOTE: I can get away with using SEEK_SET and SEEK_CUR because
263 this is native-only. If it ever has to be cross, we'll have
264 to rethink this. */
265 }
266}
267
268/* Save infrun state for the fork PTID.
269 Exported for use by linux child_follow_fork. */
270
271extern void
272fork_save_infrun_state (struct fork_info *fp, int clobber_regs)
273{
274 char path[MAXPATHLEN];
275 struct dirent *de;
276 DIR *d;
277
278 if (fp->savedregs)
279 regcache_xfree (fp->savedregs);
280
594f7785 281 fp->savedregs = regcache_dup (get_current_regcache ());
ac264b3b
MS
282 fp->clobber_regs = clobber_regs;
283 fp->pc = read_pc ();
284
285 if (clobber_regs)
286 {
287 /* Now save the 'state' (file position) of all open file descriptors.
288 Unfortunately fork does not take care of that for us... */
289 snprintf (path, MAXPATHLEN, "/proc/%ld/fd", (long) PIDGET (fp->ptid));
290 if ((d = opendir (path)) != NULL)
291 {
292 long tmp;
293
294 fp->maxfd = 0;
295 while ((de = readdir (d)) != NULL)
296 {
297 /* Count open file descriptors (actually find highest
298 numbered). */
299 tmp = strtol (&de->d_name[0], NULL, 10);
300 if (fp->maxfd < tmp)
301 fp->maxfd = tmp;
302 }
303 /* Allocate array of file positions. */
304 fp->filepos = xrealloc (fp->filepos,
305 (fp->maxfd + 1) * sizeof (*fp->filepos));
306
307 /* Initialize to -1 (invalid). */
308 for (tmp = 0; tmp <= fp->maxfd; tmp++)
309 fp->filepos[tmp] = -1;
310
311 /* Now find actual file positions. */
312 rewinddir (d);
313 while ((de = readdir (d)) != NULL)
314 if (isdigit (de->d_name[0]))
315 {
316 tmp = strtol (&de->d_name[0], NULL, 10);
317 fp->filepos[tmp] = call_lseek (tmp, 0, SEEK_CUR);
318 }
319 closedir (d);
320 }
321 }
322}
323
324/* Kill 'em all, let God sort 'em out... */
325
326extern void
327linux_fork_killall (void)
328{
329 /* Walk list and kill every pid. No need to treat the
330 current inferior_ptid as special (we do not return a
331 status for it) -- however any process may be a child
332 or a parent, so may get a SIGCHLD from a previously
333 killed child. Wait them all out. */
56aac7e8 334 struct fork_info *fp;
ac264b3b
MS
335 pid_t pid, ret;
336 int status;
337
56aac7e8
MS
338 for (fp = fork_list; fp; fp = fp->next)
339 {
340 pid = PIDGET (fp->ptid);
341 do {
4c28f408
PA
342 /* Use SIGKILL instead of PTRACE_KILL because the former works even
343 if the thread is running, while the later doesn't. */
344 kill (pid, SIGKILL);
56aac7e8
MS
345 ret = waitpid (pid, &status, 0);
346 /* We might get a SIGCHLD instead of an exit status. This is
347 aggravated by the first kill above - a child has just
348 died. MVS comment cut-and-pasted from linux-nat. */
349 } while (ret == pid && WIFSTOPPED (status));
350 }
351 init_fork_list (); /* Clear list, prepare to start fresh. */
ac264b3b
MS
352}
353
354/* The current inferior_ptid has exited, but there are other viable
355 forks to debug. Delete the exiting one and context-switch to the
356 first available. */
357
358extern void
359linux_fork_mourn_inferior (void)
360{
361 /* Wait just one more time to collect the inferior's exit status.
362 Do not check whether this succeeds though, since we may be
363 dealing with a process that we attached to. Such a process will
364 only report its exit status to its original parent. */
365 int status;
366
367 waitpid (ptid_get_pid (inferior_ptid), &status, 0);
368
369 /* OK, presumably inferior_ptid is the one who has exited.
370 We need to delete that one from the fork_list, and switch
371 to the next available fork. */
372 delete_fork (inferior_ptid);
7f9f62ba
PA
373 /* Delete process from GDB's inferior list. */
374 delete_inferior (ptid_get_pid (inferior_ptid));
791b663b
DJ
375
376 /* There should still be a fork - if there's only one left,
377 delete_fork won't remove it, because we haven't updated
378 inferior_ptid yet. */
379 gdb_assert (fork_list);
380
381 fork_load_infrun_state (fork_list);
382 printf_filtered (_("[Switching to %s]\n"),
383 target_pid_to_str (inferior_ptid));
384
385 /* If there's only one fork, switch back to non-fork mode. */
386 if (fork_list->next == NULL)
387 delete_fork (inferior_ptid);
ac264b3b
MS
388}
389
390/* Fork list <-> user interface. */
391
392static void
393delete_fork_command (char *args, int from_tty)
394{
395 ptid_t ptid;
396
397 if (!args || !*args)
398 error (_("Requires argument (fork/checkpoint id to delete)"));
399
400 ptid = fork_id_to_ptid (parse_and_eval_long (args));
401 if (ptid_equal (ptid, minus_one_ptid))
402 error (_("No such fork/checkpoint id, %s"), args);
403
404 if (ptid_equal (ptid, inferior_ptid))
405 error (_("Please switch to another fork/checkpoint before deleting the current one"));
406
1dce6535 407 if (ptrace (PTRACE_KILL, PIDGET (ptid), 0, 0))
ac264b3b
MS
408 error (_("Unable to kill pid %s"), target_tid_to_str (ptid));
409
410 if (from_tty)
411 printf_filtered (_("Killed %s\n"), target_pid_to_str (ptid));
412
413 delete_fork (ptid);
7f9f62ba
PA
414 /* Delete process from GDB's inferior list. */
415 delete_inferior (ptid_get_pid (ptid));
ac264b3b
MS
416}
417
418static void
419detach_fork_command (char *args, int from_tty)
420{
421 ptid_t ptid;
422
423 if (!args || !*args)
424 error (_("Requires argument (fork id to detach)"));
425
426 ptid = fork_id_to_ptid (parse_and_eval_long (args));
427 if (ptid_equal (ptid, minus_one_ptid))
428 error (_("No such fork id, %s"), args);
429
430 if (ptid_equal (ptid, inferior_ptid))
431 error (_("Please switch to another fork before detaching the current one"));
432
1dce6535 433 if (ptrace (PTRACE_DETACH, PIDGET (ptid), 0, 0))
ac264b3b
MS
434 error (_("Unable to detach %s"), target_pid_to_str (ptid));
435
436 if (from_tty)
437 printf_filtered (_("Detached %s\n"), target_pid_to_str (ptid));
438
439 delete_fork (ptid);
7f9f62ba
PA
440 /* Delete process from GDB's process table. */
441 detach_inferior (ptid_get_pid (ptid));
ac264b3b
MS
442}
443
444/* Print information about currently known forks. */
445
446static void
447info_forks_command (char *arg, int from_tty)
448{
449 struct frame_info *cur_frame;
450 struct symtab_and_line sal;
451 struct symtab *cur_symtab;
452 struct fork_info *fp;
453 int cur_line;
454 ULONGEST pc;
b8db102d
MS
455 int requested = -1;
456 struct fork_info *printed = NULL;
457
458 if (arg && *arg)
459 requested = (int) parse_and_eval_long (arg);
ac264b3b
MS
460
461 for (fp = fork_list; fp; fp = fp->next)
462 {
b8db102d
MS
463 if (requested > 0 && fp->num != requested)
464 continue;
465
466 printed = fp;
ac264b3b
MS
467 if (ptid_equal (fp->ptid, inferior_ptid))
468 {
469 printf_filtered ("* ");
470 pc = read_pc ();
471 }
472 else
473 {
474 printf_filtered (" ");
475 pc = fp->pc;
476 }
477 printf_filtered ("%d %s", fp->num, target_pid_to_str (fp->ptid));
478 if (fp->num == 0)
479 printf_filtered (_(" (main process)"));
480 printf_filtered (_(" at "));
ed49a04f 481 fputs_filtered (paddress (pc), gdb_stdout);
ac264b3b
MS
482
483 sal = find_pc_line (pc, 0);
484 if (sal.symtab)
485 {
486 char *tmp = strrchr (sal.symtab->filename, '/');
487
488 if (tmp)
489 printf_filtered (_(", file %s"), tmp + 1);
490 else
491 printf_filtered (_(", file %s"), sal.symtab->filename);
492 }
493 if (sal.line)
494 printf_filtered (_(", line %d"), sal.line);
495 if (!sal.symtab && !sal.line)
496 {
497 struct minimal_symbol *msym;
498
499 msym = lookup_minimal_symbol_by_pc (pc);
500 if (msym)
501 printf_filtered (", <%s>", SYMBOL_LINKAGE_NAME (msym));
502 }
503
504 putchar_filtered ('\n');
505 }
b8db102d
MS
506 if (printed == NULL)
507 {
508 if (requested > 0)
509 printf_filtered (_("No fork number %d.\n"), requested);
510 else
511 printf_filtered (_("No forks.\n"));
512 }
ac264b3b
MS
513}
514
515/* Save/restore mode variable 'detach_fork':
516 We need to temporarily take over this mode variable, while
517 preserving the user-specified state, and make sure that it
518 gets restored in case of error.
519
520 The int pointer that we use comes from the caller, so we can
521 be called more than once (even though currently we don't need to). */
522
523static void
524restore_detach_fork (void *arg)
525{
526 detach_fork = *(int *) arg;
527}
528
529static struct cleanup *
530save_detach_fork (int *saved_val)
531{
532 *saved_val = detach_fork;
533 return make_cleanup (restore_detach_fork, (void *) saved_val);
534}
535
536static void
537checkpoint_command (char *args, int from_tty)
538{
3e3b026f
UW
539 struct objfile *fork_objf;
540 struct gdbarch *gdbarch;
ac264b3b
MS
541 struct target_waitstatus last_target_waitstatus;
542 ptid_t last_target_ptid;
543 struct value *fork_fn = NULL, *ret;
544 struct fork_info *fp;
545 pid_t retpid;
546 struct cleanup *old_chain;
547 long i;
548 /* Make this temp var static, 'cause it's used in the error context. */
549 static int temp_detach_fork;
550
74960c60
VP
551 /* Remove breakpoints, so that they are not inserted
552 in the forked process. */
553 remove_breakpoints ();
554
ac264b3b
MS
555 /* Make the inferior fork, record its (and gdb's) state. */
556
557 if (lookup_minimal_symbol ("fork", NULL, NULL) != NULL)
3e3b026f 558 fork_fn = find_function_in_inferior ("fork", &fork_objf);
ac264b3b
MS
559 if (!fork_fn)
560 if (lookup_minimal_symbol ("_fork", NULL, NULL) != NULL)
3e3b026f 561 fork_fn = find_function_in_inferior ("fork", &fork_objf);
ac264b3b
MS
562 if (!fork_fn)
563 error (_("checkpoint: can't find fork function in inferior."));
564
3e3b026f
UW
565 gdbarch = get_objfile_arch (fork_objf);
566 ret = value_from_longest (builtin_type (gdbarch)->builtin_int, 0);
ac264b3b
MS
567 old_chain = save_detach_fork (&temp_detach_fork);
568 detach_fork = 0;
569 ret = call_function_by_hand (fork_fn, 0, &ret);
570 do_cleanups (old_chain);
571 if (!ret) /* Probably can't happen. */
572 error (_("checkpoint: call_function_by_hand returned null."));
573
574 retpid = value_as_long (ret);
575 get_last_target_status (&last_target_ptid, &last_target_waitstatus);
576 if (from_tty)
577 {
578 int parent_pid;
579
580 printf_filtered (_("checkpoint: fork returned pid %ld.\n"),
581 (long) retpid);
582 if (info_verbose)
583 {
584 parent_pid = ptid_get_lwp (last_target_ptid);
585 if (parent_pid == 0)
586 parent_pid = ptid_get_pid (last_target_ptid);
587 printf_filtered (_(" gdb says parent = %ld.\n"),
588 (long) parent_pid);
589 }
590 }
591
592 fp = find_fork_pid (retpid);
593 if (!fp)
594 error (_("Failed to find new fork"));
595 fork_save_infrun_state (fp, 1);
74960c60 596 insert_breakpoints ();
ac264b3b
MS
597}
598
599static void
600linux_fork_context (struct fork_info *newfp, int from_tty)
601{
602 /* Now we attempt to switch processes. */
603 struct fork_info *oldfp = find_fork_ptid (inferior_ptid);
604 ptid_t ptid;
605 int id, i;
606
607 if (!newfp)
608 error (_("No such fork/process"));
609
610 if (!oldfp)
791b663b 611 oldfp = add_fork (ptid_get_pid (inferior_ptid));
ac264b3b
MS
612
613 fork_save_infrun_state (oldfp, 1);
74960c60 614 remove_breakpoints ();
ac264b3b 615 fork_load_infrun_state (newfp);
74960c60 616 insert_breakpoints ();
ac264b3b
MS
617
618 printf_filtered (_("Switching to %s\n"),
619 target_pid_to_str (inferior_ptid));
620
621 print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC);
622}
623
624/* Switch inferior process (fork) context, by process id. */
625static void
626process_command (char *args, int from_tty)
627{
628 struct fork_info *fp;
629
630 if (!args || !*args)
631 error (_("Requires argument (process id to switch to)"));
632
633 if ((fp = find_fork_pid (parse_and_eval_long (args))) == NULL)
634 error (_("Not found: process id %s"), args);
635
636 linux_fork_context (fp, from_tty);
637}
638
639/* Switch inferior process (fork) context, by fork id. */
640static void
641fork_command (char *args, int from_tty)
642{
643 struct fork_info *fp;
644
645 if (!args || !*args)
646 error (_("Requires argument (fork id to switch to)"));
647
648 if ((fp = find_fork_id (parse_and_eval_long (args))) == NULL)
649 error (_("Not found: fork id %s"), args);
650
651 linux_fork_context (fp, from_tty);
652}
653
654/* Switch inferior process (fork) context, by checkpoint id. */
655static void
656restart_command (char *args, int from_tty)
657{
658 struct fork_info *fp;
659
660 if (!args || !*args)
661 error (_("Requires argument (checkpoint id to restart)"));
662
663 if ((fp = find_fork_id (parse_and_eval_long (args))) == NULL)
664 error (_("Not found: checkpoint id %s"), args);
665
666 linux_fork_context (fp, from_tty);
667}
668
669void
670_initialize_linux_fork (void)
671{
672 init_fork_list ();
673
674 /* Set/show detach-on-fork: user-settable mode. */
675
676 add_setshow_boolean_cmd ("detach-on-fork", class_obscure, &detach_fork, _("\
677Set whether gdb will detach the child of a fork."), _("\
678Show whether gdb will detach the child of a fork."), _("\
679Tells gdb whether to detach the child of a fork."),
680 NULL, NULL, &setlist, &showlist);
681
682 /* Set/show restart-auto-finish: user-settable count. Causes the
683 first "restart" of a fork to do some number of "finish" commands
684 before returning to user.
685
686 Useful because otherwise the virgin fork process will be stopped
687 somewhere in the un-interesting fork system call. */
688
689 /* Checkpoint command: create a fork of the inferior process
690 and set it aside for later debugging. */
691
692 add_com ("checkpoint", class_obscure, checkpoint_command, _("\
693Fork a duplicate process (experimental)."));
694
695 /* Restart command: restore the context of a specified fork
696 process. May be used for "program forks" as well as for
697 "debugger forks" (checkpoints). */
698
699 add_com ("restart", class_obscure, restart_command, _("\
700restart <n>: restore program context from a checkpoint.\n\
701Argument 'n' is checkpoint ID, as displayed by 'info checkpoints'."));
702
b8db102d 703 /* Delete checkpoint command: kill the process and remove it from
ac264b3b
MS
704 fork list. */
705
b8db102d
MS
706 add_cmd ("checkpoint", class_obscure, delete_fork_command, _("\
707Delete a fork/checkpoint (experimental)."),
708 &deletelist);
ac264b3b 709
f73adfeb 710 /* Detach checkpoint command: release the process to run independently,
ac264b3b
MS
711 and remove it from the fork list. */
712
f73adfeb
AS
713 add_cmd ("checkpoint", class_obscure, detach_fork_command, _("\
714Detach from a fork/checkpoint (experimental)."),
715 &detachlist);
ac264b3b
MS
716
717 /* Info checkpoints command: list all forks/checkpoints
718 currently under gdb's control. */
719
720 add_info ("checkpoints", info_forks_command,
721 _("IDs of currently known forks/checkpoints."));
722
723 /* Command aliases (let "fork" and "checkpoint" be used
724 interchangeably). */
725
b8db102d 726 add_alias_cmd ("fork", "checkpoint", class_obscure, 1, &deletelist);
f73adfeb 727 add_alias_cmd ("fork", "checkpoint", class_obscure, 1, &detachlist);
ac264b3b
MS
728 add_info_alias ("forks", "checkpoints", 0);
729
730 /* "fork <n>" (by analogy to "thread <n>"). */
731 add_com ("fork", class_obscure, fork_command, _("\
732fork <n>: Switch between forked processes.\n\
733Argument 'n' is fork ID, as displayed by 'info forks'."));
734
735 /* "process <proc id>" as opposed to "fork <fork id>". */
736 add_com ("process", class_obscure, process_command, _("\
737process <pid>: Switch between forked processes.\n\
738Argument 'pid' is process ID, as displayed by 'info forks' or 'shell ps'."));
739}
This page took 0.252544 seconds and 4 git commands to generate.