X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Flinux-fork.c;h=3b0e41a43a0c6337d2ccdae9eceecde3347f08d9;hb=e2882c85786571175a0b0bfc3bcd2f14620b1ea3;hp=754500f0a667e87b9b43c5643907529fa8601934;hpb=52554a0e324951b5c58e71f2815e841377e9c50c;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/linux-fork.c b/gdb/linux-fork.c index 754500f0a6..3b0e41a43a 100644 --- a/gdb/linux-fork.c +++ b/gdb/linux-fork.c @@ -1,6 +1,6 @@ /* GNU/Linux native-dependent code for debugging multiple forks. - Copyright (C) 2005-2013 Free Software Foundation, Inc. + Copyright (C) 2005-2018 Free Software Foundation, Inc. This file is part of GDB. @@ -20,28 +20,24 @@ #include "defs.h" #include "arch-utils.h" #include "inferior.h" +#include "infrun.h" #include "regcache.h" #include "gdbcmd.h" #include "infcall.h" #include "objfiles.h" -#include "gdb_assert.h" -#include "gdb_string.h" #include "linux-fork.h" #include "linux-nat.h" #include "gdbthread.h" #include "source.h" -#include +#include "nat/gdb_ptrace.h" #include "gdb_wait.h" -#include "gdb_dirent.h" +#include #include struct fork_info *fork_list; static int highest_fork_num; -/* Prevent warning from -Wmissing-prototypes. */ -extern void _initialize_linux_fork (void); - /* Fork list data structure: */ struct fork_info { @@ -64,6 +60,21 @@ forks_exist_p (void) return (fork_list != NULL); } +/* Return the last fork in the list. */ + +static struct fork_info * +find_last_fork (void) +{ + struct fork_info *last; + + if (fork_list == NULL) + return NULL; + + for (last = fork_list; last->next != NULL; last = last->next) + ; + return last; +} + /* Add a fork to the internal fork list. */ struct fork_info * @@ -81,11 +92,19 @@ add_fork (pid_t pid) add_fork (ptid_get_pid (inferior_ptid)); /* safe recursion */ } - fp = XZALLOC (struct fork_info); + fp = XCNEW (struct fork_info); fp->ptid = ptid_build (pid, pid, 0); fp->num = ++highest_fork_num; - fp->next = fork_list; - fork_list = fp; + + if (fork_list == NULL) + fork_list = fp; + else + { + struct fork_info *last = find_last_fork (); + + last->next = fp; + } + return fp; } @@ -107,7 +126,7 @@ free_fork (struct fork_info *fp) if (fp) { if (fp->savedregs) - regcache_xfree (fp->savedregs); + delete fp->savedregs; if (fp->filepos) xfree (fp->filepos); xfree (fp); @@ -226,7 +245,7 @@ call_lseek (int fd, off_t offset, int whence) { char exp[80]; - snprintf (&exp[0], sizeof (exp), "lseek (%d, %ld, %d)", + snprintf (&exp[0], sizeof (exp), "(long) lseek (%d, %ld, %d)", fd, (long) offset, whence); return (off_t) parse_and_eval_long (&exp[0]); } @@ -273,7 +292,7 @@ fork_save_infrun_state (struct fork_info *fp, int clobber_regs) DIR *d; if (fp->savedregs) - regcache_xfree (fp->savedregs); + delete fp->savedregs; fp->savedregs = regcache_dup (get_current_regcache ()); fp->clobber_regs = clobber_regs; @@ -298,8 +317,7 @@ fork_save_infrun_state (struct fork_info *fp, int clobber_regs) fp->maxfd = tmp; } /* Allocate array of file positions. */ - fp->filepos = xrealloc (fp->filepos, - (fp->maxfd + 1) * sizeof (*fp->filepos)); + fp->filepos = XRESIZEVEC (off_t, fp->filepos, fp->maxfd + 1); /* Initialize to -1 (invalid). */ for (tmp = 0; tmp <= fp->maxfd; tmp++) @@ -355,12 +373,13 @@ linux_fork_killall (void) void linux_fork_mourn_inferior (void) { + struct fork_info *last; + int status; + /* Wait just one more time to collect the inferior's exit status. Do not check whether this succeeds though, since we may be dealing with a process that we attached to. Such a process will only report its exit status to its original parent. */ - int status; - waitpid (ptid_get_pid (inferior_ptid), &status, 0); /* OK, presumably inferior_ptid is the one who has exited. @@ -373,7 +392,8 @@ linux_fork_mourn_inferior (void) inferior_ptid yet. */ gdb_assert (fork_list); - fork_load_infrun_state (fork_list); + last = find_last_fork (); + fork_load_infrun_state (last); printf_filtered (_("[Switching to %s]\n"), target_pid_to_str (inferior_ptid)); @@ -417,7 +437,7 @@ linux_fork_detach (const char *args, int from_tty) static void inferior_call_waitpid_cleanup (void *fp) { - struct fork_info *oldfp = fp; + struct fork_info *oldfp = (struct fork_info *) fp; if (oldfp) { @@ -455,9 +475,10 @@ inferior_call_waitpid (ptid_t pptid, int pid) old_cleanup = make_cleanup (inferior_call_waitpid_cleanup, oldfp); /* Get the waitpid_fn. */ - if (lookup_minimal_symbol ("waitpid", NULL, NULL) != NULL) + if (lookup_minimal_symbol ("waitpid", NULL, NULL).minsym != NULL) waitpid_fn = find_function_in_inferior ("waitpid", &waitpid_objf); - if (!waitpid_fn && lookup_minimal_symbol ("_waitpid", NULL, NULL) != NULL) + if (!waitpid_fn + && lookup_minimal_symbol ("_waitpid", NULL, NULL).minsym != NULL) waitpid_fn = find_function_in_inferior ("_waitpid", &waitpid_objf); if (!waitpid_fn) goto out; @@ -468,7 +489,7 @@ inferior_call_waitpid (ptid_t pptid, int pid) argv[2] = value_from_longest (builtin_type (gdbarch)->builtin_int, 0); argv[3] = 0; - retv = call_function_by_hand (waitpid_fn, 3, argv); + retv = call_function_by_hand (waitpid_fn, NULL, 3, argv); if (value_as_long (retv) < 0) goto out; @@ -482,7 +503,7 @@ out: /* Fork list <-> user interface. */ static void -delete_checkpoint_command (char *args, int from_tty) +delete_checkpoint_command (const char *args, int from_tty) { ptid_t ptid, pptid; struct fork_info *fi; @@ -523,7 +544,7 @@ Please switch to another checkpoint before deleting the current one")); } static void -detach_checkpoint_command (char *args, int from_tty) +detach_checkpoint_command (const char *args, int from_tty) { ptid_t ptid; @@ -550,7 +571,7 @@ Please switch to another checkpoint before detaching the current one")); /* Print information about currently known checkpoints. */ static void -info_checkpoints_command (char *arg, int from_tty) +info_checkpoints_command (const char *arg, int from_tty) { struct gdbarch *gdbarch = get_current_arch (); struct symtab_and_line sal; @@ -596,7 +617,7 @@ info_checkpoints_command (char *arg, int from_tty) msym = lookup_minimal_symbol_by_pc (pc); if (msym.minsym) - printf_filtered (", <%s>", SYMBOL_LINKAGE_NAME (msym.minsym)); + printf_filtered (", <%s>", MSYMBOL_LINKAGE_NAME (msym.minsym)); } putchar_filtered ('\n'); @@ -647,7 +668,7 @@ inf_has_multiple_threads (void) } static void -checkpoint_command (char *args, int from_tty) +checkpoint_command (const char *args, int from_tty) { struct objfile *fork_objf; struct gdbarch *gdbarch; @@ -656,7 +677,6 @@ checkpoint_command (char *args, int from_tty) struct value *fork_fn = NULL, *ret; struct fork_info *fp; pid_t retpid; - struct cleanup *old_chain; if (!target_has_execution) error (_("The program is not being run.")); @@ -668,10 +688,10 @@ checkpoint_command (char *args, int from_tty) /* Make the inferior fork, record its (and gdb's) state. */ - if (lookup_minimal_symbol ("fork", NULL, NULL) != NULL) + if (lookup_minimal_symbol ("fork", NULL, NULL).minsym != NULL) fork_fn = find_function_in_inferior ("fork", &fork_objf); if (!fork_fn) - if (lookup_minimal_symbol ("_fork", NULL, NULL) != NULL) + if (lookup_minimal_symbol ("_fork", NULL, NULL).minsym != NULL) fork_fn = find_function_in_inferior ("fork", &fork_objf); if (!fork_fn) error (_("checkpoint: can't find fork function in inferior.")); @@ -680,22 +700,27 @@ checkpoint_command (char *args, int from_tty) ret = value_from_longest (builtin_type (gdbarch)->builtin_int, 0); /* Tell linux-nat.c that we're checkpointing this inferior. */ - old_chain = make_cleanup_restore_integer (&checkpointing_pid); - checkpointing_pid = ptid_get_pid (inferior_ptid); + { + scoped_restore save_pid + = make_scoped_restore (&checkpointing_pid, ptid_get_pid (inferior_ptid)); + + ret = call_function_by_hand (fork_fn, NULL, 0, &ret); + } - ret = call_function_by_hand (fork_fn, 0, &ret); - do_cleanups (old_chain); if (!ret) /* Probably can't happen. */ error (_("checkpoint: call_function_by_hand returned null.")); retpid = value_as_long (ret); get_last_target_status (&last_target_ptid, &last_target_waitstatus); + + fp = find_fork_pid (retpid); + if (from_tty) { int parent_pid; - printf_filtered (_("checkpoint: fork returned pid %ld.\n"), - (long) retpid); + printf_filtered (_("checkpoint %d: fork returned pid %ld.\n"), + fp != NULL ? fp->num : -1, (long) retpid); if (info_verbose) { parent_pid = ptid_get_lwp (last_target_ptid); @@ -706,7 +731,6 @@ checkpoint_command (char *args, int from_tty) } } - fp = find_fork_pid (retpid); if (!fp) error (_("Failed to find new fork")); fork_save_infrun_state (fp, 1); @@ -737,7 +761,7 @@ linux_fork_context (struct fork_info *newfp, int from_tty) /* Switch inferior process (checkpoint) context, by checkpoint id. */ static void -restart_command (char *args, int from_tty) +restart_command (const char *args, int from_tty) { struct fork_info *fp;