/* Machine independent support for SVR4 /proc (process file system) for GDB.
- Copyright 1999 Free Software Foundation, Inc.
+ Copyright 1999-2000 Free Software Foundation, Inc.
Written by Michael Snyder at Cygnus Solutions.
Based on work by Fred Fish, Stu Grossman, Geoff Noer, and others.
#include "target.h"
#include "gdbcore.h"
#include "gdbcmd.h"
+#include "gdbthread.h"
#if defined (NEW_PROC_API)
#define _STRUCTURED_PROC 1 /* Should be done by configure script. */
#include <sys/fault.h>
#include <sys/syscall.h>
#include <sys/errno.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <ctype.h>
/*
* PROCFS.C
#ifdef NEW_PROC_API
#include <sys/types.h>
-#include <dirent.h> /* opendir/readdir, for listing the LWP's */
+#include "gdb_dirent.h" /* opendir/readdir, for listing the LWP's */
#endif
#include <fcntl.h> /* for O_RDONLY */
#include <unistd.h> /* for "X_OK" */
#include "gdb_stat.h" /* for struct stat */
+/* Note: procfs-utils.h must be included after the above system header
+ files, because it redefines various system calls using macros.
+ This may be incompatible with the prototype declarations. */
+
+#include "proc-utils.h"
+
+/* Prototypes for supply_gregset etc. */
+#include "gregset.h"
+
/* =================== TARGET_OPS "MODULE" =================== */
/*
* This module defines the GDB target vector and its methods.
*/
-static void procfs_open PARAMS((char *, int));
-static void procfs_attach PARAMS ((char *, int));
-static void procfs_detach PARAMS ((char *, int));
-static void procfs_resume PARAMS ((int, int, enum target_signal));
-static int procfs_can_run PARAMS ((void));
-static void procfs_stop PARAMS ((void));
-static void procfs_files_info PARAMS ((struct target_ops *));
-static void procfs_fetch_registers PARAMS ((int));
-static void procfs_store_registers PARAMS ((int));
-static void procfs_notice_signals PARAMS ((int));
-static void procfs_prepare_to_store PARAMS ((void));
-static void procfs_kill_inferior PARAMS ((void));
-static void procfs_mourn_inferior PARAMS ((void));
-static void procfs_create_inferior PARAMS ((char *, char *, char **));
-static int procfs_wait PARAMS ((int,
- struct target_waitstatus *));
-static int procfs_xfer_memory PARAMS ((CORE_ADDR,
- char *, int, int,
- struct target_ops *));
-
-static int procfs_thread_alive PARAMS ((int));
-
-void procfs_find_new_threads PARAMS ((void));
-char *procfs_pid_to_str PARAMS ((int));
+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 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_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 int procfs_thread_alive (int);
+
+void procfs_find_new_threads (void);
+char *procfs_pid_to_str (int);
struct target_ops procfs_ops; /* the target vector */
procfs_ops.to_thread_alive = procfs_thread_alive;
procfs_ops.to_pid_to_str = procfs_pid_to_str;
+ procfs_ops.to_has_all_memory = 1;
+ procfs_ops.to_has_memory = 1;
procfs_ops.to_has_execution = 1;
procfs_ops.to_has_stack = 1;
procfs_ops.to_has_registers = 1;
/* =================== END, TARGET_OPS "MODULE" =================== */
-/*
- * Temporary debugging code:
- *
- * These macros allow me to trace the system calls that we make
- * to control the child process. This is quite handy for comparing
- * with the older version of procfs.
- */
-
-#ifdef TRACE_PROCFS
-#ifdef NEW_PROC_API
-extern int write_with_trace PARAMS ((int, void *, size_t, char *, int));
-extern off_t lseek_with_trace PARAMS ((int, off_t, int, char *, int));
-
-#if 0
-#define write(X,Y,Z) write_with_trace (X, Y, Z, __FILE__, __LINE__)
-#endif
-
-#define lseek(X,Y,Z) lseek_with_trace (X, Y, Z, __FILE__, __LINE__)
-#else
-extern int ioctl_with_trace PARAMS ((int, long, void *, char *, int));
-#define ioctl(X,Y,Z) ioctl_with_trace (X, Y, Z, __FILE__, __LINE__)
-#endif
-#define open(X,Y) open_with_trace (X, Y, __FILE__, __LINE__)
-#define close(X) close_with_trace (X, __FILE__, __LINE__)
-#define wait(X) wait_with_trace (X, __FILE__, __LINE__)
-
-#if 0
-#define PROCFS_NOTE(X) procfs_note (X, __FILE__, __LINE__)
-#define PROC_PRETTYFPRINT_STATUS(X,Y,Z,T) \
-proc_prettyfprint_status (X, Y, Z, T)
-#else
-#define PROCFS_NOTE(X)
-#define PROC_PRETTYFPRINT_STATUS(X,Y,Z,T)
-#endif
-
-#else
-#define PROCFS_NOTE(X)
-#define PROC_PRETTYFPRINT_STATUS(X,Y,Z,T)
-#endif
-
- /* temp: */
-#undef PROCFS_NOTE
-#define PROCFS_NOTE(X)
- /* suppress */
-
-
/*
* World Unification:
*
typedef prstatus_t gdb_lwpstatus_t;
#endif /* NEW_PROC_API */
-
-/* These #ifdefs are for sol2.x in particular. sol2.x has
- both a "gregset_t" and a "prgregset_t", which have
- similar uses but different layouts. sol2.x gdb tries to
- use prgregset_t (and prfpregset_t) everywhere. */
-
-#ifdef GDB_GREGSET_TYPE
- typedef GDB_GREGSET_TYPE gdb_gregset_t;
-#else
- typedef gregset_t gdb_gregset_t;
-#endif
-
-#ifdef GDB_FPREGSET_TYPE
- typedef GDB_FPREGSET_TYPE gdb_fpregset_t;
-#else
- typedef fpregset_t gdb_fpregset_t;
-#endif
-
-/* The PIDs that we pass to and from GDB will be composed from
- the actual PID plus the LWPID. These macros will be used to
- compose and decompose them. */
+/* Provide default composite pid manipulation macros for systems that
+ don't have threads. */
#ifndef PIDGET
-#define PIDGET(PID) (((PID) & 0xffff))
-#endif
-
-#ifndef TIDGET
-#define TIDGET(PID) (((PID) & 0x7fffffff) >> 16)
+#define PIDGET(PID) (PID)
+#define TIDGET(PID) (PID)
#endif
-
#ifndef MERGEPID
-#define MERGEPID(PID, TID) (((PID) & 0xffff) | ((TID) << 16))
+#define MERGEPID(PID, TID) (PID)
#endif
typedef struct procinfo {
/* Function prototypes for procinfo module: */
-static procinfo *find_procinfo_or_die PARAMS ((int pid, int tid));
-static procinfo *find_procinfo PARAMS ((int pid, int tid));
-static procinfo *create_procinfo PARAMS ((int pid, int tid));
-static void destroy_procinfo PARAMS ((procinfo *p));
-static void dead_procinfo PARAMS ((procinfo *p,
- char *msg, int killp));
-static int open_procinfo_files PARAMS ((procinfo *p, int which));
-static void close_procinfo_files PARAMS ((procinfo *p));
+static procinfo *find_procinfo_or_die (int pid, int tid);
+static procinfo *find_procinfo (int pid, int tid);
+static procinfo *create_procinfo (int pid, int tid);
+static void destroy_procinfo (procinfo * p);
+static void do_destroy_procinfo_cleanup (void *);
+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);
/* The head of the procinfo list: */
static procinfo * procinfo_list;
procinfo *pi = find_procinfo (pid, tid);
if (pi == NULL)
- if (tid)
- error ("procfs: couldn't find pid %d (kernel thread %d) in procinfo list.",
- pid, tid);
- else
- error ("procfs: couldn't find pid %d in procinfo list.", pid);
+ {
+ if (tid)
+ error ("procfs: couldn't find pid %d (kernel thread %d) in procinfo list.",
+ pid, tid);
+ else
+ error ("procfs: couldn't find pid %d in procinfo list.", pid);
+ }
return pi;
}
procinfo *pi;
int which;
{
+#ifdef NEW_PROC_API
char tmp[MAX_PROC_NAME_SIZE];
+#endif
int fd;
/*
* Function: create_procinfo
*
* Allocate a data structure and link it into the procinfo list.
- * (First tries to find a pre-existing one (FIXME: why???)
+ * (First tries to find a pre-existing one (FIXME: why?)
*
* Return: pointer to new procinfo struct.
*/
{
procinfo *pi, *parent;
- if (pi = find_procinfo (pid, tid))
+ if ((pi = find_procinfo (pid, tid)))
return pi; /* Already exists, nothing to do. */
/* find parent before doing malloc, to save having to cleanup */
}
}
+static void
+do_destroy_procinfo_cleanup (void *pi)
+{
+ destroy_procinfo (pi);
+}
+
enum { NOKILL, KILL };
/*
* functions, we do our best to hide them all in here.
*/
-int proc_get_status PARAMS ((procinfo *pi));
-long proc_flags PARAMS ((procinfo *pi));
-int proc_why PARAMS ((procinfo *pi));
-int proc_what PARAMS ((procinfo *pi));
-int proc_set_run_on_last_close PARAMS ((procinfo *pi));
-int proc_unset_run_on_last_close PARAMS ((procinfo *pi));
-int proc_set_inherit_on_fork PARAMS ((procinfo *pi));
-int proc_unset_inherit_on_fork PARAMS ((procinfo *pi));
-int proc_set_async PARAMS ((procinfo *pi));
-int proc_unset_async PARAMS ((procinfo *pi));
-int proc_stop_process PARAMS ((procinfo *pi));
-int proc_trace_signal PARAMS ((procinfo *pi, int signo));
-int proc_ignore_signal PARAMS ((procinfo *pi, int signo));
-int proc_clear_current_fault PARAMS ((procinfo *pi));
-int proc_set_current_signal PARAMS ((procinfo *pi, int signo));
-int proc_clear_current_signal PARAMS ((procinfo *pi));
-int proc_set_gregs PARAMS ((procinfo *pi));
-int proc_set_fpregs PARAMS ((procinfo *pi));
-int proc_wait_for_stop PARAMS ((procinfo *pi));
-int proc_run_process PARAMS ((procinfo *pi, int step, int signo));
-int proc_kill PARAMS ((procinfo *pi, int signo));
-int proc_parent_pid PARAMS ((procinfo *pi));
-int proc_get_nthreads PARAMS ((procinfo *pi));
-int proc_get_current_thread PARAMS ((procinfo *pi));
-int proc_set_held_signals PARAMS ((procinfo *pi, sigset_t *sighold));
-int proc_set_traced_sysexit PARAMS ((procinfo *pi, sysset_t *sysset));
-int proc_set_traced_sysentry PARAMS ((procinfo *pi, sysset_t *sysset));
-int proc_set_traced_faults PARAMS ((procinfo *pi, fltset_t *fltset));
-int proc_set_traced_signals PARAMS ((procinfo *pi, sigset_t *sigset));
-
-int proc_update_threads PARAMS ((procinfo *pi));
-int proc_iterate_over_threads PARAMS ((procinfo *pi,
- int (*func) PARAMS ((procinfo *,
- procinfo *,
- void *)),
- void *ptr));
-
-gdb_gregset_t *proc_get_gregs PARAMS ((procinfo *pi));
-gdb_fpregset_t *proc_get_fpregs PARAMS ((procinfo *pi));
-sysset_t *proc_get_traced_sysexit PARAMS ((procinfo *pi, sysset_t *save));
-sysset_t *proc_get_traced_sysentry PARAMS ((procinfo *pi, sysset_t *save));
-fltset_t *proc_get_traced_faults PARAMS ((procinfo *pi, fltset_t *save));
-sigset_t *proc_get_traced_signals PARAMS ((procinfo *pi, sigset_t *save));
-sigset_t *proc_get_held_signals PARAMS ((procinfo *pi, sigset_t *save));
-sigset_t *proc_get_pending_signals PARAMS ((procinfo *pi, sigset_t *save));
-struct sigaction *proc_get_signal_actions PARAMS ((procinfo *pi,
- struct sigaction *save));
-
-void proc_warn PARAMS ((procinfo *pi, char *func, int line));
-void proc_error PARAMS ((procinfo *pi, char *func, int line));
+int proc_get_status (procinfo * pi);
+long proc_flags (procinfo * pi);
+int proc_why (procinfo * pi);
+int proc_what (procinfo * pi);
+int proc_set_run_on_last_close (procinfo * pi);
+int proc_unset_run_on_last_close (procinfo * pi);
+int proc_set_inherit_on_fork (procinfo * pi);
+int proc_unset_inherit_on_fork (procinfo * pi);
+int proc_set_async (procinfo * pi);
+int proc_unset_async (procinfo * pi);
+int proc_stop_process (procinfo * pi);
+int proc_trace_signal (procinfo * pi, int signo);
+int proc_ignore_signal (procinfo * pi, int signo);
+int proc_clear_current_fault (procinfo * pi);
+int proc_set_current_signal (procinfo * pi, int signo);
+int proc_clear_current_signal (procinfo * pi);
+int proc_set_gregs (procinfo * pi);
+int proc_set_fpregs (procinfo * pi);
+int proc_wait_for_stop (procinfo * pi);
+int proc_run_process (procinfo * pi, int step, int signo);
+int proc_kill (procinfo * pi, int signo);
+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_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_update_threads (procinfo * pi);
+int proc_iterate_over_threads (procinfo * pi,
+ int (*func) (procinfo *, procinfo *, void *),
+ void *ptr);
+
+gdb_gregset_t *proc_get_gregs (procinfo * pi);
+gdb_fpregset_t *proc_get_fpregs (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);
+
+void proc_warn (procinfo * pi, char *func, int line);
+void proc_error (procinfo * pi, char *func, int line);
void
proc_warn (pi, func, line)
return 0; /* FIXME: not a good failure value (but what is?) */
#ifdef NEW_PROC_API
+# ifdef UNIXWARE
+ /* UnixWare 7.1 puts process status flags, e.g. PR_ASYNC, in
+ pstatus_t and LWP status flags, e.g. PR_STOPPED, in lwpstatus_t.
+ The two sets of flags don't overlap. */
+ return pi->prstatus.pr_flags | pi->prstatus.pr_lwp.pr_flags;
+# else
return pi->prstatus.pr_lwp.pr_flags;
+# endif
#else
return pi->prstatus.pr_flags;
#endif
}
/*
- * Function: proc_modify_flags
+ * Function: proc_modify_flag
*
* === I appologize for the messiness of this function.
* === This is an area where the different versions of
* Set or reset any of the following process flags:
* PR_FORK -- forked child will inherit trace flags
* PR_RLC -- traced process runs when last /proc file closed.
+ * PR_KLC -- traced process is killed when last /proc file closed.
* PR_ASYNC -- LWP's get to run/stop independently.
*
* There are three methods for doing this function:
* [OSF, Sol5]
*
* Note: Irix does not define PR_ASYNC.
- * Note: OSF is the only one that can ONLY use the oldest method.
+ * Note: OSF does not define PR_KLC.
+ * Note: OSF is the only one that can ONLY use the oldest method.
*
* Arguments:
* pi -- the procinfo
flag == PR_RLC ? "PR_RLC" :
#ifdef PR_ASYNC
flag == PR_ASYNC ? "PR_ASYNC" :
+#endif
+#ifdef PR_KLC
+ flag == PR_KLC ? "PR_KLC" :
#endif
"<unknown flag>",
mode == FLAG_RESET ? "off" : "on");
return proc_modify_flag (pi, PR_RLC, FLAG_RESET);
}
+#ifdef PR_KLC
+/*
+ * Function: proc_set_kill_on_last_close
+ *
+ * Set the kill_on_last_close flag.
+ * Process with all threads will be killed when debugger
+ * closes all /proc fds (or debugger exits or dies).
+ *
+ * Returns non-zero for success, zero for failure.
+ */
+
+int
+proc_set_kill_on_last_close (pi)
+ procinfo *pi;
+{
+ return proc_modify_flag (pi, PR_KLC, FLAG_SET);
+}
+
+/*
+ * Function: proc_unset_kill_on_last_close
+ *
+ * Reset the kill_on_last_close flag.
+ * Process will NOT be killed when debugger
+ * closes its file handles (or exits or dies).
+ *
+ * Returns non-zero for success, zero for failure.
+ */
+
+int
+proc_unset_kill_on_last_close (pi)
+ procinfo *pi;
+{
+ return proc_modify_flag (pi, PR_KLC, FLAG_RESET);
+}
+#endif /* PR_KLC */
+
/*
* Function: proc_set_inherit_on_fork
*
else
{
#ifdef NEW_PROC_API
- int cmd = PCSTOP;
+ long 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
{
- int cmd = PCWSTOP;
+ long 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
{
- int cmd[2];
+ long cmd[2];
cmd[0] = PCRUN;
cmd[1] = runflags;
#ifdef NEW_PROC_API
{
struct {
- int cmd;
+ long cmd;
/* Use char array to avoid alignment issues. */
char sigset[sizeof (sigset_t)];
} arg;
#ifdef NEW_PROC_API
{
struct {
- int cmd;
+ long cmd;
/* Use char array to avoid alignment issues. */
char fltset[sizeof (fltset_t)];
} arg;
#ifdef NEW_PROC_API
{
struct {
- int cmd;
+ long cmd;
/* Use char array to avoid alignment issues. */
char sysset[sizeof (sysset_t)];
} arg;
#ifdef NEW_PROC_API
{
struct {
- int cmd;
+ long cmd;
/* Use char array to avoid alignment issues. */
char sysset[sizeof (sysset_t)];
} arg;
#ifdef NEW_PROC_API
{
struct {
- int cmd;
+ long cmd;
/* Use char array to avoid alignment issues. */
char hold[sizeof (sigset_t)];
} arg;
#ifdef NEW_PROC_API
{
- int cmd = PCCFAULT;
+ long cmd = PCCFAULT;
win = (write (pi->ctl_fd, (void *) &cmd, sizeof (cmd)) == sizeof (cmd));
}
#else
{
int win;
struct {
- int cmd;
+ long cmd;
/* Use char array to avoid alignment issues. */
char sinfo[sizeof (struct siginfo)];
} arg;
#ifdef NEW_PROC_API
{
struct {
- int cmd;
+ long cmd;
/* Use char array to avoid alignment issues. */
char sinfo[sizeof (struct siginfo)];
} arg;
{
#ifdef NEW_PROC_API
struct {
- int cmd;
+ long cmd;
/* Use char array to avoid alignment issues. */
char gregs[sizeof (gdb_gregset_t)];
} arg;
{
#ifdef NEW_PROC_API
struct {
- int cmd;
+ long cmd;
/* Use char array to avoid alignment issues. */
char fpregs[sizeof (gdb_fpregset_t)];
} arg;
else
{
#ifdef NEW_PROC_API
- int cmd[2];
+ long cmd[2];
cmd[0] = PCKILL;
cmd[1] = signo;
int
proc_set_watchpoint (pi, addr, len, wflags)
- procinfo *pi;
- void *addr;
+ procinfo *pi;
+ CORE_ADDR addr;
int len;
int wflags;
{
return 0;
#else
struct {
- int cmd;
+ long cmd;
char watch[sizeof (prwatch_t)];
} arg;
prwatch_t *pwatch;
pwatch = (prwatch_t *) &arg.watch;
- pwatch->pr_vaddr = addr;
+ pwatch->pr_vaddr = address_to_host_pointer (addr);
pwatch->pr_size = len;
pwatch->pr_wflags = wflags;
#if defined(NEW_PROC_API) && defined (PCWATCH)
every time, I don't need to lseek it. */
int
proc_iterate_over_mappings (func)
- int (*func) PARAMS ((int, CORE_ADDR));
+ int (*func) (int, CORE_ADDR);
{
struct prmap *map;
procinfo *pi;
- int nmaps = 0, i;
- int funcstat = 0;
- int fd, map_fd;
+#ifndef NEW_PROC_API /* avoid compiler warning */
+ int nmaps = 0;
+ int i;
+#else
+ int map_fd;
char pathname[MAX_PROC_NAME_SIZE];
+#endif
+ int funcstat = 0;
+ int fd;
pi = find_procinfo_or_die (PIDGET (inferior_pid), 0);
proc_error (pi, "proc_iterate_over_mappings (open)", __LINE__);
/* Make sure it gets closed again. */
- make_cleanup ((make_cleanup_func) close, (void *) map_fd);
+ make_cleanup_close (map_fd);
/* Allocate space for mapping (lifetime only for this function). */
map = alloca (sizeof (struct prmap));
not a problem. */
/* Stop looping if the callback returns non-zero. */
- if ((funcstat = (*func) (fd, (CORE_ADDR) map[i].pr_vaddr)) != 0)
+ funcstat = (*func) (fd, host_pointer_to_address (map[i].pr_vaddr));
+ if (funcstat != 0)
break;
}
#endif
return NULL;
}
/* Make sure it gets closed again! */
- old_chain = make_cleanup ((make_cleanup_func) close, (void *) fd);
+ old_chain = make_cleanup_close (fd);
/* Now 'read' thru the table, find a match and return it. */
while (read (fd, ldt_entry, sizeof (struct ssd)) == sizeof (struct ssd))
/*
* Unixware and Solaris 6 (and later) version
*/
+static void
+do_closedir_cleanup (void *dir)
+{
+ closedir (dir);
+}
+
int
proc_update_threads (pi)
procinfo *pi;
if ((dirp = opendir (pathname)) == NULL)
proc_error (pi, "update_threads, opendir", __LINE__);
- old_chain = make_cleanup ((make_cleanup_func) closedir, dirp);
+ old_chain = make_cleanup (do_closedir_cleanup, dirp);
while ((direntry = readdir (dirp)) != NULL)
if (direntry->d_name[0] != '.') /* skip '.' and '..' */
{
int
proc_iterate_over_threads (pi, func, ptr)
procinfo *pi;
- int (*func) PARAMS ((procinfo *, procinfo *, void *));
+ int (*func) (procinfo *, procinfo *, void *);
void *ptr;
{
procinfo *thread, *next;
* Here are all of the gdb target vector functions and their friends.
*/
-static int do_attach PARAMS ((int pid));
-static void do_detach PARAMS ((int signo));
-static int register_gdb_signals PARAMS ((procinfo *, sigset_t *));
+static int do_attach (int pid);
+static void do_detach (int signo);
+static int register_gdb_signals (procinfo *, sigset_t *);
/*
* Function: procfs_debug_inferior
int signo;
{
procinfo *pi;
- long pflags;
/* Find procinfo for the main process */
pi = find_procinfo_or_die (PIDGET (inferior_pid), 0); /* FIXME: threads */
supply_gregset (gregs);
-#if defined (FP0_REGNUM) /* need floating point? */
- if ((regno >= 0 && regno < FP0_REGNUM) ||
- regno == PC_REGNUM ||
-#ifdef NPC_REGNUM
- regno == NPC_REGNUM ||
-#endif
- regno == FP_REGNUM ||
- regno == SP_REGNUM)
- return; /* not a floating point register */
+ if (FP0_REGNUM >= 0) /* need floating point? */
+ {
+ if ((regno >= 0 && regno < FP0_REGNUM) ||
+ regno == PC_REGNUM ||
+ (NPC_REGNUM >= 0 && regno == NPC_REGNUM) ||
+ regno == FP_REGNUM ||
+ regno == SP_REGNUM)
+ return; /* not a floating point register */
- if ((fpregs = proc_get_fpregs (pi)) == NULL)
- proc_error (pi, "fetch_registers, get_fpregs", __LINE__);
+ if ((fpregs = proc_get_fpregs (pi)) == NULL)
+ proc_error (pi, "fetch_registers, get_fpregs", __LINE__);
- supply_fpregset (fpregs);
-#endif
+ supply_fpregset (fpregs);
+ }
}
/* Get ready to modify the registers array. On machines which store
if (!proc_set_gregs (pi))
proc_error (pi, "store_registers, set_gregs", __LINE__);
-#if defined (FP0_REGNUM) /* need floating point? */
- if ((regno >= 0 && regno < FP0_REGNUM) ||
- regno == PC_REGNUM ||
-#ifdef NPC_REGNUM
- regno == NPC_REGNUM ||
-#endif
- regno == FP_REGNUM ||
- regno == SP_REGNUM)
- return; /* not a floating point register */
-
- if ((fpregs = proc_get_fpregs (pi)) == NULL)
- proc_error (pi, "store_registers, get_fpregs", __LINE__);
-
- fill_fpregset (fpregs, regno);
- if (!proc_set_fpregs (pi))
- proc_error (pi, "store_registers, set_fpregs", __LINE__);
-#endif
+ if (FP0_REGNUM >= 0) /* need floating point? */
+ {
+ if ((regno >= 0 && regno < FP0_REGNUM) ||
+ regno == PC_REGNUM ||
+ (NPC_REGNUM >= 0 && regno == NPC_REGNUM) ||
+ regno == FP_REGNUM ||
+ regno == SP_REGNUM)
+ return; /* not a floating point register */
+
+ if ((fpregs = proc_get_fpregs (pi)) == NULL)
+ proc_error (pi, "store_registers, get_fpregs", __LINE__);
+
+ fill_fpregset (fpregs, regno);
+ if (!proc_set_fpregs (pi))
+ proc_error (pi, "store_registers, set_fpregs", __LINE__);
+ }
}
/*
why = proc_why (pi);
what = proc_what (pi);
-#if 0
- {
- int stopped_pc = read_pc ();
- if (stopped_pc != 0x10c68 &&
- stopped_pc != 0x10c6c &&
- stopped_pc != 0x10c70 &&
- stopped_pc != 0x22768 &&
- stopped_pc != 0x10c74)
- printf ("%x,%d,%d\n", stopped_pc, why, what);
- }
-#endif
-
if (flags & (PR_STOPPED | PR_ISTOP))
{
#ifdef PR_ASYNC
return a "success" exit code. Bogus: what if
it returns something else? */
wstat = 0;
- retval = inferior_pid; /* ??? */
+ retval = inferior_pid; /* ? ? ? */
}
else
{
if ((nsysargs = proc_nsysarg (pi)) > 0 &&
(sysargs = proc_sysargs (pi)) != NULL)
{
- printf_filtered ("%d syscall arguments:\n", nsysargs);
+ printf_filtered ("%ld syscall arguments:\n", nsysargs);
for (i = 0; i < nsysargs; i++)
- printf_filtered ("#%d: 0x%08x\n",
+ printf_filtered ("#%ld: 0x%08lx\n",
i, sysargs[i]);
}
if ((nsysargs = proc_nsysarg (pi)) > 0 &&
(sysargs = proc_sysargs (pi)) != NULL)
{
- printf_filtered ("%d syscall arguments:\n", nsysargs);
+ printf_filtered ("%ld syscall arguments:\n", nsysargs);
for (i = 0; i < nsysargs; i++)
- printf_filtered ("#%d: 0x%08x\n",
+ printf_filtered ("#%ld: 0x%08lx\n",
i, sysargs[i]);
}
}
temp = MERGEPID (pi->pid, temp);
if (!in_thread_list (temp))
{
- printf_filtered ("[*New %s]\n",
+ printf_filtered ("[New %s]\n",
target_pid_to_str (temp));
add_thread (temp);
}
if (!proc_set_gregs (pi)) /* flush gregs cache */
proc_warn (pi, "target_resume, set_gregs",
__LINE__);
-#ifdef FP0_REGNUM
- if (pi->fpregs_dirty)
- if (parent == NULL ||
- proc_get_current_thread (parent) != pi->tid)
- if (!proc_set_fpregs (pi)) /* flush fpregs cache */
- proc_warn (pi, "target_resume, set_fpregs",
- __LINE__);
-#endif
+ if (FP0_REGNUM >= 0)
+ if (pi->fpregs_dirty)
+ if (parent == NULL ||
+ proc_get_current_thread (parent) != pi->tid)
+ if (!proc_set_fpregs (pi)) /* flush fpregs cache */
+ proc_warn (pi, "target_resume, set_fpregs",
+ __LINE__);
#endif
if (parent != NULL)
return 0;
}
+#if 0
/*
* Function: make_signal_thread_runnable
*
#endif
return 0;
}
+#endif
/*
* Function: target_resume
/* Convert signal to host numbering. */
if (signo == 0 ||
- signo == TARGET_SIGNAL_STOP && pi->ignore_next_sigstop)
+ (signo == TARGET_SIGNAL_STOP && pi->ignore_next_sigstop))
native_signo = 0;
else
native_signo = target_signal_to_host (signo);
}
#else /* PROCFS_NEED_PIOCSSIG_FOR_KILL */
if (!proc_kill (pi, SIGKILL))
- proc_warn (pi, "unconditionally_kill, proc_kill", __LINE__);
+ proc_error (pi, "unconditionally_kill, proc_kill", __LINE__);
#endif /* PROCFS_NEED_PIOCSSIG_FOR_KILL */
destroy_procinfo (pi);
/* FIXME: should we use waitpid to make sure we get the right event?
Should we check the returned event? */
{
+#if 0
int status, ret;
-#if 0
ret = waitpid (pi->pid, &status, 0);
#else
wait (NULL);
if ((fail = procfs_debug_inferior (pi)) != 0)
proc_error (pi, "init_inferior (procfs_debug_inferior)", fail);
+ /* FIXME: logically, we should really be turning OFF run-on-last-close,
+ and possibly even turning ON kill-on-last-close at this point. But
+ I can't make that change without careful testing which I don't have
+ time to do right now... */
/* Turn on run-on-last-close flag so that the child
will die if GDB goes away for some reason. */
if (!proc_set_run_on_last_close (pi))
#else
/* One trap to exec the shell, one to exec the program being debugged. */
startup_inferior (2);
-#endif
+#endif /* START_INFERIOR_TRAPS_EXPECTED */
}
/*
procinfo *pi;
sysset_t exitset;
- sysset_t entryset;
if ((pi = create_procinfo (getpid (), 0)) == NULL)
perror_with_name ("procfs: create_procinfo failed in child.");
old_chain = make_cleanup (null_cleanup, 0);
if (args)
- if ((argv = buildargv (args)) == NULL)
- nomem (0);
- else
- make_cleanup ((make_cleanup_func) freeargv, argv);
-
+ {
+ if ((argv = buildargv (args)) == NULL)
+ nomem (0);
+ else
+ make_cleanup_freeargv (argv);
+ }
while (argv != NULL && *argv != NULL)
{
if (isdigit (argv[0][0]))
/* No. So open a procinfo for it, but
remember to close it again when finished. */
process = create_procinfo (pid, 0);
- make_cleanup ((make_cleanup_func) destroy_procinfo, process);
+ make_cleanup (do_destroy_procinfo_cleanup, process);
if (!open_procinfo_files (process, FD_CTL))
proc_error (process, "info proc, open_procinfo_files", __LINE__);
}
}
-int
-mapping_test (fd, core_addr)
- int fd;
- CORE_ADDR core_addr;
-{
- printf ("File descriptor %d, base address 0x%08x\n", fd, core_addr);
- if (fd > 0)
- close (fd);
- return 0;
-}
-
-void
-test_mapping_cmd (args, from_tty)
- char *args;
- int from_tty;
-{
- int ret;
- ret = proc_iterate_over_mappings (mapping_test);
- printf ("iterate_over_mappings returned %d.\n", ret);
-}
-
void
_initialize_procfs ()
{
"Cancel a trace of entries into the syscall.");
add_com ("proc-untrace-exit", no_class, proc_untrace_sysexit_cmd,
"Cancel a trace of exits from the syscall.");
-
- add_com ("test-mapping", no_class, test_mapping_cmd,
- "test iterate-over-mappings");
}
/* =================== END, GDB "MODULE" =================== */
else
return -1;
}
-
-int
-procfs_get_pid_fd (pid)
- int pid;
-{
- procinfo *pi;
-
- if (pid == -1 && inferior_pid != 0)
- pi = find_procinfo (PIDGET (inferior_pid), 0);
- else
- pi = find_procinfo (PIDGET (pid), 0);
-
- if (pi)
- return pi->ctl_fd;
- else
- return -1;
-}