aboutsummaryrefslogtreecommitdiff
path: root/gdb/procfs.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/procfs.c')
-rw-r--r--gdb/procfs.c73
1 files changed, 55 insertions, 18 deletions
diff --git a/gdb/procfs.c b/gdb/procfs.c
index 637837f..d9891b4 100644
--- a/gdb/procfs.c
+++ b/gdb/procfs.c
@@ -1425,12 +1425,13 @@ LOCAL FUNCTION
SYNOPSIS
- void create_procinfo (int pid)
+ struct procinfo * create_procinfo (int pid)
DESCRIPTION
- Allocate a procinfo structure, open the /proc file and then sets up
- the set of signals and faults that are to be traced.
+ Allocate a procinfo structure, open the /proc file and then set up the
+ set of signals and faults that are to be traced. Returns a pointer to
+ the new procinfo structure.
NOTES
@@ -1439,7 +1440,7 @@ NOTES
*/
-static void
+static struct procinfo *
create_procinfo (pid)
int pid;
{
@@ -1471,6 +1472,8 @@ create_procinfo (pid)
if (ioctl (pi->fd, PIOCSFAULT, &pi->prrun.pr_fault) < 0)
proc_init_failed (pi, "PIOCSFAULT failed");
+
+ return pi;
}
/*
@@ -2129,20 +2132,20 @@ do_detach (signal)
{
/* Clear any fault that might have stopped it. */
if (ioctl (pi->fd, PIOCCFAULT, 0))
- {
- print_sys_errmsg (pi->pathname, errno);
+ {
+ print_sys_errmsg (pi->pathname, errno);
printf_unfiltered ("PIOCCFAULT failed.\n");
- }
+ }
/* Make it run again when we close it. */
-#if defined (PIOCSET) /* New method */
+#if defined (PIOCSET) /* New method */
{
- long pr_flags;
- pr_flags = PR_RLC;
- result = ioctl (pi->fd, PIOCSET, &pr_flags);
+ long pr_flags;
+ pr_flags = PR_RLC;
+ result = ioctl (pi->fd, PIOCSET, &pr_flags);
}
#else
-#if defined (PIOCSRLC) /* Original method */
+#if defined (PIOCSRLC) /* Original method */
result = ioctl (pi->fd, PIOCSRLC, 0);
#endif
#endif
@@ -2202,10 +2205,12 @@ procfs_wait (pid, ourstatus)
if (pi->had_event)
break;
-wait_again:
-
if (!pi)
- pi = wait_fd ();
+ {
+ wait_again:
+
+ pi = wait_fd ();
+ }
if (pid != -1)
for (pi = procinfo_list; pi; pi = pi->next)
@@ -2308,6 +2313,28 @@ wait_again:
statval = (SIGTRAP << 8) | 0177;
break;
+ case SYS_fork:
+#ifdef SYS_vfork
+ case SYS_vfork:
+#endif
+/* At this point, we've detected the completion of a fork (or vfork) call in
+ our child. The grandchild is also stopped because we set inherit-on-fork
+ earlier. (Note that nobody has the grandchilds' /proc file open at this
+ point.) We will release the grandchild from the debugger by opening it's
+ /proc file and then closing it. Since run-on-last-close is set, the
+ grandchild continues on its' merry way. */
+
+ {
+ struct procinfo *pitemp;
+
+ pitemp = create_procinfo (pi->prstatus.pr_rval1);
+ if (pitemp)
+ close_proc_file (pitemp);
+
+ if (ioctl (pi->fd, PIOCRUN, &pi->prrun) != 0)
+ perror_with_name (pi->pathname);
+ }
+ goto wait_again;
#endif /* SYS_sproc */
default:
@@ -3387,16 +3414,16 @@ No process. Start debugging a program or specify an explicit process ID.");
LOCAL FUNCTION
- procfs_set_sproc_trap -- arrange for exec'd child stop on sproc
+ procfs_set_sproc_trap -- arrange for child to stop on sproc().
SYNOPSIS
- void procfs_set_sproc_trap (void)
+ void procfs_set_sproc_trap (struct procinfo *)
DESCRIPTION
This function sets up a trap on sproc system call exits so that we can
- detect the arrival of a new thread. We are called with the child
+ detect the arrival of a new thread. We are called with the new thread
stopped prior to it's first instruction.
Also note that we turn on the inherit-on-fork flag in the child process
@@ -3419,6 +3446,16 @@ procfs_set_sproc_trap (pi)
praddset (&exitset, SYS_sproc);
+ /* We trap on fork() and vfork() in order to disable debugging in our grand-
+ children and descendant processes. At this time, GDB can only handle
+ threads (multiple processes, one address space). forks (and execs) result
+ in the creation of multiple address spaces, which GDB can't handle yet. */
+
+ praddset (&exitset, SYS_fork);
+#ifdef SYS_vfork
+ praddset (&exitset, SYS_vfork);
+#endif
+
if (ioctl (pi->fd, PIOCSEXIT, &exitset) < 0)
{
print_sys_errmsg (pi->pathname, errno);