#include "target.h"
#include "command.h"
#include "gdbcore.h"
-#include "thread.h"
+#include "gdbthread.h"
#define MAX_SYSCALLS 256 /* Maximum number of syscalls for table */
static int num_poll_list = 0; /* Number of entries in poll_list */
-static int last_resume_pid = -1; /* Last pid used with procfs_resume */
-
/* Much of the information used in the /proc interface, particularly for
printing status information, is kept as tables of structures of the
following form. These tables can be used to map numeric values to
/* Prototypes for local functions */
+static void procfs_stop PARAMS ((void));
+
+static int procfs_thread_alive PARAMS ((int));
+
+static int procfs_can_run PARAMS ((void));
+
+static void procfs_mourn_inferior PARAMS ((void));
+
+static void procfs_fetch_registers PARAMS ((int));
+
+static int procfs_wait PARAMS ((int, struct target_waitstatus *));
+
+static void procfs_open PARAMS ((char *, int));
+
+static void procfs_files_info PARAMS ((struct target_ops *));
+
+static void procfs_prepare_to_store PARAMS ((void));
+
+static void procfs_detach PARAMS ((char *, int));
+
+static void procfs_attach PARAMS ((char *, int));
+
+static void proc_set_exec_trap PARAMS ((void));
+
+static int procfs_init_inferior PARAMS ((int));
+
+static struct procinfo *create_procinfo PARAMS ((int));
+
+static void procfs_store_registers PARAMS ((int));
+
+static int procfs_xfer_memory PARAMS ((CORE_ADDR, char *, int, int, struct target_ops *));
+
+static void procfs_kill_inferior PARAMS ((void));
+
+static char *sigcodedesc PARAMS ((siginfo_t *));
+
+static char *sigcodename PARAMS ((siginfo_t *));
+
+static struct procinfo *wait_fd PARAMS ((void));
+
+static void remove_fd PARAMS ((struct procinfo *));
+
+static void add_fd PARAMS ((struct procinfo *));
+
static void set_proc_siginfo PARAMS ((struct procinfo *, int));
static void init_syscall_table PARAMS ((void));
wait_fd ()
{
struct procinfo *pi;
+#ifndef LOSING_POLL
int num_fds;
int i;
+#endif
set_sigint_trap (); /* Causes SIGINT to be passed on to the
attached process. */
set_sigio_trap ();
#ifndef LOSING_POLL
- num_fds = poll (poll_list, num_poll_list, -1);
+ while (1)
+ {
+ num_fds = poll (poll_list, num_poll_list, -1);
+ if (num_fds > 0)
+ break;
+ if (num_fds < 0 && errno == EINTR)
+ continue;
+ print_sys_errmsg ("poll failed", errno);
+ error ("Poll failed, returned %d", num_fds);
+ }
#else
pi = current_procinfo;
#ifndef LOSING_POLL
- if (num_fds <= 0)
- {
- print_sys_errmsg ("poll failed\n", errno);
- error ("Poll failed, returned %d", num_fds);
- }
-
for (i = 0; i < num_poll_list && num_fds > 0; i++)
{
if ((poll_list[i].revents & (POLLPRI|POLLERR|POLLHUP|POLLNVAL)) == 0)
pip = create_procinfo (pid);
+#ifndef PIOCSSPCACT
procfs_set_syscall_trap (pip, SYS_exit, PROCFS_SYSCALL_ENTRY,
procfs_exit_handler);
-#ifndef PRFS_STOPEXEC
#ifdef SYS_exec
procfs_set_syscall_trap (pip, SYS_exec, PROCFS_SYSCALL_EXIT,
procfs_exec_handler);
procfs_set_syscall_trap (pip, SYS_execve, PROCFS_SYSCALL_EXIT,
procfs_exec_handler);
#endif
-#endif /* PRFS_STOPEXEC */
+#endif /* PIOCSSPCACT */
/* Setup traps on exit from sproc() */
#ifdef PIOCSSPCACT
/* Under Alpha OSF/1 we have to use a PIOCSSPCACT ioctl to trace
- exits from exec system calls because of the user level loader. */
+ exits from exec system calls because of the user level loader.
+ Starting with OSF/1-4.0, tracing the entry to the exit system
+ call no longer works. So we have to use PRFS_STOPTERM to trace
+ termination of the inferior. */
{
int prfs_flags;
gdb_flush (gdb_stderr);
_exit (127);
}
- prfs_flags |= PRFS_STOPEXEC;
+ prfs_flags |= PRFS_STOPEXEC | PRFS_STOPTERM;
if (ioctl (fd, PIOCSSPCACT, &prfs_flags) < 0)
{
perror (procname);
_exit (127);
}
}
-#else
+#else /* PIOCSSPCACT */
/* GW: Rationale...
Not all systems with /proc have all the exec* syscalls with the same
names. On the SGI, for example, there is no SYS_exec, but there
gdb_flush (gdb_stderr);
_exit (127);
}
-#endif
praddset (&entryset, SYS_exit);
gdb_flush (gdb_stderr);
_exit (126);
}
+#endif /* PIOCSSPCACT */
/* Turn off inherit-on-fork flag so that all grand-children of gdb
start with tracing flags cleared. */
do_attach (pid)
int pid;
{
- int result;
struct procinfo *pi;
pi = (struct procinfo *) xmalloc (sizeof (struct procinfo));
do_detach (signal)
int signal;
{
- int result;
struct procinfo *pi;
pi = current_procinfo;
error ("PR_SYSEXIT, unhandled system call %d", what);
}
break;
+#ifdef PR_DEAD
+ case (short)PR_DEAD:
+ {
+ int dummy;
+
+ /* The inferior process is about to terminate.
+ pr_what has the process's exit or return value.
+ A PIOCRUN ioctl must be used to restart the process so it
+ can finish exiting. */
+
+ pi->prrun.pr_flags = PRCFAULT;
+
+ if (ioctl (pi->fd, PIOCRUN, &pi->prrun) != 0)
+ perror_with_name (pi->pathname);
+
+ if (wait (&dummy) < 0)
+ rtnval = -1;
+ statval = pi->prstatus.pr_what;
+ }
+ break;
+#endif
case PR_REQUESTED:
statval = (SIGSTOP << 8) | 0177;
break;
int status = 0;
int all = 0;
int nlwp;
- id_t *lwps;
+ int *lwps;
old_chain = make_cleanup (null_cleanup, 0);
}
#else /* PIOCLWPIDS */
nlwp = 1;
- lwps = alloca ((2 * nlwp + 2) * sizeof (id_t));
+ lwps = alloca ((2 * nlwp + 2) * sizeof *lwps);
lwps[0] = 0;
#endif /* PIOCLWPIDS */
int fd;
int flag;
{
+#ifdef PIOCSET
long pr_flags;
+#endif
int retval;
#ifdef PIOCSET /* New method */
int fd;
int flag;
{
+#ifdef PIOCSET
long pr_flags;
+#endif
int retval;
#ifdef PIOCSET /* New method */
/* Why is this necessary? Shouldn't dead threads just be removed from the
thread database? */
-int
+static int
procfs_thread_alive (pid)
int pid;
{
XXX - This may not be correct for all systems. Some may want to use
killpg() instead of kill (-pgrp). */
-void
+static void
procfs_stop ()
{
extern pid_t inferior_process_group;
kill (-inferior_process_group, SIGINT);
}
+\f
+/* Convert a pid to printable form. */
+#ifdef TIDGET
+char *
+procfs_pid_to_str (pid)
+ int pid;
+{
+ static char buf[100];
+
+ sprintf (buf, "Kernel thread %d", TIDGET (pid));
+
+ return buf;
+}
+#endif /* TIDGET */
\f
struct target_ops procfs_ops = {
"procfs", /* to_shortname */