Updated copyright notices for most files.
[external/binutils.git] / gdb / linux-fork.c
1 /* GNU/Linux native-dependent code for debugging multiple forks.
2
3    Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
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
9    the Free Software Foundation; either version 3 of the License, or
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
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19
20 #include "defs.h"
21 #include "inferior.h"
22 #include "regcache.h"
23 #include "gdbcmd.h"
24 #include "infcall.h"
25 #include "objfiles.h"
26 #include "gdb_assert.h"
27 #include "gdb_string.h"
28 #include "linux-fork.h"
29 #include "linux-nat.h"
30
31 #include <sys/ptrace.h>
32 #include "gdb_wait.h"
33 #include <sys/param.h>
34 #include "gdb_dirent.h"
35 #include <ctype.h>
36
37 struct fork_info *fork_list;
38 static int highest_fork_num;
39
40 /* Prevent warning from -Wmissing-prototypes.  */
41 extern void _initialize_linux_fork (void);
42
43 int detach_fork = 1;            /* Default behavior is to detach
44                                    newly forked processes (legacy).  */
45
46 /* Fork list data structure:  */
47 struct 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
62 extern int
63 forks_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
71 extern struct fork_info *
72 add_fork (pid_t pid)
73 {
74   struct fork_info *fp;
75
76   if (fork_list == NULL && pid != PIDGET (inferior_ptid))
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);
87   fp->ptid = ptid_build (pid, pid, 0);
88   fp->num = ++highest_fork_num;
89   fp->next = fork_list;
90   fork_list = fp;
91   return fp;
92 }
93
94 static void
95 free_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
119 static void
120 delete_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.  */
154 static struct fork_info *
155 find_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.  */
167 static struct fork_info *
168 find_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.  */
180 extern struct fork_info *
181 find_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
192 static ptid_t
193 fork_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
202 static void
203 init_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;
213       delete_inferior (ptid_get_pid (fp->ptid));
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
225 static off_t
226 call_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
237 static void
238 fork_load_infrun_state (struct fork_info *fp)
239 {
240   extern void nullify_last_target_wait_ptid ();
241   int i;
242
243   inferior_ptid = fp->ptid;
244
245   linux_nat_switch_fork (inferior_ptid);
246
247   if (fp->savedregs && fp->clobber_regs)
248     regcache_cpy (get_current_regcache (), fp->savedregs);
249
250   registers_changed ();
251   reinit_frame_cache ();
252
253   stop_pc = read_pc ();
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
271 extern void
272 fork_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
281   fp->savedregs = regcache_dup (get_current_regcache ());
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
326 extern void
327 linux_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.  */
334   struct fork_info *fp;
335   pid_t pid, ret;
336   int status;
337
338   for (fp = fork_list; fp; fp = fp->next)
339     {
340       pid = PIDGET (fp->ptid);
341       do {
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);
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.  */
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
358 extern void
359 linux_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);
373   /* Delete process from GDB's inferior list.  */
374   delete_inferior (ptid_get_pid (inferior_ptid));
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);
388 }
389
390 /* The current inferior_ptid is being detached, but there are other
391    viable forks to debug.  Detach and delete it and context-switch to
392    the first available.  */
393
394 extern void
395 linux_fork_detach (char *args, int from_tty)
396 {
397   /* OK, inferior_ptid is the one we are detaching from.  We need to
398      delete it from the fork_list, and switch to the next available
399      fork.  */
400
401   if (ptrace (PTRACE_DETACH, PIDGET (inferior_ptid), 0, 0))
402     error (_("Unable to detach %s"), target_pid_to_str (inferior_ptid));
403
404   delete_fork (inferior_ptid);
405   /* Delete process from GDB's inferior list.  */
406   delete_inferior (ptid_get_pid (inferior_ptid));
407
408   /* There should still be a fork - if there's only one left,
409      delete_fork won't remove it, because we haven't updated
410      inferior_ptid yet.  */
411   gdb_assert (fork_list);
412
413   fork_load_infrun_state (fork_list);
414
415   if (from_tty)
416     printf_filtered (_("[Switching to %s]\n"),
417                      target_pid_to_str (inferior_ptid));
418
419   /* If there's only one fork, switch back to non-fork mode.  */
420   if (fork_list->next == NULL)
421     delete_fork (inferior_ptid);
422 }
423
424 /* Fork list <-> user interface.  */
425
426 static void
427 delete_fork_command (char *args, int from_tty)
428 {
429   ptid_t ptid;
430
431   if (!args || !*args)
432     error (_("Requires argument (fork/checkpoint id to delete)"));
433
434   ptid = fork_id_to_ptid (parse_and_eval_long (args));
435   if (ptid_equal (ptid, minus_one_ptid))
436     error (_("No such fork/checkpoint id, %s"), args);
437
438   if (ptid_equal (ptid, inferior_ptid))
439     error (_("Please switch to another fork/checkpoint before deleting the current one"));
440
441   if (ptrace (PTRACE_KILL, PIDGET (ptid), 0, 0))
442     error (_("Unable to kill pid %s"), target_tid_to_str (ptid));
443
444   if (from_tty)
445     printf_filtered (_("Killed %s\n"), target_pid_to_str (ptid));
446
447   delete_fork (ptid);
448   /* Delete process from GDB's inferior list.  */
449   delete_inferior (ptid_get_pid (ptid));
450 }
451
452 static void
453 detach_fork_command (char *args, int from_tty)
454 {
455   ptid_t ptid;
456
457   if (!args || !*args)
458     error (_("Requires argument (fork id to detach)"));
459
460   ptid = fork_id_to_ptid (parse_and_eval_long (args));
461   if (ptid_equal (ptid, minus_one_ptid))
462     error (_("No such fork id, %s"), args);
463
464   if (ptid_equal (ptid, inferior_ptid))
465     error (_("Please switch to another fork before detaching the current one"));
466
467   if (ptrace (PTRACE_DETACH, PIDGET (ptid), 0, 0))
468     error (_("Unable to detach %s"), target_pid_to_str (ptid));
469
470   if (from_tty)
471     printf_filtered (_("Detached %s\n"), target_pid_to_str (ptid));
472
473   delete_fork (ptid);
474   /* Delete process from GDB's process table.  */
475   detach_inferior (ptid_get_pid (ptid));
476 }
477
478 /* Print information about currently known forks.  */
479
480 static void
481 info_forks_command (char *arg, int from_tty)
482 {
483   struct frame_info *cur_frame;
484   struct symtab_and_line sal;
485   struct symtab *cur_symtab;
486   struct fork_info *fp;
487   int cur_line;
488   ULONGEST pc;
489   int requested = -1;
490   struct fork_info *printed = NULL;
491
492   if (arg && *arg)
493     requested = (int) parse_and_eval_long (arg);
494
495   for (fp = fork_list; fp; fp = fp->next)
496     {
497       if (requested > 0 && fp->num != requested)
498         continue;
499
500       printed = fp;
501       if (ptid_equal (fp->ptid, inferior_ptid))
502         {
503           printf_filtered ("* ");
504           pc = read_pc ();
505         }
506       else
507         {
508           printf_filtered ("  ");
509           pc = fp->pc;
510         }
511       printf_filtered ("%d %s", fp->num, target_pid_to_str (fp->ptid));
512       if (fp->num == 0)
513         printf_filtered (_(" (main process)"));
514       printf_filtered (_(" at "));
515       fputs_filtered (paddress (pc), gdb_stdout);
516
517       sal = find_pc_line (pc, 0);
518       if (sal.symtab)
519         {
520           char *tmp = strrchr (sal.symtab->filename, '/');
521
522           if (tmp)
523             printf_filtered (_(", file %s"), tmp + 1);
524           else
525             printf_filtered (_(", file %s"), sal.symtab->filename);
526         }
527       if (sal.line)
528         printf_filtered (_(", line %d"), sal.line);
529       if (!sal.symtab && !sal.line)
530         {
531           struct minimal_symbol *msym;
532
533           msym = lookup_minimal_symbol_by_pc (pc);
534           if (msym)
535             printf_filtered (", <%s>", SYMBOL_LINKAGE_NAME (msym));
536         }
537
538       putchar_filtered ('\n');
539     }
540   if (printed == NULL)
541     {
542       if (requested > 0)
543         printf_filtered (_("No fork number %d.\n"), requested);
544       else
545         printf_filtered (_("No forks.\n"));
546     }
547 }
548
549 /* Save/restore mode variable 'detach_fork':
550    We need to temporarily take over this mode variable, while
551    preserving the user-specified state, and make sure that it 
552    gets restored in case of error.
553
554    The int pointer that we use comes from the caller, so we can
555    be called more than once (even though currently we don't need to).  */
556
557 static void 
558 restore_detach_fork (void *arg)
559 {
560   detach_fork = *(int *) arg;
561 }
562
563 static struct cleanup *
564 save_detach_fork (int *saved_val)
565 {
566   *saved_val = detach_fork;
567   return make_cleanup (restore_detach_fork, (void *) saved_val);
568 }
569
570 static void
571 checkpoint_command (char *args, int from_tty)
572 {
573   struct objfile *fork_objf;
574   struct gdbarch *gdbarch;
575   struct target_waitstatus last_target_waitstatus;
576   ptid_t last_target_ptid;
577   struct value *fork_fn = NULL, *ret;
578   struct fork_info *fp;
579   pid_t retpid;
580   struct cleanup *old_chain;
581   long i;
582   /* Make this temp var static, 'cause it's used in the error context.  */
583   static int temp_detach_fork;
584
585   /* Remove breakpoints, so that they are not inserted
586      in the forked process.  */
587   remove_breakpoints ();
588
589   /* Make the inferior fork, record its (and gdb's) state.  */
590
591   if (lookup_minimal_symbol ("fork", NULL, NULL) != NULL)
592     fork_fn = find_function_in_inferior ("fork", &fork_objf);
593   if (!fork_fn)
594     if (lookup_minimal_symbol ("_fork", NULL, NULL) != NULL)
595       fork_fn = find_function_in_inferior ("fork", &fork_objf);
596   if (!fork_fn)
597     error (_("checkpoint: can't find fork function in inferior."));
598
599   gdbarch = get_objfile_arch (fork_objf);
600   ret = value_from_longest (builtin_type (gdbarch)->builtin_int, 0);
601   old_chain = save_detach_fork (&temp_detach_fork);
602   detach_fork = 0;
603   ret = call_function_by_hand (fork_fn, 0, &ret);
604   do_cleanups (old_chain);
605   if (!ret)     /* Probably can't happen.  */
606     error (_("checkpoint: call_function_by_hand returned null."));
607
608   retpid = value_as_long (ret);
609   get_last_target_status (&last_target_ptid, &last_target_waitstatus);
610   if (from_tty)
611     {
612       int parent_pid;
613
614       printf_filtered (_("checkpoint: fork returned pid %ld.\n"), 
615                        (long) retpid);
616       if (info_verbose)
617         {
618           parent_pid = ptid_get_lwp (last_target_ptid);
619           if (parent_pid == 0)
620             parent_pid = ptid_get_pid (last_target_ptid);
621           printf_filtered (_("   gdb says parent = %ld.\n"), 
622                            (long) parent_pid);
623         }
624     }
625
626   fp = find_fork_pid (retpid);
627   if (!fp)
628     error (_("Failed to find new fork"));
629   fork_save_infrun_state (fp, 1);
630   insert_breakpoints ();
631 }
632
633 static void
634 linux_fork_context (struct fork_info *newfp, int from_tty)
635 {
636   /* Now we attempt to switch processes.  */
637   struct fork_info *oldfp;
638   ptid_t ptid;
639   int id, i;
640
641   gdb_assert (newfp != NULL);
642
643   oldfp = find_fork_ptid (inferior_ptid);
644   gdb_assert (oldfp != NULL);
645
646   fork_save_infrun_state (oldfp, 1);
647   remove_breakpoints ();
648   fork_load_infrun_state (newfp);
649   insert_breakpoints ();
650
651   printf_filtered (_("Switching to %s\n"), 
652                    target_pid_to_str (inferior_ptid));
653
654   print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC);
655 }
656
657 /* Switch inferior process (fork) context, by process id.  */
658 static void
659 process_command (char *args, int from_tty)
660 {
661   struct fork_info *fp;
662
663   if (!args || !*args)
664     error (_("Requires argument (process id to switch to)"));
665
666   if ((fp = find_fork_pid (parse_and_eval_long (args))) == NULL)
667     error (_("Not found: process id %s"), args);
668
669   linux_fork_context (fp, from_tty);
670 }
671
672 /* Switch inferior process (fork) context, by fork id.  */
673 static void
674 fork_command (char *args, int from_tty)
675 {
676   struct fork_info *fp;
677
678   if (!args || !*args)
679     error (_("Requires argument (fork id to switch to)"));
680
681   if ((fp = find_fork_id (parse_and_eval_long (args))) == NULL)
682     error (_("Not found: fork id %s"), args);
683
684   linux_fork_context (fp, from_tty);
685 }
686
687 /* Switch inferior process (fork) context, by checkpoint id.  */
688 static void
689 restart_command (char *args, int from_tty)
690 {
691   struct fork_info *fp;
692
693   if (!args || !*args)
694     error (_("Requires argument (checkpoint id to restart)"));
695
696   if ((fp = find_fork_id (parse_and_eval_long (args))) == NULL)
697     error (_("Not found: checkpoint id %s"), args);
698
699   linux_fork_context (fp, from_tty);
700 }
701
702 void
703 _initialize_linux_fork (void)
704 {
705   init_fork_list ();
706
707   /* Set/show detach-on-fork: user-settable mode.  */
708
709   add_setshow_boolean_cmd ("detach-on-fork", class_obscure, &detach_fork, _("\
710 Set whether gdb will detach the child of a fork."), _("\
711 Show whether gdb will detach the child of a fork."), _("\
712 Tells gdb whether to detach the child of a fork."), 
713                            NULL, NULL, &setlist, &showlist);
714
715   /* Set/show restart-auto-finish: user-settable count.  Causes the
716      first "restart" of a fork to do some number of "finish" commands
717      before returning to user.
718
719      Useful because otherwise the virgin fork process will be stopped
720      somewhere in the un-interesting fork system call.  */
721
722   /* Checkpoint command: create a fork of the inferior process
723      and set it aside for later debugging.  */
724
725   add_com ("checkpoint", class_obscure, checkpoint_command, _("\
726 Fork a duplicate process (experimental)."));
727
728   /* Restart command: restore the context of a specified fork
729      process.  May be used for "program forks" as well as for
730      "debugger forks" (checkpoints).  */
731
732   add_com ("restart", class_obscure, restart_command, _("\
733 restart <n>: restore program context from a checkpoint.\n\
734 Argument 'n' is checkpoint ID, as displayed by 'info checkpoints'."));
735
736   /* Delete checkpoint command: kill the process and remove it from
737      fork list.  */
738
739   add_cmd ("checkpoint", class_obscure, delete_fork_command, _("\
740 Delete a fork/checkpoint (experimental)."),
741            &deletelist);
742
743   /* Detach checkpoint command: release the process to run independently, 
744      and remove it from the fork list.  */
745
746   add_cmd ("checkpoint", class_obscure, detach_fork_command, _("\
747 Detach from a fork/checkpoint (experimental)."),
748            &detachlist);
749
750   /* Info checkpoints command: list all forks/checkpoints 
751      currently under gdb's control.  */
752
753   add_info ("checkpoints", info_forks_command,
754             _("IDs of currently known forks/checkpoints."));
755
756   /* Command aliases (let "fork" and "checkpoint" be used 
757      interchangeably).  */
758
759   add_alias_cmd ("fork", "checkpoint", class_obscure, 1, &deletelist);
760   add_alias_cmd ("fork", "checkpoint", class_obscure, 1, &detachlist);
761   add_info_alias ("forks", "checkpoints", 0);
762
763   /* "fork <n>" (by analogy to "thread <n>").  */
764   add_com ("fork", class_obscure, fork_command, _("\
765 fork <n>: Switch between forked processes.\n\
766 Argument 'n' is fork ID, as displayed by 'info forks'."));
767
768   /* "process <proc id>" as opposed to "fork <fork id>".  */
769   add_com ("process", class_obscure, process_command, _("\
770 process <pid>: Switch between forked processes.\n\
771 Argument 'pid' is process ID, as displayed by 'info forks' or 'shell ps'."));
772 }