summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Snyder <msnyder@vmware.com>2005-11-27 00:02:46 +0000
committerMichael Snyder <msnyder@vmware.com>2005-11-27 00:02:46 +0000
commit1d2d1dd46fb45402443192a14cd2e485596f242f (patch)
treea2c76d7c10b66809cb54c931bd8e01754fa4a25e
parentb80f8a5de994430287506f85c58659584948628f (diff)
downloadbinutils-gdb-1d2d1dd46fb45402443192a14cd2e485596f242f.tar.gz
2005-11-26 Michael Snyder <msnyder@redhat.com>
* linux-nat.c (super_mourn_inferior): New function pointer. (child_mourn_inferior): New method, overrides to_mourn_inferior. Handles multiple forks. (linux_target): Intercept to_mourn_inferior, save pointer to parent method.
-rw-r--r--gdb/ChangeLog8
-rw-r--r--gdb/linux-nat.c63
2 files changed, 66 insertions, 5 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index df28ca7f187..0c49ef3e913 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,5 +1,13 @@
2005-11-26 Michael Snyder <msnyder@redhat.com>
+ * linux-nat.c (super_mourn_inferior): New function pointer.
+ (child_mourn_inferior): New method, overrides to_mourn_inferior.
+ Handles multiple forks.
+ (linux_target): Intercept to_mourn_inferior, save pointer to
+ parent method.
+
+2005-11-26 Michael Snyder <msnyder@redhat.com>
+
* linux-fork.h: New file.
* linux-nat.c: Include linux-fork.h, remove forward declarations.
(kill_inferior): Loop over forks and PTRACE_KILL them all.
diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
index 757b37e859d..ebba1b1b3f8 100644
--- a/gdb/linux-nat.c
+++ b/gdb/linux-nat.c
@@ -90,12 +90,18 @@
the use of the multi-threaded target. */
static struct target_ops *linux_ops;
-/* The saved to_xfer_partial method, inherited from inf-ptrace.c. Called
- by our to_xfer_partial. */
-static LONGEST (*super_xfer_partial) (struct target_ops *, enum target_object,
- const char *, gdb_byte *, const gdb_byte *,
+/* The saved to_xfer_partial method, inherited from inf-ptrace.c.
+ Called by our to_xfer_partial. */
+static LONGEST (*super_xfer_partial) (struct target_ops *,
+ enum target_object,
+ const char *, gdb_byte *,
+ const gdb_byte *,
ULONGEST, LONGEST);
+/* The saved to_mourn_inferior method, inherited from inf-ptrace.c.
+ Called by our to_mourn_inferior. */
+static void (*super_mourn_inferior) (void);
+
static int debug_linux_nat;
static void
show_debug_linux_nat (struct ui_file *file, int from_tty,
@@ -1785,6 +1791,48 @@ resumed_callback (struct lwp_info *lp, void *data)
return lp->resumed;
}
+/* Local mourn_inferior -- we need to override mourn_inferior
+ so that we can do something clever if one of several forks
+ has exited. */
+
+static void
+child_mourn_inferior (void)
+{
+ int status;
+
+ if (fork_list &&
+ fork_list->next == NULL &&
+ ptid_equal (fork_list->ptid, inferior_ptid))
+ {
+ /* Last fork -- delete from list and handle as solo process. */
+ delete_fork (inferior_ptid);
+ }
+
+ if (fork_list == NULL)
+ {
+ /* Normal case, no other forks available. */
+ super_mourn_inferior ();
+ return;
+ }
+
+ /* Multi-fork case. */
+ /* 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 origional parent. */
+ waitpid (ptid_get_pid (inferior_ptid), &status, 0);
+
+ /* OK, presumably inferior_ptid is the one who has exited.
+ We need to delete that one from the fork_list, and switch
+ to the next available fork. FIXME safety? */
+ delete_fork (inferior_ptid);
+ inferior_ptid = fork_list[0].ptid;
+ printf_filtered ("[Switching to %s]\n",
+ target_pid_to_str (inferior_ptid));
+
+ /* Is that enough? Maybe infrun will take care of everything else... */
+}
+
/* We need to override child_wait to support attaching to cloned
processes, since a normal wait (as done by the default version)
ignores those processes. */
@@ -3257,6 +3305,9 @@ linux_target (void)
super_xfer_partial = t->to_xfer_partial;
t->to_xfer_partial = linux_xfer_partial;
+ super_mourn_inferior = t->to_mourn_inferior;
+ t->to_mourn_inferior = child_mourn_inferior;
+
linux_ops = t;
return t;
}
@@ -3767,8 +3818,10 @@ restart_command (char *args, int from_tty)
fork_load_infrun_state (newfp);
registers_changed ();
/* FIXME lose this. */
+#if 0
target_fetch_registers (-1); /* FIXME should not be necessary;
fill_gregset should do it automatically. */
+#endif
reinit_frame_cache ();
stop_pc = read_pc ();
select_frame (get_current_frame ());
@@ -3781,7 +3834,7 @@ restart_command (char *args, int from_tty)
newfp->been_restarted = 1;
printf_filtered ("Switching to %s\n",
- target_pid_or_tid_to_str (inferior_ptid));
+ target_pid_to_str (inferior_ptid));
print_stack_frame (get_selected_frame (NULL), 1, SRC_AND_LOC);
}