/* Machine independent support for SVR4 /proc (process file system) for GDB.
- Copyright 1999-2000 Free Software Foundation, Inc.
+ Copyright 1999, 2000, 2001 Free Software Foundation, Inc.
Written by Michael Snyder at Cygnus Solutions.
Based on work by Fred Fish, Stu Grossman, Geoff Noer, and others.
#endif
#include <sys/procfs.h>
+#ifdef HAVE_SYS_FAULT_H
#include <sys/fault.h>
+#endif
+#ifdef HAVE_SYS_SYSCALL_H
#include <sys/syscall.h>
+#endif
#include <sys/errno.h>
#include <sys/wait.h>
#include <signal.h>
* Solaris
* OSF
* Unixware
+ * AIX5
*
* /proc works by immitating a file system: you open a simulated file
* that represents the process you wish to interact with, and
static void procfs_open (char *, int);
static void procfs_attach (char *, int);
static void procfs_detach (char *, int);
-static void procfs_resume (int, int, enum target_signal);
+static void procfs_resume (ptid_t, int, enum target_signal);
static int procfs_can_run (void);
static void procfs_stop (void);
static void procfs_files_info (struct target_ops *);
static void procfs_fetch_registers (int);
static void procfs_store_registers (int);
-static void procfs_notice_signals (int);
+static void procfs_notice_signals (ptid_t);
static void procfs_prepare_to_store (void);
static void procfs_kill_inferior (void);
static void procfs_mourn_inferior (void);
static void procfs_create_inferior (char *, char *, char **);
-static int procfs_wait (int, struct target_waitstatus *);
-static int procfs_xfer_memory (CORE_ADDR,
- char *, int, int, struct target_ops *);
+static ptid_t procfs_wait (ptid_t, struct target_waitstatus *);
+static int procfs_xfer_memory (CORE_ADDR, char *, int, int,
+ struct mem_attrib *attrib,
+ struct target_ops *);
-static int procfs_thread_alive (int);
+static int procfs_thread_alive (ptid_t);
void procfs_find_new_threads (void);
-char *procfs_pid_to_str (int);
+char *procfs_pid_to_str (ptid_t);
struct target_ops procfs_ops; /* the target vector */
*/
#ifdef NEW_PROC_API /* Solaris 7 && 8 method for watchpoints */
-#ifndef UNIXWARE
+#ifdef WA_READ
enum { READ_WATCHFLAG = WA_READ,
WRITE_WATCHFLAG = WA_WRITE,
EXEC_WATCHFLAG = WA_EXEC,
};
#endif
+/* gdb_sigset_t */
+#ifdef HAVE_PR_SIGSET_T
+typedef pr_sigset_t gdb_sigset_t;
+#else
+typedef sigset_t gdb_sigset_t;
+#endif
+
+/* sigaction */
+#ifdef HAVE_PR_SIGACTION64_T
+typedef pr_sigaction64_t gdb_sigaction_t;
+#else
+typedef struct sigaction gdb_sigaction_t;
+#endif
+
+/* siginfo */
+#ifdef HAVE_PR_SIGINFO64_T
+typedef pr_siginfo64_t gdb_siginfo_t;
+#else
+typedef struct siginfo gdb_siginfo_t;
+#endif
+
+/* gdb_premptysysset */
+#ifdef premptysysset
+#define gdb_premptysysset premptysysset
+#else
+#define gdb_premptysysset premptyset
+#endif
+
+/* praddsysset */
+#ifdef praddsysset
+#define gdb_praddsysset praddsysset
+#else
+#define gdb_praddsysset praddset
+#endif
+
+/* prdelsysset */
+#ifdef prdelsysset
+#define gdb_prdelsysset prdelsysset
+#else
+#define gdb_prdelsysset prdelset
+#endif
+
+/* prissyssetmember */
+#ifdef prissyssetmember
+#define gdb_pr_issyssetmember prissyssetmember
+#else
+#define gdb_pr_issyssetmember prismember
+#endif
+
+/* As a feature test, saying ``#if HAVE_PRSYSENT_T'' everywhere isn't
+ as intuitively descriptive as it could be, so we'll define
+ DYNAMIC_SYSCALLS to mean the same thing. Anyway, at the time of
+ this writing, this feature is only found on AIX5 systems and
+ basically means that the set of syscalls is not fixed. I.e,
+ there's no nice table that one can #include to get all of the
+ syscall numbers. Instead, they're stored in /proc/PID/sysent
+ for each process. We are at least guaranteed that they won't
+ change over the lifetime of the process. But each process could
+ (in theory) have different syscall numbers.
+*/
+#ifdef HAVE_PRSYSENT_T
+#define DYNAMIC_SYSCALLS
+#endif
typedef prstatus_t gdb_lwpstatus_t;
#endif /* NEW_PROC_API */
-/* Provide default composite pid manipulation macros for systems that
- don't have threads. */
-
-#ifndef PIDGET
-#define PIDGET(PID) (PID)
-#define TIDGET(PID) (PID)
-#endif
-#ifndef MERGEPID
-#define MERGEPID(PID, TID) (PID)
-#endif
-
typedef struct procinfo {
struct procinfo *next;
int pid; /* Process ID */
char pathname[MAX_PROC_NAME_SIZE]; /* Pathname to /proc entry */
fltset_t saved_fltset; /* Saved traced hardware fault set */
- sigset_t saved_sigset; /* Saved traced signal set */
- sigset_t saved_sighold; /* Saved held signal set */
- sysset_t saved_exitset; /* Saved traced system call exit set */
- sysset_t saved_entryset; /* Saved traced system call entry set */
+ gdb_sigset_t saved_sigset; /* Saved traced signal set */
+ gdb_sigset_t saved_sighold; /* Saved held signal set */
+ sysset_t *saved_exitset; /* Saved traced system call exit set */
+ sysset_t *saved_entryset; /* Saved traced system call entry set */
gdb_prstatus_t prstatus; /* Current process status info */
#ifndef NEW_PROC_API
gdb_fpregset_t fpregset; /* Current floating point registers */
#endif
+
+#ifdef DYNAMIC_SYSCALLS
+ int num_syscalls; /* Total number of syscalls */
+ char **syscall_names; /* Syscall number to name map */
+#endif
struct procinfo *thread_list;
static void dead_procinfo (procinfo * p, char *msg, int killp);
static int open_procinfo_files (procinfo * p, int which);
static void close_procinfo_files (procinfo * p);
+static int sysset_t_size (procinfo *p);
+static sysset_t *sysset_t_alloc (procinfo * pi);
+#ifdef DYNAMIC_SYSCALLS
+static void load_syscalls (procinfo *pi);
+static void free_syscalls (procinfo *pi);
+static int find_syscall (procinfo *pi, char *name);
+#endif /* DYNAMIC_SYSCALLS */
/* The head of the procinfo list: */
static procinfo * procinfo_list;
return pi;
}
+/* open_with_retry() is a wrapper for open(). The appropriate
+ open() call is attempted; if unsuccessful, it will be retried as
+ many times as needed for the EAGAIN and EINTR conditions.
+
+ For other conditions, open_with_retry() will retry the open() a
+ limited number of times. In addition, a short sleep is imposed
+ prior to retrying the open(). The reason for this sleep is to give
+ the kernel a chance to catch up and create the file in question in
+ the event that GDB "wins" the race to open a file before the kernel
+ has created it. */
+
+static int
+open_with_retry (const char *pathname, int flags)
+{
+ int retries_remaining, status;
+
+ retries_remaining = 2;
+
+ while (1)
+ {
+ status = open (pathname, flags);
+
+ if (status >= 0 || retries_remaining == 0)
+ break;
+ else if (errno != EINTR && errno != EAGAIN)
+ {
+ retries_remaining--;
+ sleep (1);
+ }
+ }
+
+ return status;
+}
+
/*
* Function: open_procinfo_files
*
strcat (tmp, "/lwpctl");
else
strcat (tmp, "/ctl");
- fd = open (tmp, O_WRONLY);
+ fd = open_with_retry (tmp, O_WRONLY);
if (fd <= 0)
return 0; /* fail */
pi->ctl_fd = fd;
if (pi->tid)
return 0; /* there is no 'as' file descriptor for an lwp */
strcat (tmp, "/as");
- fd = open (tmp, O_RDWR);
+ fd = open_with_retry (tmp, O_RDWR);
if (fd <= 0)
return 0; /* fail */
pi->as_fd = fd;
strcat (tmp, "/lwpstatus");
else
strcat (tmp, "/status");
- fd = open (tmp, O_RDONLY);
+ fd = open_with_retry (tmp, O_RDONLY);
if (fd <= 0)
return 0; /* fail */
pi->status_fd = fd;
#ifdef PIOCTSTATUS /* OSF */
- if ((fd = open (pi->pathname, O_RDWR)) == 0) /* Only one FD; just open it. */
+ /* Only one FD; just open it. */
+ if ((fd = open_with_retry (pi->pathname, O_RDWR)) == 0)
return 0;
#else /* Sol 2.5, Irix, other? */
if (pi->tid == 0) /* Master procinfo for the process */
{
- fd = open (pi->pathname, O_RDWR);
+ fd = open_with_retry (pi->pathname, O_RDWR);
if (fd <= 0)
return 0; /* fail */
}
pi->pid = pid;
pi->tid = tid;
+#ifdef DYNAMIC_SYSCALLS
+ load_syscalls (pi);
+#endif
+
+ pi->saved_entryset = sysset_t_alloc (pi);
+ pi->saved_exitset = sysset_t_alloc (pi);
+
/* Chain into list. */
if (tid == 0)
{
close_procinfo_files (pi);
/* Step three: free the memory. */
- free (pi);
+#ifdef DYNAMIC_SYSCALLS
+ free_syscalls (pi);
+#endif
+ xfree (pi->saved_entryset);
+ xfree (pi->saved_exitset);
+ xfree (pi);
}
static void
error (msg);
}
+/*
+ * Function: sysset_t_size
+ *
+ * Returns the (complete) size of a sysset_t struct. Normally, this
+ * is just sizeof (syset_t), but in the case of Monterey/64, the actual
+ * size of sysset_t isn't known until runtime.
+ */
+
+static int
+sysset_t_size (procinfo * pi)
+{
+#ifndef DYNAMIC_SYSCALLS
+ return sizeof (sysset_t);
+#else
+ return sizeof (sysset_t) - sizeof (uint64_t)
+ + sizeof (uint64_t) * ((pi->num_syscalls + (8 * sizeof (uint64_t) - 1))
+ / (8 * sizeof (uint64_t)));
+#endif
+}
+
+/* Function: sysset_t_alloc
+
+ Allocate and (partially) initialize a sysset_t struct. */
+
+static sysset_t *
+sysset_t_alloc (procinfo * pi)
+{
+ sysset_t *ret;
+ int size = sysset_t_size (pi);
+ ret = xmalloc (size);
+#ifdef DYNAMIC_SYSCALLS
+ ret->pr_size = (pi->num_syscalls + (8 * sizeof (uint64_t) - 1))
+ / (8 * sizeof (uint64_t));
+#endif
+ return ret;
+}
+
+#ifdef DYNAMIC_SYSCALLS
+
+/* Function: load_syscalls
+
+ Extract syscall numbers and names from /proc/<pid>/sysent. Initialize
+ pi->num_syscalls with the number of syscalls and pi->syscall_names
+ with the names. (Certain numbers may be skipped in which case the
+ names for these numbers will be left as NULL.) */
+
+#define MAX_SYSCALL_NAME_LENGTH 256
+#define MAX_SYSCALLS 65536
+
+static void
+load_syscalls (procinfo *pi)
+{
+ char pathname[MAX_PROC_NAME_SIZE];
+ int sysent_fd;
+ prsysent_t header;
+ prsyscall_t *syscalls;
+ int i, size, maxcall;
+
+ pi->num_syscalls = 0;
+ pi->syscall_names = 0;
+
+ /* Open the file descriptor for the sysent file */
+ sprintf (pathname, "/proc/%d/sysent", pi->pid);
+ sysent_fd = open_with_retry (pathname, O_RDONLY);
+ if (sysent_fd < 0)
+ {
+ error ("load_syscalls: Can't open /proc/%d/sysent", pi->pid);
+ }
+
+ size = sizeof header - sizeof (prsyscall_t);
+ if (read (sysent_fd, &header, size) != size)
+ {
+ error ("load_syscalls: Error reading /proc/%d/sysent", pi->pid);
+ }
+
+ if (header.pr_nsyscalls == 0)
+ {
+ error ("load_syscalls: /proc/%d/sysent contains no syscalls!", pi->pid);
+ }
+
+ size = header.pr_nsyscalls * sizeof (prsyscall_t);
+ syscalls = xmalloc (size);
+
+ if (read (sysent_fd, syscalls, size) != size)
+ {
+ xfree (syscalls);
+ error ("load_syscalls: Error reading /proc/%d/sysent", pi->pid);
+ }
+
+ /* Find maximum syscall number. This may not be the same as
+ pr_nsyscalls since that value refers to the number of entries
+ in the table. (Also, the docs indicate that some system
+ call numbers may be skipped.) */
+
+ maxcall = syscalls[0].pr_number;
+
+ for (i = 1; i < header.pr_nsyscalls; i++)
+ if (syscalls[i].pr_number > maxcall
+ && syscalls[i].pr_nameoff > 0
+ && syscalls[i].pr_number < MAX_SYSCALLS)
+ maxcall = syscalls[i].pr_number;
+
+ pi->num_syscalls = maxcall+1;
+ pi->syscall_names = xmalloc (pi->num_syscalls * sizeof (char *));
+
+ for (i = 0; i < pi->num_syscalls; i++)
+ pi->syscall_names[i] = NULL;
+
+ /* Read the syscall names in */
+ for (i = 0; i < header.pr_nsyscalls; i++)
+ {
+ char namebuf[MAX_SYSCALL_NAME_LENGTH];
+ int nread;
+ int callnum;
+
+ if (syscalls[i].pr_number >= MAX_SYSCALLS
+ || syscalls[i].pr_number < 0
+ || syscalls[i].pr_nameoff <= 0
+ || (lseek (sysent_fd, (off_t) syscalls[i].pr_nameoff, SEEK_SET)
+ != (off_t) syscalls[i].pr_nameoff))
+ continue;
+
+ nread = read (sysent_fd, namebuf, sizeof namebuf);
+ if (nread <= 0)
+ continue;
+
+ callnum = syscalls[i].pr_number;
+
+ if (pi->syscall_names[callnum] != NULL)
+ {
+ /* FIXME: Generate warning */
+ continue;
+ }
+
+ namebuf[nread-1] = '\0';
+ size = strlen (namebuf) + 1;
+ pi->syscall_names[callnum] = xmalloc (size);
+ strncpy (pi->syscall_names[callnum], namebuf, size-1);
+ pi->syscall_names[callnum][size-1] = '\0';
+ }
+
+ close (sysent_fd);
+ xfree (syscalls);
+}
+
+/* Function: free_syscalls
+
+ Free the space allocated for the syscall names from the procinfo
+ structure. */
+
+static void
+free_syscalls (procinfo *pi)
+{
+ if (pi->syscall_names)
+ {
+ int i;
+
+ for (i = 0; i < pi->num_syscalls; i++)
+ if (pi->syscall_names[i] != NULL)
+ xfree (pi->syscall_names[i]);
+
+ xfree (pi->syscall_names);
+ pi->syscall_names = 0;
+ }
+}
+
+/* Function: find_syscall
+
+ Given a name, look up (and return) the corresponding syscall number.
+ If no match is found, return -1. */
+
+static int
+find_syscall (procinfo *pi, char *name)
+{
+ int i;
+ for (i = 0; i < pi->num_syscalls; i++)
+ {
+ if (pi->syscall_names[i] && strcmp (name, pi->syscall_names[i]) == 0)
+ return i;
+ }
+ return -1;
+}
+#endif
+
/* =================== END, STRUCT PROCINFO "MODULE" =================== */
/* =================== /proc "MODULE" =================== */
int proc_parent_pid (procinfo * pi);
int proc_get_nthreads (procinfo * pi);
int proc_get_current_thread (procinfo * pi);
-int proc_set_held_signals (procinfo * pi, sigset_t * sighold);
+int proc_set_held_signals (procinfo * pi, gdb_sigset_t * sighold);
int proc_set_traced_sysexit (procinfo * pi, sysset_t * sysset);
int proc_set_traced_sysentry (procinfo * pi, sysset_t * sysset);
int proc_set_traced_faults (procinfo * pi, fltset_t * fltset);
-int proc_set_traced_signals (procinfo * pi, sigset_t * sigset);
+int proc_set_traced_signals (procinfo * pi, gdb_sigset_t * sigset);
int proc_update_threads (procinfo * pi);
int proc_iterate_over_threads (procinfo * pi,
sysset_t *proc_get_traced_sysexit (procinfo * pi, sysset_t * save);
sysset_t *proc_get_traced_sysentry (procinfo * pi, sysset_t * save);
fltset_t *proc_get_traced_faults (procinfo * pi, fltset_t * save);
-sigset_t *proc_get_traced_signals (procinfo * pi, sigset_t * save);
-sigset_t *proc_get_held_signals (procinfo * pi, sigset_t * save);
-sigset_t *proc_get_pending_signals (procinfo * pi, sigset_t * save);
-struct sigaction *proc_get_signal_actions (procinfo * pi,
- struct sigaction *save);
+gdb_sigset_t *proc_get_traced_signals (procinfo * pi, gdb_sigset_t * save);
+gdb_sigset_t *proc_get_held_signals (procinfo * pi, gdb_sigset_t * save);
+gdb_sigset_t *proc_get_pending_signals (procinfo * pi, gdb_sigset_t * save);
+gdb_sigaction_t *proc_get_signal_actions (procinfo * pi, gdb_sigaction_t *save);
void proc_warn (procinfo * pi, char *func, int line);
void proc_error (procinfo * pi, char *func, int line);
from one operating system to the next...) */
#ifdef PCUNSET
#define GDBRESET PCUNSET
-#endif
+#else
#ifdef PCRESET
#define GDBRESET PCRESET
+#endif
#endif
{
- long arg[2];
+ procfs_ctl_t arg[2];
if (mode == FLAG_SET) /* Set the flag (RLC, FORK, or ASYNC) */
arg[0] = PCSET;
else
{
#ifdef NEW_PROC_API
- long cmd = PCSTOP;
+ procfs_ctl_t cmd = PCSTOP;
win = (write (pi->ctl_fd, (char *) &cmd, sizeof (cmd)) == sizeof (cmd));
#else /* ioctl method */
win = (ioctl (pi->ctl_fd, PIOCSTOP, &pi->prstatus) >= 0);
#ifdef NEW_PROC_API
{
- long cmd = PCWSTOP;
+ procfs_ctl_t cmd = PCWSTOP;
win = (write (pi->ctl_fd, (char *) &cmd, sizeof (cmd)) == sizeof (cmd));
/* We been runnin' and we stopped -- need to update status. */
pi->status_valid = 0;
#ifdef NEW_PROC_API
{
- long cmd[2];
+ procfs_ctl_t cmd[2];
cmd[0] = PCRUN;
cmd[1] = runflags;
*/
int
-proc_set_traced_signals (procinfo *pi, sigset_t *sigset)
+proc_set_traced_signals (procinfo *pi, gdb_sigset_t *sigset)
{
int win;
#ifdef NEW_PROC_API
{
struct {
- long cmd;
+ procfs_ctl_t cmd;
/* Use char array to avoid alignment issues. */
- char sigset[sizeof (sigset_t)];
+ char sigset[sizeof (gdb_sigset_t)];
} arg;
arg.cmd = PCSTRACE;
- memcpy (&arg.sigset, sigset, sizeof (sigset_t));
+ memcpy (&arg.sigset, sigset, sizeof (gdb_sigset_t));
win = (write (pi->ctl_fd, (char *) &arg, sizeof (arg)) == sizeof (arg));
}
#ifdef NEW_PROC_API
{
struct {
- long cmd;
+ procfs_ctl_t cmd;
/* Use char array to avoid alignment issues. */
char fltset[sizeof (fltset_t)];
} arg;
#ifdef NEW_PROC_API
{
- struct {
- long cmd;
+ struct gdb_proc_ctl_pcsentry {
+ procfs_ctl_t cmd;
/* Use char array to avoid alignment issues. */
char sysset[sizeof (sysset_t)];
- } arg;
+ } *argp;
+ int argp_size = sizeof (struct gdb_proc_ctl_pcsentry)
+ - sizeof (sysset_t)
+ + sysset_t_size (pi);
- arg.cmd = PCSENTRY;
- memcpy (&arg.sysset, sysset, sizeof (sysset_t));
+ argp = xmalloc (argp_size);
- win = (write (pi->ctl_fd, (char *) &arg, sizeof (arg)) == sizeof (arg));
+ argp->cmd = PCSENTRY;
+ memcpy (&argp->sysset, sysset, sysset_t_size (pi));
+
+ win = (write (pi->ctl_fd, (char *) argp, argp_size) == argp_size);
+ xfree (argp);
}
#else /* ioctl method */
win = (ioctl (pi->ctl_fd, PIOCSENTRY, sysset) >= 0);
#ifdef NEW_PROC_API
{
- struct {
- long cmd;
+ struct gdb_proc_ctl_pcsexit {
+ procfs_ctl_t cmd;
/* Use char array to avoid alignment issues. */
char sysset[sizeof (sysset_t)];
- } arg;
+ } *argp;
+ int argp_size = sizeof (struct gdb_proc_ctl_pcsexit)
+ - sizeof (sysset_t)
+ + sysset_t_size (pi);
- arg.cmd = PCSEXIT;
- memcpy (&arg.sysset, sysset, sizeof (sysset_t));
+ argp = xmalloc (argp_size);
- win = (write (pi->ctl_fd, (char *) &arg, sizeof (arg)) == sizeof (arg));
+ argp->cmd = PCSEXIT;
+ memcpy (&argp->sysset, sysset, sysset_t_size (pi));
+
+ win = (write (pi->ctl_fd, (char *) argp, argp_size) == argp_size);
+ xfree (argp);
}
#else /* ioctl method */
win = (ioctl (pi->ctl_fd, PIOCSEXIT, sysset) >= 0);
*/
int
-proc_set_held_signals (procinfo *pi, sigset_t *sighold)
+proc_set_held_signals (procinfo *pi, gdb_sigset_t *sighold)
{
int win;
#ifdef NEW_PROC_API
{
struct {
- long cmd;
+ procfs_ctl_t cmd;
/* Use char array to avoid alignment issues. */
- char hold[sizeof (sigset_t)];
+ char hold[sizeof (gdb_sigset_t)];
} arg;
arg.cmd = PCSHOLD;
- memcpy (&arg.hold, sighold, sizeof (sigset_t));
+ memcpy (&arg.hold, sighold, sizeof (gdb_sigset_t));
win = (write (pi->ctl_fd, (void *) &arg, sizeof (arg)) == sizeof (arg));
}
#else
* Will also copy the sigset if 'save' is non-zero.
*/
-sigset_t *
-proc_get_pending_signals (procinfo *pi, sigset_t *save)
+gdb_sigset_t *
+proc_get_pending_signals (procinfo *pi, gdb_sigset_t *save)
{
- sigset_t *ret = NULL;
+ gdb_sigset_t *ret = NULL;
/*
* We should never have to apply this operation to any procinfo
ret = &pi->prstatus.pr_sigpend;
#endif
if (save && ret)
- memcpy (save, ret, sizeof (sigset_t));
+ memcpy (save, ret, sizeof (gdb_sigset_t));
return ret;
}
* Will also copy the sigactionset if 'save' is non-zero.
*/
-struct sigaction *
-proc_get_signal_actions (procinfo *pi, struct sigaction *save)
+gdb_sigaction_t *
+proc_get_signal_actions (procinfo *pi, gdb_sigaction_t *save)
{
- struct sigaction *ret = NULL;
+ gdb_sigaction_t *ret = NULL;
/*
* We should never have to apply this operation to any procinfo
ret = &pi->prstatus.pr_action;
#endif
if (save && ret)
- memcpy (save, ret, sizeof (struct sigaction));
+ memcpy (save, ret, sizeof (gdb_sigaction_t));
return ret;
}
* Will also copy the sigset if 'save' is non-zero.
*/
-sigset_t *
-proc_get_held_signals (procinfo *pi, sigset_t *save)
+gdb_sigset_t *
+proc_get_held_signals (procinfo *pi, gdb_sigset_t *save)
{
- sigset_t *ret = NULL;
+ gdb_sigset_t *ret = NULL;
/*
* We should never have to apply this operation to any procinfo
#endif /* UNIXWARE */
#else /* not NEW_PROC_API */
{
- static sigset_t sigheld;
+ static gdb_sigset_t sigheld;
if (ioctl (pi->ctl_fd, PIOCGHOLD, &sigheld) >= 0)
ret = &sigheld;
}
#endif /* NEW_PROC_API */
if (save && ret)
- memcpy (save, ret, sizeof (sigset_t));
+ memcpy (save, ret, sizeof (gdb_sigset_t));
return ret;
}
* Will also copy the sigset if 'save' is non-zero.
*/
-sigset_t *
-proc_get_traced_signals (procinfo *pi, sigset_t *save)
+gdb_sigset_t *
+proc_get_traced_signals (procinfo *pi, gdb_sigset_t *save)
{
- sigset_t *ret = NULL;
+ gdb_sigset_t *ret = NULL;
/*
* We should never have to apply this operation to any procinfo
ret = &pi->prstatus.pr_sigtrace;
#else
{
- static sigset_t sigtrace;
+ static gdb_sigset_t sigtrace;
if (ioctl (pi->ctl_fd, PIOCGTRACE, &sigtrace) >= 0)
ret = &sigtrace;
}
#endif
if (save && ret)
- memcpy (save, ret, sizeof (sigset_t));
+ memcpy (save, ret, sizeof (gdb_sigset_t));
return ret;
}
int
proc_trace_signal (procinfo *pi, int signo)
{
- sigset_t temp;
+ gdb_sigset_t temp;
/*
* We should never have to apply this operation to any procinfo
int
proc_ignore_signal (procinfo *pi, int signo)
{
- sigset_t temp;
+ gdb_sigset_t temp;
/*
* We should never have to apply this operation to any procinfo
if (!proc_get_status (pi))
return NULL;
+#ifndef DYNAMIC_SYSCALLS
ret = &pi->prstatus.pr_sysentry;
-#else
+#else /* DYNAMIC_SYSCALLS */
+ {
+ static sysset_t *sysentry;
+ size_t size;
+
+ if (!sysentry)
+ sysentry = sysset_t_alloc (pi);
+ ret = sysentry;
+ if (pi->status_fd == 0 && open_procinfo_files (pi, FD_STATUS) == 0)
+ return NULL;
+ if (pi->prstatus.pr_sysentry_offset == 0)
+ {
+ gdb_premptysysset (sysentry);
+ }
+ else
+ {
+ int rsize;
+
+ if (lseek (pi->status_fd, (off_t) pi->prstatus.pr_sysentry_offset,
+ SEEK_SET)
+ != (off_t) pi->prstatus.pr_sysentry_offset)
+ return NULL;
+ size = sysset_t_size (pi);
+ gdb_premptysysset (sysentry);
+ rsize = read (pi->status_fd, sysentry, size);
+ if (rsize < 0)
+ return NULL;
+ }
+ }
+#endif /* DYNAMIC_SYSCALLS */
+#else /* !NEW_PROC_API */
{
static sysset_t sysentry;
if (ioctl (pi->ctl_fd, PIOCGENTRY, &sysentry) >= 0)
ret = &sysentry;
}
-#endif
+#endif /* NEW_PROC_API */
if (save && ret)
- memcpy (save, ret, sizeof (sysset_t));
+ memcpy (save, ret, sysset_t_size (pi));
return ret;
}
if (!proc_get_status (pi))
return NULL;
+#ifndef DYNAMIC_SYSCALLS
ret = &pi->prstatus.pr_sysexit;
+#else /* DYNAMIC_SYSCALLS */
+ {
+ static sysset_t *sysexit;
+ size_t size;
+
+ if (!sysexit)
+ sysexit = sysset_t_alloc (pi);
+ ret = sysexit;
+ if (pi->status_fd == 0 && open_procinfo_files (pi, FD_STATUS) == 0)
+ return NULL;
+ if (pi->prstatus.pr_sysexit_offset == 0)
+ {
+ gdb_premptysysset (sysexit);
+ }
+ else
+ {
+ int rsize;
+
+ if (lseek (pi->status_fd, (off_t) pi->prstatus.pr_sysexit_offset, SEEK_SET)
+ != (off_t) pi->prstatus.pr_sysexit_offset)
+ return NULL;
+ size = sysset_t_size (pi);
+ gdb_premptysysset (sysexit);
+ rsize = read (pi->status_fd, sysexit, size);
+ if (rsize < 0)
+ return NULL;
+ }
+ }
+#endif /* DYNAMIC_SYSCALLS */
#else
{
static sysset_t sysexit;
}
#endif
if (save && ret)
- memcpy (save, ret, sizeof (sysset_t));
+ memcpy (save, ret, sysset_t_size (pi));
return ret;
}
#ifdef NEW_PROC_API
{
- long cmd = PCCFAULT;
+ procfs_ctl_t cmd = PCCFAULT;
win = (write (pi->ctl_fd, (void *) &cmd, sizeof (cmd)) == sizeof (cmd));
}
#else
{
int win;
struct {
- long cmd;
+ procfs_ctl_t cmd;
/* Use char array to avoid alignment issues. */
- char sinfo[sizeof (struct siginfo)];
+ char sinfo[sizeof (gdb_siginfo_t)];
} arg;
- struct siginfo *mysinfo;
+ gdb_siginfo_t *mysinfo;
/*
* We should never have to apply this operation to any procinfo
#endif
/* The pointer is just a type alias. */
- mysinfo = (struct siginfo *) &arg.sinfo;
+ mysinfo = (gdb_siginfo_t *) &arg.sinfo;
mysinfo->si_signo = signo;
mysinfo->si_code = 0;
mysinfo->si_pid = getpid (); /* ?why? */
#ifdef NEW_PROC_API
{
struct {
- long cmd;
+ procfs_ctl_t cmd;
/* Use char array to avoid alignment issues. */
- char sinfo[sizeof (struct siginfo)];
+ char sinfo[sizeof (gdb_siginfo_t)];
} arg;
- struct siginfo *mysinfo;
+ gdb_siginfo_t *mysinfo;
arg.cmd = PCSSIG;
/* The pointer is just a type alias. */
- mysinfo = (struct siginfo *) &arg.sinfo;
+ mysinfo = (gdb_siginfo_t *) &arg.sinfo;
mysinfo->si_signo = 0;
mysinfo->si_code = 0;
mysinfo->si_errno = 0;
{
#ifdef NEW_PROC_API
struct {
- long cmd;
+ procfs_ctl_t cmd;
/* Use char array to avoid alignment issues. */
char gregs[sizeof (gdb_gregset_t)];
} arg;
{
#ifdef NEW_PROC_API
struct {
- long cmd;
+ procfs_ctl_t cmd;
/* Use char array to avoid alignment issues. */
char fpregs[sizeof (gdb_fpregset_t)];
} arg;
else
{
#ifdef NEW_PROC_API
- long cmd[2];
+ procfs_ctl_t cmd[2];
cmd[0] = PCKILL;
cmd[1] = signo;
return 0;
#else
struct {
- long cmd;
+ procfs_ctl_t cmd;
char watch[sizeof (prwatch_t)];
} arg;
prwatch_t *pwatch;
It doesn't get called that often... and if I open it
every time, I don't need to lseek it. */
int
-proc_iterate_over_mappings (func)
- int (*func) (int, CORE_ADDR);
+proc_iterate_over_mappings (int (*func) (int, CORE_ADDR))
{
struct prmap *map;
procinfo *pi;
int funcstat = 0;
int fd;
- pi = find_procinfo_or_die (PIDGET (inferior_pid), 0);
+ pi = find_procinfo_or_die (PIDGET (inferior_ptid), 0);
#ifdef NEW_PROC_API
/* Open map fd. */
sprintf (pathname, "/proc/%d/map", pi->pid);
- if ((map_fd = open (pathname, O_RDONLY)) < 0)
+ if ((map_fd = open_with_retry (pathname, O_RDONLY)) < 0)
proc_error (pi, "proc_iterate_over_mappings (open)", __LINE__);
/* Make sure it gets closed again. */
{
sprintf (name, "/proc/%d/object/%s", pi->pid, map->pr_mapname);
/* Note: caller's responsibility to close this fd! */
- fd = open (name, O_RDONLY);
+ fd = open_with_retry (name, O_RDONLY);
/* Note: we don't test the above call for failure;
we just pass the FD on as given. Sometimes there is
no file, so the ioctl may return failure, but that's
/* Open the file descriptor for the LDT table. */
sprintf (pathname, "/proc/%d/ldt", pi->pid);
- if ((fd = open (pathname, O_RDONLY)) < 0)
+ if ((fd = open_with_retry (pathname, O_RDONLY)) < 0)
{
proc_warn (pi, "proc_get_LDT_entry (open)", __LINE__);
return NULL;
if ((nlwp = proc_get_nthreads (pi)) <= 1)
return 1; /* Process is not multi-threaded; nothing to do. */
- if ((prstatus = (gdb_prstatus_t *)
- malloc (sizeof (gdb_prstatus_t) * (nlwp + 1))) == 0)
- perror_with_name ("procfs: malloc failed in update_threads");
+ prstatus = xmalloc (sizeof (gdb_prstatus_t) * (nlwp + 1));
- old_chain = make_cleanup (free, prstatus);
+ old_chain = make_cleanup (xfree, prstatus);
if (ioctl (pi->ctl_fd, PIOCLSTATUS, prstatus) < 0)
proc_error (pi, "update_threads (PIOCLSTATUS)", __LINE__);
if (nthreads < 2)
return 0; /* nothing to do for 1 or fewer threads */
- if ((threads = malloc (nthreads * sizeof (tid_t))) == NULL)
- proc_error (pi, "update_threads, malloc", __LINE__);
+ threads = xmalloc (nthreads * sizeof (tid_t));
if (ioctl (pi->ctl_fd, PIOCTLIST, threads) < 0)
proc_error (pi, "procfs: update_threads (PIOCTLIST)", __LINE__);
*/
int
-proc_iterate_over_threads (pi, func, ptr)
- procinfo *pi;
- int (*func) (procinfo *, procinfo *, void *);
- void *ptr;
+proc_iterate_over_threads (procinfo *pi,
+ int (*func) (procinfo *, procinfo *, void *),
+ void *ptr)
{
procinfo *thread, *next;
int retval = 0;
* Here are all of the gdb target vector functions and their friends.
*/
-static int do_attach (int pid);
+static ptid_t do_attach (ptid_t ptid);
static void do_detach (int signo);
-static int register_gdb_signals (procinfo *, sigset_t *);
+static int register_gdb_signals (procinfo *, gdb_sigset_t *);
/*
* Function: procfs_debug_inferior
procfs_debug_inferior (procinfo *pi)
{
fltset_t traced_faults;
- sigset_t traced_signals;
- sysset_t traced_syscall_entries;
- sysset_t traced_syscall_exits;
+ gdb_sigset_t traced_signals;
+ sysset_t *traced_syscall_entries;
+ sysset_t *traced_syscall_exits;
+ int status;
#ifdef PROCFS_DONT_TRACE_FAULTS
/* On some systems (OSF), we don't trace hardware faults.
if (!register_gdb_signals (pi, &traced_signals))
return __LINE__;
+
/* Register to trace the 'exit' system call (on entry). */
- premptyset (&traced_syscall_entries);
- praddset (&traced_syscall_entries, SYS_exit);
+ traced_syscall_entries = sysset_t_alloc (pi);
+ gdb_premptysysset (traced_syscall_entries);
+#ifdef SYS_exit
+ gdb_praddsysset (traced_syscall_entries, SYS_exit);
+#endif
#ifdef SYS_lwpexit
- praddset (&traced_syscall_entries, SYS_lwpexit); /* And _lwp_exit... */
+ gdb_praddsysset (traced_syscall_entries, SYS_lwpexit); /* And _lwp_exit... */
#endif
#ifdef SYS_lwp_exit
- praddset (&traced_syscall_entries, SYS_lwp_exit);
+ gdb_praddsysset (traced_syscall_entries, SYS_lwp_exit);
+#endif
+#ifdef DYNAMIC_SYSCALLS
+ {
+ int callnum = find_syscall (pi, "_exit");
+ if (callnum >= 0)
+ gdb_praddsysset (traced_syscall_entries, callnum);
+ }
#endif
- if (!proc_set_traced_sysentry (pi, &traced_syscall_entries))
+ status = proc_set_traced_sysentry (pi, traced_syscall_entries);
+ xfree (traced_syscall_entries);
+ if (!status)
return __LINE__;
#ifdef PRFS_STOPEXEC /* defined on OSF */
names. On the SGI, for example, there is no SYS_exec, but there
*is* a SYS_execv. So, we try to account for that. */
- premptyset (&traced_syscall_exits);
+ traced_syscall_exits = sysset_t_alloc (pi);
+ gdb_premptysysset (traced_syscall_exits);
#ifdef SYS_exec
- praddset (&traced_syscall_exits, SYS_exec);
+ gdb_praddsysset (traced_syscall_exits, SYS_exec);
#endif
#ifdef SYS_execve
- praddset (&traced_syscall_exits, SYS_execve);
+ gdb_praddsysset (traced_syscall_exits, SYS_execve);
#endif
#ifdef SYS_execv
- praddset (&traced_syscall_exits, SYS_execv);
+ gdb_praddsysset (traced_syscall_exits, SYS_execv);
#endif
#ifdef SYS_lwpcreate
- praddset (&traced_syscall_exits, SYS_lwpcreate);
- praddset (&traced_syscall_exits, SYS_lwpexit);
+ gdb_praddsysset (traced_syscall_exits, SYS_lwpcreate);
+ gdb_praddsysset (traced_syscall_exits, SYS_lwpexit);
#endif
#ifdef SYS_lwp_create /* FIXME: once only, please */
- praddset (&traced_syscall_exits, SYS_lwp_create);
- praddset (&traced_syscall_exits, SYS_lwp_exit);
+ gdb_praddsysset (traced_syscall_exits, SYS_lwp_create);
+ gdb_praddsysset (traced_syscall_exits, SYS_lwp_exit);
#endif
+#ifdef DYNAMIC_SYSCALLS
+ {
+ int callnum = find_syscall (pi, "execve");
+ if (callnum >= 0)
+ gdb_praddsysset (traced_syscall_exits, callnum);
+ callnum = find_syscall (pi, "ra_execve");
+ if (callnum >= 0)
+ gdb_praddsysset (traced_syscall_exits, callnum);
+ }
+#endif
- if (!proc_set_traced_sysexit (pi, &traced_syscall_exits))
+ status = proc_set_traced_sysexit (pi, traced_syscall_exits);
+ xfree (traced_syscall_exits);
+ if (!status)
return __LINE__;
#endif /* PRFS_STOPEXEC */
if (exec_file)
printf_filtered ("Attaching to program `%s', %s\n",
- exec_file, target_pid_to_str (pid));
+ exec_file, target_pid_to_str (pid_to_ptid (pid)));
else
- printf_filtered ("Attaching to %s\n", target_pid_to_str (pid));
+ printf_filtered ("Attaching to %s\n",
+ target_pid_to_str (pid_to_ptid (pid)));
fflush (stdout);
}
- inferior_pid = do_attach (pid);
+ inferior_ptid = do_attach (pid_to_ptid (pid));
push_target (&procfs_ops);
}
if (exec_file == 0)
exec_file = "";
printf_filtered ("Detaching from program: %s %s\n",
- exec_file, target_pid_to_str (inferior_pid));
+ exec_file, target_pid_to_str (inferior_ptid));
fflush (stdout);
}
if (args)
signo = atoi (args);
do_detach (signo);
- inferior_pid = 0;
+ inferior_ptid = null_ptid;
unpush_target (&procfs_ops); /* Pop out of handling an inferior */
}
-static int
-do_attach (int pid)
+static ptid_t
+do_attach (ptid_t ptid)
{
procinfo *pi;
int fail;
- if ((pi = create_procinfo (pid, 0)) == NULL)
+ if ((pi = create_procinfo (PIDGET (ptid), 0)) == NULL)
perror ("procfs: out of memory in 'attach'");
if (!open_procinfo_files (pi, FD_CTL))
{
fprintf_filtered (gdb_stderr, "procfs:%d -- ", __LINE__);
sprintf (errmsg, "do_attach: couldn't open /proc file for process %d",
- pid);
+ PIDGET (ptid));
dead_procinfo (pi, errmsg, NOKILL);
}
dead_procinfo (pi, "do_attach: couldn't save traced faults.", NOKILL);
if (!proc_get_traced_signals (pi, &pi->saved_sigset))
dead_procinfo (pi, "do_attach: couldn't save traced signals.", NOKILL);
- if (!proc_get_traced_sysentry (pi, &pi->saved_entryset))
+ if (!proc_get_traced_sysentry (pi, pi->saved_entryset))
dead_procinfo (pi, "do_attach: couldn't save traced syscall entries.",
NOKILL);
- if (!proc_get_traced_sysexit (pi, &pi->saved_exitset))
+ if (!proc_get_traced_sysexit (pi, pi->saved_exitset))
dead_procinfo (pi, "do_attach: couldn't save traced syscall exits.",
NOKILL);
if (!proc_get_held_signals (pi, &pi->saved_sighold))
procinfo *pi;
/* Find procinfo for the main process */
- pi = find_procinfo_or_die (PIDGET (inferior_pid), 0); /* FIXME: threads */
+ pi = find_procinfo_or_die (PIDGET (inferior_ptid), 0); /* FIXME: threads */
if (signo)
if (!proc_set_current_signal (pi, signo))
proc_warn (pi, "do_detach, set_current_signal", __LINE__);
if (!proc_set_traced_faults (pi, &pi->saved_fltset))
proc_warn (pi, "do_detach, set_traced_faults", __LINE__);
- if (!proc_set_traced_sysentry (pi, &pi->saved_entryset))
+ if (!proc_set_traced_sysentry (pi, pi->saved_entryset))
proc_warn (pi, "do_detach, set_traced_sysentry", __LINE__);
- if (!proc_set_traced_sysexit (pi, &pi->saved_exitset))
+ if (!proc_set_traced_sysexit (pi, pi->saved_exitset))
proc_warn (pi, "do_detach, set_traced_sysexit", __LINE__);
if (!proc_set_held_signals (pi, &pi->saved_sighold))
int pid;
int tid;
- pid = PIDGET (inferior_pid);
- tid = TIDGET (inferior_pid);
+ pid = PIDGET (inferior_ptid);
+ tid = TIDGET (inferior_ptid);
/* First look up procinfo for the main process. */
pi = find_procinfo_or_die (pid, 0);
/* If the event thread is not the same as GDB's requested thread
- (ie. inferior_pid), then look up procinfo for the requested
+ (ie. inferior_ptid), then look up procinfo for the requested
thread. */
if ((tid != 0) &&
(tid != proc_get_current_thread (pi)))
if (pi == NULL)
error ("procfs: fetch_registers failed to find procinfo for %s",
- target_pid_to_str (inferior_pid));
+ target_pid_to_str (inferior_ptid));
if ((gregs = proc_get_gregs (pi)) == NULL)
proc_error (pi, "fetch_registers, get_gregs", __LINE__);
int pid;
int tid;
- pid = PIDGET (inferior_pid);
- tid = TIDGET (inferior_pid);
+ pid = PIDGET (inferior_ptid);
+ tid = TIDGET (inferior_ptid);
/* First find procinfo for main process */
pi = find_procinfo_or_die (pid, 0);
/* If current lwp for process is not the same as requested thread
- (ie. inferior_pid), then find procinfo for the requested thread. */
+ (ie. inferior_ptid), then find procinfo for the requested thread. */
if ((tid != 0) &&
(tid != proc_get_current_thread (pi)))
if (pi == NULL)
error ("procfs: store_registers: failed to find procinfo for %s",
- target_pid_to_str (inferior_pid));
+ target_pid_to_str (inferior_ptid));
if ((gregs = proc_get_gregs (pi)) == NULL)
proc_error (pi, "store_registers, get_gregs", __LINE__);
}
}
+static int
+syscall_is_lwp_exit (procinfo *pi, int scall)
+{
+
+#ifdef SYS_lwp_exit
+ if (scall == SYS_lwp_exit)
+ return 1;
+#endif
+#ifdef SYS_lwpexit
+ if (scall == SYS_lwpexit)
+ return 1;
+#endif
+ return 0;
+}
+
+static int
+syscall_is_exit (procinfo *pi, int scall)
+{
+#ifdef SYS_exit
+ if (scall == SYS_exit)
+ return 1;
+#endif
+#ifdef DYNAMIC_SYSCALLS
+ if (find_syscall (pi, "_exit") == scall)
+ return 1;
+#endif
+ return 0;
+}
+
+static int
+syscall_is_exec (procinfo *pi, int scall)
+{
+#ifdef SYS_exec
+ if (scall == SYS_exec)
+ return 1;
+#endif
+#ifdef SYS_execv
+ if (scall == SYS_execv)
+ return 1;
+#endif
+#ifdef SYS_execve
+ if (scall == SYS_execve)
+ return 1;
+#endif
+#ifdef DYNAMIC_SYSCALLS
+ if (find_syscall (pi, "_execve"))
+ return 1;
+ if (find_syscall (pi, "ra_execve"))
+ return 1;
+#endif
+ return 0;
+}
+
+static int
+syscall_is_lwp_create (procinfo *pi, int scall)
+{
+#ifdef SYS_lwp_create
+ if (scall == SYS_lwp_create)
+ return 1;
+#endif
+#ifdef SYS_lwpcreate
+ if (scall == SYS_lwpcreate)
+ return 1;
+#endif
+ return 0;
+}
+
/*
* Function: target_wait
*
* event codes are returned thru a pointer parameter.
*/
-static int
-procfs_wait (int pid, struct target_waitstatus *status)
+static ptid_t
+procfs_wait (ptid_t ptid, struct target_waitstatus *status)
{
/* First cut: loosely based on original version 2.1 */
procinfo *pi;
- int temp, wstat;
- int retval;
+ int wstat;
+ int temp_tid;
+ ptid_t retval, temp_ptid;
int why, what, flags;
int retry = 0;
retry++;
wstat = 0;
- retval = -1;
+ retval = pid_to_ptid (-1);
/* Find procinfo for main process */
- pi = find_procinfo_or_die (PIDGET (inferior_pid), 0);
+ pi = find_procinfo_or_die (PIDGET (inferior_ptid), 0);
if (pi)
{
/* We must assume that the status is stale now... */
/* wait_for_stop failed: has the child terminated? */
if (errno == ENOENT)
{
+ int wait_retval;
+
/* /proc file not found; presumably child has terminated. */
- retval = wait (&wstat); /* "wait" for the child's exit */
+ wait_retval = wait (&wstat); /* "wait" for the child's exit */
- if (retval != PIDGET (inferior_pid)) /* wrong child? */
+ if (wait_retval != PIDGET (inferior_ptid)) /* wrong child? */
error ("procfs: couldn't stop process %d: wait returned %d\n",
- inferior_pid, retval);
+ PIDGET (inferior_ptid), wait_retval);
/* FIXME: might I not just use waitpid?
Or try find_procinfo to see if I know about this child? */
+ retval = pid_to_ptid (wait_retval);
}
+ else if (errno == EINTR)
+ goto wait_again;
else
{
/* Unknown error from wait_for_stop. */
wstat = (what << 8) | 0177;
break;
case PR_SYSENTRY:
- switch (what) {
-#ifdef SYS_lwp_exit
- case SYS_lwp_exit:
-#endif
-#ifdef SYS_lwpexit
- case SYS_lwpexit:
-#endif
-#if defined (SYS_lwp_exit) || defined (SYS_lwpexit)
- printf_filtered ("[%s exited]\n",
- target_pid_to_str (retval));
- delete_thread (retval);
- status->kind = TARGET_WAITKIND_SPURIOUS;
- return retval;
-#endif /* _lwp_exit */
-
- case SYS_exit:
- /* Handle SYS_exit call only */
- /* Stopped at entry to SYS_exit.
- Make it runnable, resume it, then use
- the wait system call to get its exit code.
- Proc_run_process always clears the current
- fault and signal.
- Then return its exit status. */
- pi->status_valid = 0;
- wstat = 0;
- /* FIXME: what we should do is return
- TARGET_WAITKIND_SPURIOUS. */
- if (!proc_run_process (pi, 0, 0))
- proc_error (pi, "target_wait, run_process", __LINE__);
- if (attach_flag)
- {
- /* Don't call wait: simulate waiting for exit,
- return a "success" exit code. Bogus: what if
- it returns something else? */
- wstat = 0;
- retval = inferior_pid; /* ? ? ? */
- }
- else
- {
- int temp = wait (&wstat);
-
- /* FIXME: shouldn't I make sure I get the right
- event from the right process? If (for
- instance) I have killed an earlier inferior
- process but failed to clean up after it
- somehow, I could get its termination event
- here. */
-
- /* If wait returns -1, that's what we return to GDB. */
- if (temp < 0)
- retval = temp;
- }
- break;
- default:
- printf_filtered ("procfs: trapped on entry to ");
- proc_prettyprint_syscall (proc_what (pi), 0);
- printf_filtered ("\n");
-#ifndef PIOCSSPCACT
+ if (syscall_is_lwp_exit (pi, what))
{
- long i, nsysargs, *sysargs;
-
- if ((nsysargs = proc_nsysarg (pi)) > 0 &&
- (sysargs = proc_sysargs (pi)) != NULL)
+ printf_filtered ("[%s exited]\n",
+ target_pid_to_str (retval));
+ delete_thread (retval);
+ status->kind = TARGET_WAITKIND_SPURIOUS;
+ return retval;
+ }
+ else if (syscall_is_exit (pi, what))
+ {
+ /* Handle SYS_exit call only */
+ /* Stopped at entry to SYS_exit.
+ Make it runnable, resume it, then use
+ the wait system call to get its exit code.
+ Proc_run_process always clears the current
+ fault and signal.
+ Then return its exit status. */
+ pi->status_valid = 0;
+ wstat = 0;
+ /* FIXME: what we should do is return
+ TARGET_WAITKIND_SPURIOUS. */
+ if (!proc_run_process (pi, 0, 0))
+ proc_error (pi, "target_wait, run_process", __LINE__);
+ if (attach_flag)
{
- printf_filtered ("%ld syscall arguments:\n", nsysargs);
- for (i = 0; i < nsysargs; i++)
- printf_filtered ("#%ld: 0x%08lx\n",
- i, sysargs[i]);
+ /* Don't call wait: simulate waiting for exit,
+ return a "success" exit code. Bogus: what if
+ it returns something else? */
+ wstat = 0;
+ retval = inferior_ptid; /* ? ? ? */
+ }
+ else
+ {
+ int temp = wait (&wstat);
+
+ /* FIXME: shouldn't I make sure I get the right
+ event from the right process? If (for
+ instance) I have killed an earlier inferior
+ process but failed to clean up after it
+ somehow, I could get its termination event
+ here. */
+
+ /* If wait returns -1, that's what we return to GDB. */
+ if (temp < 0)
+ retval = pid_to_ptid (temp);
}
-
}
-#endif
- if (status)
- {
- /* How to exit gracefully, returning "unknown event" */
- status->kind = TARGET_WAITKIND_SPURIOUS;
- return inferior_pid;
- }
- else
+ else
+ {
+ printf_filtered ("procfs: trapped on entry to ");
+ proc_prettyprint_syscall (proc_what (pi), 0);
+ printf_filtered ("\n");
+#ifndef PIOCSSPCACT
{
- /* How to keep going without returning to wfi: */
- target_resume (pid, 0, TARGET_SIGNAL_0);
- goto wait_again;
- }
- break;
- }
- break;
- case PR_SYSEXIT:
- switch (what) {
-#ifdef SYS_exec
- case SYS_exec:
-#endif
-#ifdef SYS_execv
- case SYS_execv:
-#endif
-#ifdef SYS_execve
- case SYS_execve:
-#endif
- /* Hopefully this is our own "fork-child" execing
- the real child. Hoax this event into a trap, and
- GDB will see the child about to execute its start
- address. */
- wstat = (SIGTRAP << 8) | 0177;
- break;
-#ifdef SYS_lwp_create
- case SYS_lwp_create:
-#endif
-#ifdef SYS_lwpcreate
- case SYS_lwpcreate:
-#endif
-#if defined(SYS_lwp_create) || defined(SYS_lwpcreate)
- /*
- * This syscall is somewhat like fork/exec.
- * We will get the event twice: once for the parent LWP,
- * and once for the child. We should already know about
- * the parent LWP, but the child will be new to us. So,
- * whenever we get this event, if it represents a new
- * thread, simply add the thread to the list.
- */
+ long i, nsysargs, *sysargs;
- /* If not in procinfo list, add it. */
- temp = proc_get_current_thread (pi);
- if (!find_procinfo (pi->pid, temp))
- create_procinfo (pi->pid, temp);
+ if ((nsysargs = proc_nsysarg (pi)) > 0 &&
+ (sysargs = proc_sysargs (pi)) != NULL)
+ {
+ printf_filtered ("%ld syscall arguments:\n", nsysargs);
+ for (i = 0; i < nsysargs; i++)
+ printf_filtered ("#%ld: 0x%08lx\n",
+ i, sysargs[i]);
+ }
- temp = MERGEPID (pi->pid, temp);
- /* If not in GDB's thread list, add it. */
- if (!in_thread_list (temp))
- {
- printf_filtered ("[New %s]\n", target_pid_to_str (temp));
- add_thread (temp);
}
- /* Return to WFI, but tell it to immediately resume. */
- status->kind = TARGET_WAITKIND_SPURIOUS;
- return inferior_pid;
-#endif /* _lwp_create */
-
-#ifdef SYS_lwp_exit
- case SYS_lwp_exit:
-#endif
-#ifdef SYS_lwpexit
- case SYS_lwpexit:
-#endif
-#if defined (SYS_lwp_exit) || defined (SYS_lwpexit)
- printf_filtered ("[%s exited]\n",
- target_pid_to_str (retval));
- delete_thread (retval);
- status->kind = TARGET_WAITKIND_SPURIOUS;
- return retval;
-#endif /* _lwp_exit */
-
-#ifdef SYS_sproc
- case SYS_sproc:
- /* Nothing to do here for now. The old procfs
- seemed to use this event to handle threads on
- older (non-LWP) systems, where I'm assuming that
- threads were actually separate processes. Irix,
- maybe? Anyway, low priority for now. */
#endif
-#ifdef SYS_fork
- case SYS_fork:
- /* FIXME: do we need to handle this? Investigate. */
-#endif
-#ifdef SYS_vfork
- case SYS_vfork:
- /* FIXME: see above. */
-#endif
- default:
- printf_filtered ("procfs: trapped on exit from ");
- proc_prettyprint_syscall (proc_what (pi), 0);
- printf_filtered ("\n");
-#ifndef PIOCSSPCACT
+ if (status)
+ {
+ /* How to exit gracefully, returning "unknown event" */
+ status->kind = TARGET_WAITKIND_SPURIOUS;
+ return inferior_ptid;
+ }
+ else
+ {
+ /* How to keep going without returning to wfi: */
+ target_resume (ptid, 0, TARGET_SIGNAL_0);
+ goto wait_again;
+ }
+ }
+ break;
+ case PR_SYSEXIT:
+ if (syscall_is_exec (pi, what))
+ {
+ /* Hopefully this is our own "fork-child" execing
+ the real child. Hoax this event into a trap, and
+ GDB will see the child about to execute its start
+ address. */
+ wstat = (SIGTRAP << 8) | 0177;
+ }
+ else if (syscall_is_lwp_create (pi, what))
{
- long i, nsysargs, *sysargs;
+ /*
+ * This syscall is somewhat like fork/exec.
+ * We will get the event twice: once for the parent LWP,
+ * and once for the child. We should already know about
+ * the parent LWP, but the child will be new to us. So,
+ * whenever we get this event, if it represents a new
+ * thread, simply add the thread to the list.
+ */
+
+ /* If not in procinfo list, add it. */
+ temp_tid = proc_get_current_thread (pi);
+ if (!find_procinfo (pi->pid, temp_tid))
+ create_procinfo (pi->pid, temp_tid);
- if ((nsysargs = proc_nsysarg (pi)) > 0 &&
- (sysargs = proc_sysargs (pi)) != NULL)
+ temp_ptid = MERGEPID (pi->pid, temp_tid);
+ /* If not in GDB's thread list, add it. */
+ if (!in_thread_list (temp_ptid))
{
- printf_filtered ("%ld syscall arguments:\n", nsysargs);
- for (i = 0; i < nsysargs; i++)
- printf_filtered ("#%ld: 0x%08lx\n",
- i, sysargs[i]);
+ printf_filtered ("[New %s]\n",
+ target_pid_to_str (temp_ptid));
+ add_thread (temp_ptid);
}
+ /* Return to WFI, but tell it to immediately resume. */
+ status->kind = TARGET_WAITKIND_SPURIOUS;
+ return inferior_ptid;
}
+ else if (syscall_is_lwp_exit (pi, what))
+ {
+ printf_filtered ("[%s exited]\n",
+ target_pid_to_str (retval));
+ delete_thread (retval);
+ status->kind = TARGET_WAITKIND_SPURIOUS;
+ return retval;
+ }
+ else if (0)
+ {
+ /* FIXME: Do we need to handle SYS_sproc,
+ SYS_fork, or SYS_vfork here? The old procfs
+ seemed to use this event to handle threads on
+ older (non-LWP) systems, where I'm assuming
+ that threads were actually separate processes.
+ Irix, maybe? Anyway, low priority for now. */
+ }
+ else
+ {
+ printf_filtered ("procfs: trapped on exit from ");
+ proc_prettyprint_syscall (proc_what (pi), 0);
+ printf_filtered ("\n");
+#ifndef PIOCSSPCACT
+ {
+ long i, nsysargs, *sysargs;
+
+ if ((nsysargs = proc_nsysarg (pi)) > 0 &&
+ (sysargs = proc_sysargs (pi)) != NULL)
+ {
+ printf_filtered ("%ld syscall arguments:\n", nsysargs);
+ for (i = 0; i < nsysargs; i++)
+ printf_filtered ("#%ld: 0x%08lx\n",
+ i, sysargs[i]);
+ }
+ }
#endif
- status->kind = TARGET_WAITKIND_SPURIOUS;
- return inferior_pid;
- }
+ status->kind = TARGET_WAITKIND_SPURIOUS;
+ return inferior_ptid;
+ }
break;
case PR_REQUESTED:
#if 0 /* FIXME */
else
{
/* If not in procinfo list, add it. */
- temp = proc_get_current_thread (pi);
- if (!find_procinfo (pi->pid, temp))
- create_procinfo (pi->pid, temp);
+ temp_tid = proc_get_current_thread (pi);
+ if (!find_procinfo (pi->pid, temp_tid))
+ create_procinfo (pi->pid, temp_tid);
/* If not in GDB's thread list, add it. */
- temp = MERGEPID (pi->pid, temp);
- if (!in_thread_list (temp))
+ temp_ptid = MERGEPID (pi->pid, temp_tid);
+ if (!in_thread_list (temp_ptid))
{
printf_filtered ("[New %s]\n",
- target_pid_to_str (temp));
- add_thread (temp);
+ target_pid_to_str (temp_ptid));
+ add_thread (temp_ptid);
}
status->kind = TARGET_WAITKIND_STOPPED;
break;
case FLTPAGE: /* Recoverable page fault */
default: /* FIXME: use si_signo if possible for fault */
- retval = -1;
+ retval = pid_to_ptid (-1);
printf_filtered ("procfs:%d -- ", __LINE__);
printf_filtered ("child stopped for unknown reason:\n");
proc_prettyprint_why (why, what, 1);
* Got this far without error:
* If retval isn't in the threads database, add it.
*/
- if (retval > 0 &&
- retval != inferior_pid &&
+ if (PIDGET (retval) > 0 &&
+ !ptid_equal (retval, inferior_ptid) &&
!in_thread_list (retval))
{
/*
/* In addition, it's possible that this is the first
* new thread we've seen, in which case we may not
- * have created entries for inferior_pid yet.
+ * have created entries for inferior_ptid yet.
*/
- if (TIDGET (inferior_pid) != 0)
+ if (TIDGET (inferior_ptid) != 0)
{
- if (!in_thread_list (inferior_pid))
- add_thread (inferior_pid);
- if (find_procinfo (PIDGET (inferior_pid),
- TIDGET (inferior_pid)) == NULL)
- create_procinfo (PIDGET (inferior_pid),
- TIDGET (inferior_pid));
+ if (!in_thread_list (inferior_ptid))
+ add_thread (inferior_ptid);
+ if (find_procinfo (PIDGET (inferior_ptid),
+ TIDGET (inferior_ptid)) == NULL)
+ create_procinfo (PIDGET (inferior_ptid),
+ TIDGET (inferior_ptid));
}
}
}
return retval;
}
+/* Transfer LEN bytes between GDB address MYADDR and target address
+ MEMADDR. If DOWRITE is non-zero, transfer them to the target,
+ otherwise transfer them from the target. TARGET is unused.
+
+ The return value is 0 if an error occurred or no bytes were
+ transferred. Otherwise, it will be a positive value which
+ indicates the number of bytes transferred between gdb and the
+ target. (Note that the interface also makes provisions for
+ negative values, but this capability isn't implemented here.) */
+
static int
-procfs_xfer_memory (memaddr, myaddr, len, dowrite, target)
- CORE_ADDR memaddr;
- char *myaddr;
- int len;
- int dowrite;
- struct target_ops *target; /* ignored */
+procfs_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int dowrite,
+ struct mem_attrib *attrib, struct target_ops *target)
{
procinfo *pi;
int nbytes = 0;
/* Find procinfo for main process */
- pi = find_procinfo_or_die (PIDGET (inferior_pid), 0);
+ pi = find_procinfo_or_die (PIDGET (inferior_ptid), 0);
if (pi->as_fd == 0 &&
open_procinfo_files (pi, FD_AS) == 0)
{
*/
static void
-procfs_resume (int pid, int step, enum target_signal signo)
+procfs_resume (ptid_t ptid, int step, enum target_signal signo)
{
procinfo *pi, *thread;
int native_signo;
to proc_run_process (for use in the prrun struct by ioctl). */
/* Find procinfo for main process */
- pi = find_procinfo_or_die (PIDGET (inferior_pid), 0);
+ pi = find_procinfo_or_die (PIDGET (inferior_ptid), 0);
/* First cut: ignore pid argument */
errno = 0;
/* Void the process procinfo's caches. */
invalidate_cache (NULL, pi, NULL);
- if (pid != -1)
+ if (PIDGET (ptid) != -1)
{
/* Resume a specific thread, presumably suppressing the others. */
- thread = find_procinfo (PIDGET (pid), TIDGET (pid));
- if (thread == NULL)
- warning ("procfs: resume can't find thread %d -- resuming all.",
- TIDGET (pid));
- else
+ thread = find_procinfo (PIDGET (ptid), TIDGET (ptid));
+ if (thread != NULL)
{
if (thread->tid != 0)
{
*/
static int
-register_gdb_signals (procinfo *pi, sigset_t *signals)
+register_gdb_signals (procinfo *pi, gdb_sigset_t *signals)
{
int signo;
*/
static void
-procfs_notice_signals (int pid)
+procfs_notice_signals (ptid_t ptid)
{
- sigset_t signals;
- procinfo *pi = find_procinfo_or_die (PIDGET (pid), 0);
+ gdb_sigset_t signals;
+ procinfo *pi = find_procinfo_or_die (PIDGET (ptid), 0);
if (proc_get_traced_signals (pi, &signals) &&
register_gdb_signals (pi, &signals))
{
printf_filtered ("\tUsing the running image of %s %s via /proc.\n",
attach_flag? "attached": "child",
- target_pid_to_str (inferior_pid));
+ target_pid_to_str (inferior_ptid));
}
/*
We do not check the result of the PIOCSSIG, the inferior might have
died already. */
{
- struct siginfo newsiginfo;
+ gdb_siginfo_t newsiginfo;
memset ((char *) &newsiginfo, 0, sizeof (newsiginfo));
newsiginfo.si_signo = SIGKILL;
static void
procfs_kill_inferior (void)
{
- if (inferior_pid != 0) /* ? */
+ if (!ptid_equal (inferior_ptid, null_ptid)) /* ? */
{
/* Find procinfo for main process */
- procinfo *pi = find_procinfo (PIDGET (inferior_pid), 0);
+ procinfo *pi = find_procinfo (PIDGET (inferior_ptid), 0);
if (pi)
unconditionally_kill_inferior (pi);
{
procinfo *pi;
- if (inferior_pid != 0)
+ if (!ptid_equal (inferior_ptid, null_ptid))
{
/* Find procinfo for main process */
- pi = find_procinfo (PIDGET (inferior_pid), 0);
+ pi = find_procinfo (PIDGET (inferior_ptid), 0);
if (pi)
destroy_procinfo (pi);
}
procfs_init_inferior (int pid)
{
procinfo *pi;
- sigset_t signals;
+ gdb_sigset_t signals;
int fail;
/* This routine called on the parent side (GDB side)
proc_error (pi, "init_inferior, get_held_signals", __LINE__);
if (!proc_get_traced_faults (pi, &pi->saved_fltset))
proc_error (pi, "init_inferior, get_traced_faults", __LINE__);
- if (!proc_get_traced_sysentry (pi, &pi->saved_entryset))
+ if (!proc_get_traced_sysentry (pi, pi->saved_entryset))
proc_error (pi, "init_inferior, get_traced_sysentry", __LINE__);
- if (!proc_get_traced_sysexit (pi, &pi->saved_exitset))
+ if (!proc_get_traced_sysexit (pi, pi->saved_exitset))
proc_error (pi, "init_inferior, get_traced_sysexit", __LINE__);
/* Register to trace selected signals in the child. */
/* The 'process ID' we return to GDB is composed of
the actual process ID plus the lwp ID. */
- inferior_pid = MERGEPID (pi->pid, proc_get_current_thread (pi));
+ inferior_ptid = MERGEPID (pi->pid, proc_get_current_thread (pi));
#ifdef START_INFERIOR_TRAPS_EXPECTED
startup_inferior (START_INFERIOR_TRAPS_EXPECTED);
because it may be sharing data space with its parent. */
procinfo *pi;
- sysset_t exitset;
+ sysset_t *exitset;
if ((pi = create_procinfo (getpid (), 0)) == NULL)
perror_with_name ("procfs: create_procinfo failed in child.");
names. On the SGI, for example, there is no SYS_exec, but there
*is* a SYS_execv. So, we try to account for that. */
- premptyset (&exitset);
+ exitset = sysset_t_alloc (pi);
+ gdb_premptysysset (exitset);
#ifdef SYS_exec
- praddset (&exitset, SYS_exec);
+ gdb_praddsysset (exitset, SYS_exec);
#endif
#ifdef SYS_execve
- praddset (&exitset, SYS_execve);
+ gdb_praddsysset (exitset, SYS_execve);
#endif
#ifdef SYS_execv
- praddset (&exitset, SYS_execv);
+ gdb_praddsysset (exitset, SYS_execv);
#endif
+#ifdef DYNAMIC_SYSCALLS
+ {
+ int callnum = find_syscall (pi, "execve");
+
+ if (callnum >= 0)
+ gdb_praddsysset (exitset, callnum);
- if (!proc_set_traced_sysexit (pi, &exitset))
+ callnum = find_syscall (pi, "ra_execve");
+ if (callnum >= 0)
+ gdb_praddsysset (exitset, callnum);
+ }
+#endif /* DYNAMIC_SYSCALLS */
+
+ if (!proc_set_traced_sysexit (pi, exitset))
{
proc_warn (pi, "set_exec_trap, set_traced_sysexit", __LINE__);
gdb_flush (gdb_stderr);
static int
procfs_notice_thread (procinfo *pi, procinfo *thread, void *ptr)
{
- int gdb_threadid = MERGEPID (pi->pid, thread->tid);
+ ptid_t gdb_threadid = MERGEPID (pi->pid, thread->tid);
if (!in_thread_list (gdb_threadid))
add_thread (gdb_threadid);
procinfo *pi;
/* Find procinfo for main process */
- pi = find_procinfo_or_die (PIDGET (inferior_pid), 0);
+ pi = find_procinfo_or_die (PIDGET (inferior_ptid), 0);
proc_update_threads (pi);
proc_iterate_over_threads (pi, procfs_notice_thread, NULL);
}
*/
static int
-procfs_thread_alive (int pid)
+procfs_thread_alive (ptid_t ptid)
{
int proc, thread;
procinfo *pi;
- proc = PIDGET (pid);
- thread = TIDGET (pid);
+ proc = PIDGET (ptid);
+ thread = TIDGET (ptid);
/* If I don't know it, it ain't alive! */
if ((pi = find_procinfo (proc, thread)) == NULL)
return 0;
*/
char *
-procfs_pid_to_str (int pid)
+procfs_pid_to_str (ptid_t ptid)
{
static char buf[80];
int proc, thread;
procinfo *pi;
- proc = PIDGET (pid);
- thread = TIDGET (pid);
+ proc = PIDGET (ptid);
+ thread = TIDGET (ptid);
pi = find_procinfo (proc, thread);
if (thread == 0)
*/
int
-procfs_set_watchpoint (int pid, CORE_ADDR addr, int len, int rwflag, int after)
+procfs_set_watchpoint (ptid_t ptid, CORE_ADDR addr, int len, int rwflag,
+ int after)
{
#ifndef UNIXWARE
+#ifndef AIX5
int pflags = 0;
procinfo *pi;
- pi = find_procinfo_or_die (pid == -1 ?
- PIDGET (inferior_pid) : PIDGET (pid), 0);
+ pi = find_procinfo_or_die (PIDGET (ptid) == -1 ?
+ PIDGET (inferior_ptid) : PIDGET (ptid), 0);
/* Translate from GDB's flags to /proc's */
if (len > 0) /* len == 0 means delete watchpoint */
return 0; /* ignore */
proc_error (pi, "set_watchpoint", __LINE__);
}
-#endif
+#endif /* AIX5 */
+#endif /* UNIXWARE */
return 0;
}
*/
int
-procfs_stopped_by_watchpoint (int pid)
+procfs_stopped_by_watchpoint (ptid_t ptid)
{
procinfo *pi;
- pi = find_procinfo_or_die (pid == -1 ?
- PIDGET (inferior_pid) : PIDGET (pid), 0);
+ pi = find_procinfo_or_die (PIDGET (ptid) == -1 ?
+ PIDGET (inferior_ptid) : PIDGET (ptid), 0);
+
+ if (!pi) /* If no process, then not stopped by watchpoint! */
+ return 0;
+
if (proc_flags (pi) & (PR_STOPPED | PR_ISTOP))
{
if (proc_why (pi) == PR_FAULTED)
* Function: procfs_find_LDT_entry
*
* Input:
- * int pid; // The GDB-style pid-plus-LWP.
+ * ptid_t ptid; // The GDB-style pid-plus-LWP.
*
* Return:
* pointer to the corresponding LDT entry.
*/
struct ssd *
-procfs_find_LDT_entry (int pid)
+procfs_find_LDT_entry (ptid_t ptid)
{
gdb_gregset_t *gregs;
int key;
procinfo *pi;
/* Find procinfo for the lwp. */
- if ((pi = find_procinfo (PIDGET (pid), TIDGET (pid))) == NULL)
+ if ((pi = find_procinfo (PIDGET (ptid), TIDGET (ptid))) == NULL)
{
- warning ("procfs_find_LDT_entry: could not find procinfi for %d.",
- pid);
+ warning ("procfs_find_LDT_entry: could not find procinfo for %d:%d.",
+ PIDGET (ptid), TIDGET (ptid));
return NULL;
}
/* get its general registers. */
if ((gregs = proc_get_gregs (pi)) == NULL)
{
- warning ("procfs_find_LDT_entry: could not read gregs for %d.",
- pid);
+ warning ("procfs_find_LDT_entry: could not read gregs for %d:%d.",
+ PIDGET (ptid), TIDGET (ptid));
return NULL;
}
/* Now extract the GS register's lower 16 bits. */
argv++;
}
if (pid == 0)
- pid = PIDGET (inferior_pid);
+ pid = PIDGET (inferior_ptid);
if (pid == 0)
error ("No current process: you must name one.");
else
sysset_t *sysset;
int syscallnum = 0;
- if (inferior_pid <= 0)
+ if (PIDGET (inferior_ptid) <= 0)
error ("you must be debugging a process to use this command.");
if (args == NULL || args[0] == 0)
error_no_arg ("system call to trace");
- pi = find_procinfo_or_die (PIDGET (inferior_pid), 0);
+ pi = find_procinfo_or_die (PIDGET (inferior_ptid), 0);
if (isdigit (args[0]))
{
syscallnum = atoi (args);
proc_error (pi, "proc-trace, get_traced_sysset", __LINE__);
if (mode == FLAG_SET)
- praddset (sysset, syscallnum);
+ gdb_praddsysset (sysset, syscallnum);
else
- prdelset (sysset, syscallnum);
+ gdb_prdelsysset (sysset, syscallnum);
if (entry_or_exit == PR_SYSENTRY)
{
* we will be able to find a 'live' procinfo.
*/
-int
+ptid_t
procfs_first_available (void)
{
- if (procinfo_list)
- return procinfo_list->pid;
- else
- return -1;
+ return pid_to_ptid (procinfo_list ? procinfo_list->pid : -1);
}