/* Machine independent support for SVR4 /proc (process file system) for GDB.
- Copyright 1991, 1992-97, 1998 Free Software Foundation, Inc.
+ Copyright 1991, 1992-98, 1999 Free Software Foundation, Inc.
Written by Fred Fish at Cygnus Support. Changes for sysv4.2mp procfs
compatibility by Geoffrey Noer at Cygnus Solutions.
#endif
/* the name of the proc status struct depends on the implementation */
-#ifdef HAVE_PSTATUS_T
- typedef pstatus_t gdb_prstatus_t;
-#else
+/* Wrap Light Weight Process member in THE_PR_LWP macro for clearer code */
+#ifndef HAVE_PSTATUS_T
typedef prstatus_t gdb_prstatus_t;
+#define THE_PR_LWP(a) a
+#else /* HAVE_PSTATUS_T */
+ typedef pstatus_t gdb_prstatus_t;
+#define THE_PR_LWP(a) a.pr_lwp
+#if !defined(HAVE_PRRUN_T) && defined(HAVE_MULTIPLE_PROC_FDS)
+ /* Fallback definitions - for using configure information directly */
+#ifndef UNIXWARE
+#define UNIXWARE 1
#endif
+#if !defined(PROCFS_USE_READ_WRITE) && !defined(HAVE_PROCFS_PIOCSET)
+#define PROCFS_USE_READ_WRITE 1
+#endif
+#endif /* !HAVE_PRRUN_T && HAVE_MULTIPLE_PROC_FDS */
+#endif /* HAVE_PSTATUS_T */
#define MAX_SYSCALLS 256 /* Maximum number of syscalls for table */
#define MAX_PROC_NAME_SIZE sizeof("/proc/1234567890/status")
-extern struct target_ops procfs_ops; /* Forward declaration */
+struct target_ops procfs_ops;
int procfs_suppress_run = 0; /* Non-zero if procfs should pretend not to
be a runnable target. Used by targets
int had_event; /* poll/select says something happened */
int was_stopped; /* Nonzero if was stopped prior to attach */
int nopass_next_sigstop; /* Don't pass a sigstop on next resume */
-#ifndef HAVE_NO_PRRUN_T
+#ifdef HAVE_PRRUN_T
prrun_t prrun; /* Control state when it is run */
#endif
gdb_prstatus_t prstatus; /* Current process status info */
static void close_proc_file PARAMS ((struct procinfo *));
+static void close_proc_file_cleanup PARAMS ((void*));
+
+static struct cleanup *make_cleanup_close_proc_file PARAMS ((struct procinfo *));
+
static void unconditionally_kill_inferior PARAMS ((struct procinfo *));
static NORETURN void proc_init_failed PARAMS ((struct procinfo *, char *, int)) ATTR_NORETURN;
static void procfs_resume PARAMS ((int pid, int step,
enum target_signal signo));
+static void init_procfs_ops PARAMS ((void));
+
/* External function prototypes that can't be easily included in any
header file because the args are typedefs in system include files. */
printf_filtered ("LWP %d exited.\n",
(pi->pid >> 16) & 0xffff);
close_proc_file (pi);
+ i--; /* don't skip deleted entry */
if (num_fds != 0)
- continue; /* already another event to process */
+ break; /* already another event to process */
else
goto wait_again; /* wait for another event */
}
LOCAL FUNCTION
- procfs_kill_inferior - kill any currently inferior
+ procfs_kill_inferior - kill any current inferior
SYNOPSIS
pi = find_procinfo (pid, 0);
-#ifdef UNIXWARE
+#ifndef HAVE_PRRUN_T
premptyset (&sctl.sigset);
#else
sctl.sigset = pi->prrun.pr_trace;
notice_signals (pi, &sctl);
-#ifndef UNIXWARE
+#ifdef HAVE_PRRUN_T
pi->prrun.pr_trace = sctl.sigset;
#endif
}
if ((pi = find_procinfo ((*lwps << 16) | pid, 1)) == 0)
pi = init_procinfo ((*lwps << 16) | pid, 0);
-#ifdef UNIXWARE
- if (pi->prstatus.pr_lwp.pr_flags & (PR_STOPPED | PR_ISTOP))
-#else
- if (pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP))
-#endif
+ if (THE_PR_LWP(pi->prstatus).pr_flags & (PR_STOPPED | PR_ISTOP))
{
pi->was_stopped = 1;
}
}
else
{
-#ifdef UNIXWARE
- if (signal || (pi->prstatus.pr_lwp.pr_flags & (PR_STOPPED | PR_ISTOP)))
-#else
- if (signal || (pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP)))
-#endif
+ if (signal
+ || (THE_PR_LWP(pi->prstatus).pr_flags & (PR_STOPPED | PR_ISTOP)))
{
long cmd;
struct proc_ctl pctl;
if (!pi->had_event)
continue;
-#ifdef UNIXWARE
- if (! (pi->prstatus.pr_lwp.pr_flags & (PR_STOPPED | PR_ISTOP)) )
+ if (! (THE_PR_LWP(pi->prstatus).pr_flags & (PR_STOPPED | PR_ISTOP)) )
continue;
- why = pi->prstatus.pr_lwp.pr_why;
- what = pi->prstatus.pr_lwp.pr_what;
-#else
- if (! (pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP)) )
- continue;
-
- why = pi->prstatus.pr_why;
- what = pi->prstatus.pr_what;
-#endif
+ why = THE_PR_LWP(pi->prstatus).pr_why;
+ what = THE_PR_LWP(pi->prstatus).pr_what;
if (why == PR_SYSENTRY || why == PR_SYSEXIT)
{
int i;
goto scan_again;
}
-#ifdef UNIXWARE
- if (!checkerr && !(pi->prstatus.pr_lwp.pr_flags & (PR_STOPPED | PR_ISTOP)))
-#else
- if (!checkerr && !(pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP)))
-#endif
+ if (!checkerr
+ && !(THE_PR_LWP(pi->prstatus).pr_flags & (PR_STOPPED | PR_ISTOP)))
{
if (!procfs_write_pcwstop (pi))
{
/* NOTREACHED */
}
}
-#ifdef UNIXWARE
- else if (pi->prstatus.pr_lwp.pr_flags & (PR_STOPPED | PR_ISTOP))
-#else
- else if (pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP))
-#endif
+ else if (THE_PR_LWP(pi->prstatus).pr_flags & (PR_STOPPED | PR_ISTOP))
{
#ifdef UNIXWARE
rtnval = pi->prstatus.pr_pid;
- why = pi->prstatus.pr_lwp.pr_why;
- what = pi->prstatus.pr_lwp.pr_what;
#else
rtnval = pi->pid;
- why = pi->prstatus.pr_why;
- what = pi->prstatus.pr_what;
#endif
+ why = THE_PR_LWP(pi->prstatus).pr_why;
+ what = THE_PR_LWP(pi->prstatus).pr_what;
switch (why)
{
/* Use the signal which the kernel assigns. This is better than
trying to second-guess it from the fault. In fact, I suspect
that FLTACCESS can be either SIGSEGV or SIGBUS. */
-#ifdef UNIXWARE
- statval = ((pi->prstatus.pr_lwp.pr_info.si_signo) << 8) | 0177;
-#else
- statval = ((pi->prstatus.pr_info.si_signo) << 8) | 0177;
-#endif
+ statval =
+ ((THE_PR_LWP(pi->prstatus).pr_info.si_signo) << 8) | 0177;
break;
}
break;
else
{
error ("PIOCWSTOP, stopped for unknown/unhandled reason, flags %#x",
-#ifdef UNIXWARE
- pi->prstatus.pr_lwp.pr_flags);
-#else
- pi->prstatus.pr_flags);
-#endif
+ THE_PR_LWP(pi->prstatus).pr_flags);
}
store_waitstatus (ourstatus, statval);
If we are not delivering the same signal that the prstatus siginfo
struct contains information about, then synthesize a siginfo struct
- to match the signal we are doing to deliver, make it of the type
+ to match the signal we are going to deliver, make it of the type
"generated by a user process", and send this synthesized copy. When
used to set the inferior's signal state, this will be required if we
are not currently stopped because of a traced signal, or if we decide
/* With Alpha OSF/1 procfs, the kernel gets really confused if it
receives a PIOCSSIG with a signal identical to the current signal,
it messes up the current signal. Work around the kernel bug. */
-#ifdef UNIXWARE
- if (signo == pip -> prstatus.pr_lwp.pr_cursig)
-#else
- if (signo == pip -> prstatus.pr_cursig)
-#endif
+ if (signo == THE_PR_LWP(pip->prstatus).pr_cursig)
return;
#endif
#ifdef UNIXWARE
- if (signo == pip->prstatus.pr_lwp.pr_info.si_signo)
+ if (signo == THE_PR_LWP(pip->prstatus).pr_info.si_signo)
{
memcpy ((char *) &sictl.siginfo, (char *) &pip->prstatus.pr_lwp.pr_info,
sizeof (siginfo_t));
}
#else
- if (signo == pip -> prstatus.pr_info.si_signo)
+ if (signo == THE_PR_LWP(pip->prstatus).pr_info.si_signo)
{
sip = &pip -> prstatus.pr_info;
}
an inferior to continue running at the same time as gdb. (FIXME?) */
signal_to_pass = 0;
else if (signo == TARGET_SIGNAL_TSTP
-#ifdef UNIXWARE
- && pi->prstatus.pr_lwp.pr_cursig == SIGTSTP
- && pi->prstatus.pr_lwp.pr_action.sa_handler == SIG_DFL
-#else
- && pi->prstatus.pr_cursig == SIGTSTP
- && pi->prstatus.pr_action.sa_handler == SIG_DFL
-#endif
+ && THE_PR_LWP(pi->prstatus).pr_cursig == SIGTSTP
+ && THE_PR_LWP(pi->prstatus).pr_action.sa_handler == SIG_DFL
)
/* We are about to pass the inferior a SIGTSTP whose action is
}
}
+static void
+close_proc_file_cleanup (pip)
+ void *pip;
+{
+ close_proc_file ((struct procinfo *) pip);
+}
+
+static struct cleanup *
+make_cleanup_close_proc_file (pip)
+ struct procinfo *pip;
+{
+ return make_cleanup (close_proc_file_cleanup, pip);
+}
+
/*
LOCAL FUNCTION
return 0;
}
- sprintf (pip->pathname, MAP_PROC_NAME_FMT, tmp);
- if ((pip->map_fd = open (pip->pathname, O_RDONLY)) < 0)
- {
- close (pip->status_fd);
- close (pip->as_fd);
- return 0;
- }
-
if (control)
{
sprintf (pip->pathname, CTL_PROC_NAME_FMT, tmp);
int why;
int what;
-#ifdef UNIXWARE
- why = pip -> prstatus.pr_lwp.pr_why;
- what = pip -> prstatus.pr_lwp.pr_what;
-#else
- why = pip -> prstatus.pr_why;
- what = pip -> prstatus.pr_what;
-#endif
+ why = THE_PR_LWP(pip->prstatus).pr_why;
+ what = THE_PR_LWP(pip->prstatus).pr_what;
-#ifdef UNIXWARE
- if (pip -> prstatus.pr_lwp.pr_flags & PR_STOPPED)
-#else
- if (pip -> prstatus.pr_flags & PR_STOPPED)
-#endif
+ if (THE_PR_LWP(pip->prstatus).pr_flags & PR_STOPPED)
{
printf_filtered ("%-32s", "Reason for stopping:");
if (!summary)
{
struct siginfo *sip;
-#ifdef UNIXWARE
- if ((pip -> prstatus.pr_lwp.pr_flags & PR_STOPPED) &&
- (pip -> prstatus.pr_lwp.pr_why == PR_SIGNALLED ||
- pip -> prstatus.pr_lwp.pr_why == PR_FAULTED))
-#else
- if ((pip -> prstatus.pr_flags & PR_STOPPED) &&
- (pip -> prstatus.pr_why == PR_SIGNALLED ||
- pip -> prstatus.pr_why == PR_FAULTED))
-#endif
+ if ((THE_PR_LWP(pip->prstatus).pr_flags & PR_STOPPED) &&
+ (THE_PR_LWP(pip->prstatus).pr_why == PR_SIGNALLED ||
+ THE_PR_LWP(pip->prstatus).pr_why == PR_FAULTED))
{
printf_filtered ("%-32s", "Additional signal/fault info:");
-#ifdef UNIXWARE
- sip = &pip -> prstatus.pr_lwp.pr_info;
-#else
- sip = &pip -> prstatus.pr_info;
-#endif
+ sip = &(THE_PR_LWP(pip->prstatus).pr_info);
if (summary)
{
printf_filtered ("%s ", signalname (sip -> si_signo));
{
nomem (0);
}
- make_cleanup (freeargv, (char *) argv);
+ make_cleanup_freeargv (argv);
while (*argv != NULL)
{
/* NOTREACHED */
}
pid = pip->pid;
- make_cleanup (close_proc_file, pip);
+ make_cleanup_close_proc_file (pip);
}
else if (**argv != '\000')
{
if (!open_proc_file ((*lwps << 16) | pid, pip, O_RDONLY, 0))
continue;
- make_cleanup (close_proc_file, pip);
+ make_cleanup_close_proc_file (pip);
if (!procfs_read_status (pip))
{
in the child and continue the parent. */
/* Third arg is pointer to new thread id. */
-#ifdef UNIXWARE
- lwp_id = read_memory_integer (pi->prstatus.pr_lwp.pr_sysarg[2], sizeof (int));
-#else
- lwp_id = read_memory_integer (pi->prstatus.pr_sysarg[2], sizeof (int));
-#endif
+ lwp_id = read_memory_integer (
+ THE_PR_LWP(pi->prstatus).pr_sysarg[2], sizeof (int));
lwp_id = (lwp_id << 16) | PIDGET (pi->pid);
SUSPENDED or RUNNABLE. If runnable, we will simply signal it to run.
If suspended, we flag it to be continued later, when it has an event. */
-#ifdef UNIXWARE
- if (childpi->prstatus.pr_lwp.pr_why == PR_SUSPENDED)
-#else
- if (childpi->prstatus.pr_why == PR_SUSPENDED)
-#endif
+ if (THE_PR_LWP(childpi->prstatus).pr_why == PR_SUSPENDED)
childpi->new_child = 1; /* Flag this as an unseen child process */
else
{
return buf;
}
#endif /* TIDGET */
-\f
-struct target_ops procfs_ops;
-void
-_initialize_procfs ()
+\f
+static void
+init_procfs_ops ()
{
-#ifdef HAVE_OPTIONAL_PROC_FS
- char procname[MAX_PROC_NAME_SIZE];
- int fd;
-
- /* If we have an optional /proc filesystem (e.g. under OSF/1),
- don't add procfs support if we cannot access the running
- GDB via /proc. */
- sprintf (procname, STATUS_PROC_NAME_FMT, getpid ());
- if ((fd = open (procname, O_RDONLY)) < 0)
- return;
- close (fd);
-#endif
procfs_ops.to_shortname = "procfs";
procfs_ops.to_longname = "Unix /proc child process";
procfs_ops.to_doc = "Unix /proc child process (started by the \"run\" command).";
procfs_ops.to_open = procfs_open;
- procfs_ops.to_close = 0;
procfs_ops.to_attach = procfs_attach;
- procfs_ops.to_require_attach = procfs_attach;
procfs_ops.to_detach = procfs_detach;
- procfs_ops.to_require_detach = procfs_detach;
procfs_ops.to_resume = procfs_resume;
procfs_ops.to_wait = procfs_wait;
procfs_ops.to_fetch_registers = procfs_fetch_registers;
procfs_ops.to_terminal_ours = terminal_ours;
procfs_ops.to_terminal_info = child_terminal_info;
procfs_ops.to_kill = procfs_kill_inferior;
- procfs_ops.to_load = 0;
- procfs_ops.to_lookup_symbol = 0;
procfs_ops.to_create_inferior = procfs_create_inferior;
procfs_ops.to_mourn_inferior = procfs_mourn_inferior;
procfs_ops.to_can_run = procfs_can_run;
procfs_ops.to_has_stack = 1;
procfs_ops.to_has_registers = 1;
procfs_ops.to_has_execution = 1;
- procfs_ops.to_has_thread_control = tc_none;
- procfs_ops.to_sections = 0;
- procfs_ops.to_sections_end = 0;
procfs_ops.to_magic = OPS_MAGIC;
+}
+
+void
+_initialize_procfs ()
+{
+#ifdef HAVE_OPTIONAL_PROC_FS
+ char procname[MAX_PROC_NAME_SIZE];
+ int fd;
+
+ /* If we have an optional /proc filesystem (e.g. under OSF/1),
+ don't add procfs support if we cannot access the running
+ GDB via /proc. */
+ sprintf (procname, STATUS_PROC_NAME_FMT, getpid ());
+ if ((fd = open (procname, O_RDONLY)) < 0)
+ return;
+ close (fd);
+#endif
+ init_procfs_ops ();
add_target (&procfs_ops);
add_info ("processes", info_proc,