/* Machine independent support for SVR4 /proc (process file system) for GDB.
- Copyright 1991, 1992 Free Software Foundation, Inc.
+ Copyright 1991, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
Written by Fred Fish at Cygnus Support.
This file is part of GDB.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
/* N O T E S
#include <sys/types.h>
#include <time.h>
+#include <sys/fault.h>
+#include <sys/syscall.h>
#include <sys/procfs.h>
#include <fcntl.h>
#include <errno.h>
-#include <string.h>
+#include "gdb_string.h"
#include <stropts.h>
#include <poll.h>
#include <unistd.h>
-#include <sys/stat.h>
+#include "gdb_stat.h"
#include "inferior.h"
#include "target.h"
#include "command.h"
#include "gdbcore.h"
+#include "thread.h"
#define MAX_SYSCALLS 256 /* Maximum number of syscalls for table */
static struct trans pr_flag_table[] =
{
#if defined (PR_STOPPED)
- PR_STOPPED, "PR_STOPPED", "Process is stopped",
+ { PR_STOPPED, "PR_STOPPED", "Process is stopped" },
#endif
#if defined (PR_ISTOP)
- PR_ISTOP, "PR_ISTOP", "Stopped on an event of interest",
+ { PR_ISTOP, "PR_ISTOP", "Stopped on an event of interest" },
#endif
#if defined (PR_DSTOP)
- PR_DSTOP, "PR_DSTOP", "A stop directive is in effect",
+ { PR_DSTOP, "PR_DSTOP", "A stop directive is in effect" },
#endif
#if defined (PR_ASLEEP)
- PR_ASLEEP, "PR_ASLEEP", "Sleeping in an interruptible system call",
+ { PR_ASLEEP, "PR_ASLEEP", "Sleeping in an interruptible system call" },
#endif
#if defined (PR_FORK)
- PR_FORK, "PR_FORK", "Inherit-on-fork is in effect",
+ { PR_FORK, "PR_FORK", "Inherit-on-fork is in effect" },
#endif
#if defined (PR_RLC)
- PR_RLC, "PR_RLC", "Run-on-last-close is in effect",
+ { PR_RLC, "PR_RLC", "Run-on-last-close is in effect" },
#endif
#if defined (PR_PTRACE)
- PR_PTRACE, "PR_PTRACE", "Process is being controlled by ptrace",
+ { PR_PTRACE, "PR_PTRACE", "Process is being controlled by ptrace" },
#endif
#if defined (PR_PCINVAL)
- PR_PCINVAL, "PR_PCINVAL", "PC refers to an invalid virtual address",
+ { PR_PCINVAL, "PR_PCINVAL", "PC refers to an invalid virtual address" },
#endif
#if defined (PR_ISSYS)
- PR_ISSYS, "PR_ISSYS", "Is a system process",
+ { PR_ISSYS, "PR_ISSYS", "Is a system process" },
#endif
#if defined (PR_STEP)
- PR_STEP, "PR_STEP", "Process has single step pending",
+ { PR_STEP, "PR_STEP", "Process has single step pending" },
#endif
#if defined (PR_KLC)
- PR_KLC, "PR_KLC", "Kill-on-last-close is in effect",
+ { PR_KLC, "PR_KLC", "Kill-on-last-close is in effect" },
#endif
#if defined (PR_ASYNC)
- PR_ASYNC, "PR_ASYNC", "Asynchronous stop is in effect",
+ { PR_ASYNC, "PR_ASYNC", "Asynchronous stop is in effect" },
#endif
#if defined (PR_PCOMPAT)
- PR_PCOMPAT, "PR_PCOMPAT", "Ptrace compatibility mode in effect",
+ { PR_PCOMPAT, "PR_PCOMPAT", "Ptrace compatibility mode in effect" },
#endif
- 0, NULL, NULL
+ { 0, NULL, NULL }
};
/* Translate values in the pr_why field of the prstatus struct. */
static struct trans pr_why_table[] =
{
#if defined (PR_REQUESTED)
- PR_REQUESTED, "PR_REQUESTED", "Directed to stop via PIOCSTOP/PIOCWSTOP",
+ { PR_REQUESTED, "PR_REQUESTED", "Directed to stop via PIOCSTOP/PIOCWSTOP" },
#endif
#if defined (PR_SIGNALLED)
- PR_SIGNALLED, "PR_SIGNALLED", "Receipt of a traced signal",
+ { PR_SIGNALLED, "PR_SIGNALLED", "Receipt of a traced signal" },
#endif
#if defined (PR_FAULTED)
- PR_FAULTED, "PR_FAULTED", "Incurred a traced hardware fault",
+ { PR_FAULTED, "PR_FAULTED", "Incurred a traced hardware fault" },
#endif
#if defined (PR_SYSENTRY)
- PR_SYSENTRY, "PR_SYSENTRY", "Entry to a traced system call",
+ { PR_SYSENTRY, "PR_SYSENTRY", "Entry to a traced system call" },
#endif
#if defined (PR_SYSEXIT)
- PR_SYSEXIT, "PR_SYSEXIT", "Exit from a traced system call",
+ { PR_SYSEXIT, "PR_SYSEXIT", "Exit from a traced system call" },
#endif
#if defined (PR_JOBCONTROL)
- PR_JOBCONTROL, "PR_JOBCONTROL", "Default job control stop signal action",
+ { PR_JOBCONTROL, "PR_JOBCONTROL", "Default job control stop signal action" },
#endif
#if defined (PR_SUSPENDED)
- PR_SUSPENDED, "PR_SUSPENDED", "Process suspended",
+ { PR_SUSPENDED, "PR_SUSPENDED", "Process suspended" },
#endif
- 0, NULL, NULL
+ { 0, NULL, NULL }
};
/* Hardware fault translation table. */
static struct trans faults_table[] =
{
#if defined (FLTILL)
- FLTILL, "FLTILL", "Illegal instruction",
+ { FLTILL, "FLTILL", "Illegal instruction" },
#endif
#if defined (FLTPRIV)
- FLTPRIV, "FLTPRIV", "Privileged instruction",
+ { FLTPRIV, "FLTPRIV", "Privileged instruction" },
#endif
#if defined (FLTBPT)
- FLTBPT, "FLTBPT", "Breakpoint trap",
+ { FLTBPT, "FLTBPT", "Breakpoint trap" },
#endif
#if defined (FLTTRACE)
- FLTTRACE, "FLTTRACE", "Trace trap",
+ { FLTTRACE, "FLTTRACE", "Trace trap" },
#endif
#if defined (FLTACCESS)
- FLTACCESS, "FLTACCESS", "Memory access fault",
+ { FLTACCESS, "FLTACCESS", "Memory access fault" },
#endif
#if defined (FLTBOUNDS)
- FLTBOUNDS, "FLTBOUNDS", "Memory bounds violation",
+ { FLTBOUNDS, "FLTBOUNDS", "Memory bounds violation" },
#endif
#if defined (FLTIOVF)
- FLTIOVF, "FLTIOVF", "Integer overflow",
+ { FLTIOVF, "FLTIOVF", "Integer overflow" },
#endif
#if defined (FLTIZDIV)
- FLTIZDIV, "FLTIZDIV", "Integer zero divide",
+ { FLTIZDIV, "FLTIZDIV", "Integer zero divide" },
#endif
#if defined (FLTFPE)
- FLTFPE, "FLTFPE", "Floating-point exception",
+ { FLTFPE, "FLTFPE", "Floating-point exception" },
#endif
#if defined (FLTSTACK)
- FLTSTACK, "FLTSTACK", "Unrecoverable stack fault",
+ { FLTSTACK, "FLTSTACK", "Unrecoverable stack fault" },
#endif
#if defined (FLTPAGE)
- FLTPAGE, "FLTPAGE", "Recoverable page fault",
+ { FLTPAGE, "FLTPAGE", "Recoverable page fault" },
#endif
- 0, NULL, NULL
+ { 0, NULL, NULL }
};
/* Translation table for signal generation information. See UNIX System
char *desc;
} siginfo_table[] = {
#if defined (SIGILL) && defined (ILL_ILLOPC)
- SIGILL, ILL_ILLOPC, "ILL_ILLOPC", "Illegal opcode",
+ { SIGILL, ILL_ILLOPC, "ILL_ILLOPC", "Illegal opcode" },
#endif
#if defined (SIGILL) && defined (ILL_ILLOPN)
- SIGILL, ILL_ILLOPN, "ILL_ILLOPN", "Illegal operand",
+ { SIGILL, ILL_ILLOPN, "ILL_ILLOPN", "Illegal operand", },
#endif
#if defined (SIGILL) && defined (ILL_ILLADR)
- SIGILL, ILL_ILLADR, "ILL_ILLADR", "Illegal addressing mode",
+ { SIGILL, ILL_ILLADR, "ILL_ILLADR", "Illegal addressing mode" },
#endif
#if defined (SIGILL) && defined (ILL_ILLTRP)
- SIGILL, ILL_ILLTRP, "ILL_ILLTRP", "Illegal trap",
+ { SIGILL, ILL_ILLTRP, "ILL_ILLTRP", "Illegal trap" },
#endif
#if defined (SIGILL) && defined (ILL_PRVOPC)
- SIGILL, ILL_PRVOPC, "ILL_PRVOPC", "Privileged opcode",
+ { SIGILL, ILL_PRVOPC, "ILL_PRVOPC", "Privileged opcode" },
#endif
#if defined (SIGILL) && defined (ILL_PRVREG)
- SIGILL, ILL_PRVREG, "ILL_PRVREG", "Privileged register",
+ { SIGILL, ILL_PRVREG, "ILL_PRVREG", "Privileged register" },
#endif
#if defined (SIGILL) && defined (ILL_COPROC)
- SIGILL, ILL_COPROC, "ILL_COPROC", "Coprocessor error",
+ { SIGILL, ILL_COPROC, "ILL_COPROC", "Coprocessor error" },
#endif
#if defined (SIGILL) && defined (ILL_BADSTK)
- SIGILL, ILL_BADSTK, "ILL_BADSTK", "Internal stack error",
+ { SIGILL, ILL_BADSTK, "ILL_BADSTK", "Internal stack error" },
#endif
#if defined (SIGFPE) && defined (FPE_INTDIV)
- SIGFPE, FPE_INTDIV, "FPE_INTDIV", "Integer divide by zero",
+ { SIGFPE, FPE_INTDIV, "FPE_INTDIV", "Integer divide by zero" },
#endif
#if defined (SIGFPE) && defined (FPE_INTOVF)
- SIGFPE, FPE_INTOVF, "FPE_INTOVF", "Integer overflow",
+ { SIGFPE, FPE_INTOVF, "FPE_INTOVF", "Integer overflow" },
#endif
#if defined (SIGFPE) && defined (FPE_FLTDIV)
- SIGFPE, FPE_FLTDIV, "FPE_FLTDIV", "Floating point divide by zero",
+ { SIGFPE, FPE_FLTDIV, "FPE_FLTDIV", "Floating point divide by zero" },
#endif
#if defined (SIGFPE) && defined (FPE_FLTOVF)
- SIGFPE, FPE_FLTOVF, "FPE_FLTOVF", "Floating point overflow",
+ { SIGFPE, FPE_FLTOVF, "FPE_FLTOVF", "Floating point overflow" },
#endif
#if defined (SIGFPE) && defined (FPE_FLTUND)
- SIGFPE, FPE_FLTUND, "FPE_FLTUND", "Floating point underflow",
+ { SIGFPE, FPE_FLTUND, "FPE_FLTUND", "Floating point underflow" },
#endif
#if defined (SIGFPE) && defined (FPE_FLTRES)
- SIGFPE, FPE_FLTRES, "FPE_FLTRES", "Floating point inexact result",
+ { SIGFPE, FPE_FLTRES, "FPE_FLTRES", "Floating point inexact result" },
#endif
#if defined (SIGFPE) && defined (FPE_FLTINV)
- SIGFPE, FPE_FLTINV, "FPE_FLTINV", "Invalid floating point operation",
+ { SIGFPE, FPE_FLTINV, "FPE_FLTINV", "Invalid floating point operation" },
#endif
#if defined (SIGFPE) && defined (FPE_FLTSUB)
- SIGFPE, FPE_FLTSUB, "FPE_FLTSUB", "Subscript out of range",
+ { SIGFPE, FPE_FLTSUB, "FPE_FLTSUB", "Subscript out of range" },
#endif
#if defined (SIGSEGV) && defined (SEGV_MAPERR)
- SIGSEGV, SEGV_MAPERR, "SEGV_MAPERR", "Address not mapped to object",
+ { SIGSEGV, SEGV_MAPERR, "SEGV_MAPERR", "Address not mapped to object" },
#endif
#if defined (SIGSEGV) && defined (SEGV_ACCERR)
- SIGSEGV, SEGV_ACCERR, "SEGV_ACCERR", "Invalid permissions for object",
+ { SIGSEGV, SEGV_ACCERR, "SEGV_ACCERR", "Invalid permissions for object" },
#endif
#if defined (SIGBUS) && defined (BUS_ADRALN)
- SIGBUS, BUS_ADRALN, "BUS_ADRALN", "Invalid address alignment",
+ { SIGBUS, BUS_ADRALN, "BUS_ADRALN", "Invalid address alignment" },
#endif
#if defined (SIGBUS) && defined (BUS_ADRERR)
- SIGBUS, BUS_ADRERR, "BUS_ADRERR", "Non-existent physical address",
+ { SIGBUS, BUS_ADRERR, "BUS_ADRERR", "Non-existent physical address" },
#endif
#if defined (SIGBUS) && defined (BUS_OBJERR)
- SIGBUS, BUS_OBJERR, "BUS_OBJERR", "Object specific hardware error",
+ { SIGBUS, BUS_OBJERR, "BUS_OBJERR", "Object specific hardware error" },
#endif
#if defined (SIGTRAP) && defined (TRAP_BRKPT)
- SIGTRAP, TRAP_BRKPT, "TRAP_BRKPT", "Process breakpoint",
+ { SIGTRAP, TRAP_BRKPT, "TRAP_BRKPT", "Process breakpoint" },
#endif
#if defined (SIGTRAP) && defined (TRAP_TRACE)
- SIGTRAP, TRAP_TRACE, "TRAP_TRACE", "Process trace trap",
+ { SIGTRAP, TRAP_TRACE, "TRAP_TRACE", "Process trace trap" },
#endif
#if defined (SIGCLD) && defined (CLD_EXITED)
- SIGCLD, CLD_EXITED, "CLD_EXITED", "Child has exited",
+ { SIGCLD, CLD_EXITED, "CLD_EXITED", "Child has exited" },
#endif
#if defined (SIGCLD) && defined (CLD_KILLED)
- SIGCLD, CLD_KILLED, "CLD_KILLED", "Child was killed",
+ { SIGCLD, CLD_KILLED, "CLD_KILLED", "Child was killed" },
#endif
#if defined (SIGCLD) && defined (CLD_DUMPED)
- SIGCLD, CLD_DUMPED, "CLD_DUMPED", "Child has terminated abnormally",
+ { SIGCLD, CLD_DUMPED, "CLD_DUMPED", "Child has terminated abnormally" },
#endif
#if defined (SIGCLD) && defined (CLD_TRAPPED)
- SIGCLD, CLD_TRAPPED, "CLD_TRAPPED", "Traced child has trapped",
+ { SIGCLD, CLD_TRAPPED, "CLD_TRAPPED", "Traced child has trapped" },
#endif
#if defined (SIGCLD) && defined (CLD_STOPPED)
- SIGCLD, CLD_STOPPED, "CLD_STOPPED", "Child has stopped",
+ { SIGCLD, CLD_STOPPED, "CLD_STOPPED", "Child has stopped" },
#endif
#if defined (SIGCLD) && defined (CLD_CONTINUED)
- SIGCLD, CLD_CONTINUED, "CLD_CONTINUED", "Stopped child had continued",
+ { SIGCLD, CLD_CONTINUED, "CLD_CONTINUED", "Stopped child had continued" },
#endif
#if defined (SIGPOLL) && defined (POLL_IN)
- SIGPOLL, POLL_IN, "POLL_IN", "Input input available",
+ { SIGPOLL, POLL_IN, "POLL_IN", "Input input available" },
#endif
#if defined (SIGPOLL) && defined (POLL_OUT)
- SIGPOLL, POLL_OUT, "POLL_OUT", "Output buffers available",
+ { SIGPOLL, POLL_OUT, "POLL_OUT", "Output buffers available" },
#endif
#if defined (SIGPOLL) && defined (POLL_MSG)
- SIGPOLL, POLL_MSG, "POLL_MSG", "Input message available",
+ { SIGPOLL, POLL_MSG, "POLL_MSG", "Input message available" },
#endif
#if defined (SIGPOLL) && defined (POLL_ERR)
- SIGPOLL, POLL_ERR, "POLL_ERR", "I/O error",
+ { SIGPOLL, POLL_ERR, "POLL_ERR", "I/O error" },
#endif
#if defined (SIGPOLL) && defined (POLL_PRI)
- SIGPOLL, POLL_PRI, "POLL_PRI", "High priority input available",
+ { SIGPOLL, POLL_PRI, "POLL_PRI", "High priority input available" },
#endif
#if defined (SIGPOLL) && defined (POLL_HUP)
- SIGPOLL, POLL_HUP, "POLL_HUP", "Device disconnected",
+ { SIGPOLL, POLL_HUP, "POLL_HUP", "Device disconnected" },
#endif
- 0, 0, NULL, NULL
+ { 0, 0, NULL, NULL }
};
static char *syscall_table[MAX_SYSCALLS];
/* Prototypes for local functions */
-static void
-set_proc_siginfo PARAMS ((struct procinfo *, int));
+static void set_proc_siginfo PARAMS ((struct procinfo *, int));
-static void
-init_syscall_table PARAMS ((void));
+static void init_syscall_table PARAMS ((void));
-static char *
-syscallname PARAMS ((int));
+static char *syscallname PARAMS ((int));
-static char *
-signalname PARAMS ((int));
+static char *signalname PARAMS ((int));
-static char *
-errnoname PARAMS ((int));
+static char *errnoname PARAMS ((int));
-static int
-proc_address_to_fd PARAMS ((struct procinfo *, CORE_ADDR, int));
+static int proc_address_to_fd PARAMS ((struct procinfo *, CORE_ADDR, int));
-static int
-open_proc_file PARAMS ((int, struct procinfo *, int));
+static int open_proc_file PARAMS ((int, struct procinfo *, int));
-static void
-close_proc_file PARAMS ((struct procinfo *));
+static void close_proc_file PARAMS ((struct procinfo *));
-static void
-unconditionally_kill_inferior PARAMS ((struct procinfo *));
+static void unconditionally_kill_inferior PARAMS ((struct procinfo *));
-static NORETURN void
-proc_init_failed PARAMS ((struct procinfo *, char *));
+static NORETURN void proc_init_failed PARAMS ((struct procinfo *, char *)) ATTR_NORETURN;
-static void
-info_proc PARAMS ((char *, int));
+static void info_proc PARAMS ((char *, int));
-static void
-info_proc_flags PARAMS ((struct procinfo *, int));
+static void info_proc_flags PARAMS ((struct procinfo *, int));
-static void
-info_proc_stop PARAMS ((struct procinfo *, int));
+static void info_proc_stop PARAMS ((struct procinfo *, int));
-static void
-info_proc_siginfo PARAMS ((struct procinfo *, int));
+static void info_proc_siginfo PARAMS ((struct procinfo *, int));
-static void
-info_proc_syscalls PARAMS ((struct procinfo *, int));
+static void info_proc_syscalls PARAMS ((struct procinfo *, int));
-static void
-info_proc_mappings PARAMS ((struct procinfo *, int));
+static void info_proc_mappings PARAMS ((struct procinfo *, int));
-static void
-info_proc_signals PARAMS ((struct procinfo *, int));
+static void info_proc_signals PARAMS ((struct procinfo *, int));
-static void
-info_proc_faults PARAMS ((struct procinfo *, int));
+static void info_proc_faults PARAMS ((struct procinfo *, int));
-static char *
-mappingflags PARAMS ((long));
+static char *mappingflags PARAMS ((long));
-static char *
-lookupname PARAMS ((struct trans *, unsigned int, char *));
+static char *lookupname PARAMS ((struct trans *, unsigned int, char *));
-static char *
-lookupdesc PARAMS ((struct trans *, unsigned int));
+static char *lookupdesc PARAMS ((struct trans *, unsigned int));
-static int
-do_attach PARAMS ((int pid));
+static int do_attach PARAMS ((int pid));
-static void
-do_detach PARAMS ((int siggnal));
+static void do_detach PARAMS ((int siggnal));
-static void
-procfs_create_inferior PARAMS ((char *, char *, char **));
+static void procfs_create_inferior PARAMS ((char *, char *, char **));
-static void
-procfs_notice_signals PARAMS ((int pid));
+static void procfs_notice_signals PARAMS ((int pid));
-static struct procinfo *
-find_procinfo PARAMS ((pid_t pid, int okfail));
+static struct procinfo *find_procinfo PARAMS ((pid_t pid, int okfail));
/* External function prototypes that can't be easily included in any
header file because the args are typedefs in system include files. */
-extern void
-supply_gregset PARAMS ((gregset_t *));
+extern void supply_gregset PARAMS ((gregset_t *));
-extern void
-fill_gregset PARAMS ((gregset_t *, int));
+extern void fill_gregset PARAMS ((gregset_t *, int));
-extern void
-supply_fpregset PARAMS ((fpregset_t *));
+extern void supply_fpregset PARAMS ((fpregset_t *));
-extern void
-fill_fpregset PARAMS ((fpregset_t *, int));
+extern void fill_fpregset PARAMS ((fpregset_t *, int));
/*
int num_fds;
int i;
- if (attach_flag)
- set_sigint_trap (); /* Causes SIGINT to be passed on to the
+ set_sigint_trap (); /* Causes SIGINT to be passed on to the
attached process. */
set_sigio_trap ();
while (ioctl (pi->fd, PIOCWSTOP, &pi->prstatus) < 0)
{
- if (errno != EINTR)
+ if (errno == ENOENT)
+ {
+ /* Process exited. */
+ pi->prstatus.pr_flags = 0;
+ break;
+ }
+ else if (errno != EINTR)
{
print_sys_errmsg (pi->pathname, errno);
error ("PIOCWSTOP failed");
pi->had_event = 1;
#endif
- if (attach_flag)
- clear_sigint_trap();
+ clear_sigint_trap ();
clear_sigio_trap ();
#ifndef LOSING_POLL
ppid = pi->prstatus.pr_ppid;
signo = SIGKILL;
+
+#ifdef PROCFS_NEED_CLEAR_CURSIG_FOR_KILL
+ /* Alpha OSF/1-3.x procfs needs a clear of the current signal
+ before the PIOCKILL, otherwise it might generate a corrupted core
+ file for the inferior. */
+ ioctl (pi->fd, PIOCSSIG, NULL);
+#endif
+#ifdef PROCFS_NEED_PIOCSSIG_FOR_KILL
+ /* Alpha OSF/1-2.x procfs needs a PIOCSSIG call with a SIGKILL signal
+ to kill the inferior, otherwise it might remain stopped with a
+ pending SIGKILL.
+ We do not check the result of the PIOCSSIG, the inferior might have
+ died already. */
+ {
+ struct siginfo newsiginfo;
+
+ memset ((char *) &newsiginfo, 0, sizeof (newsiginfo));
+ newsiginfo.si_signo = signo;
+ newsiginfo.si_code = 0;
+ newsiginfo.si_errno = 0;
+ newsiginfo.si_pid = getpid ();
+ newsiginfo.si_uid = getuid ();
+ ioctl (pi->fd, PIOCSSIG, &newsiginfo);
+ }
+#else
ioctl (pi->fd, PIOCKILL, &signo);
+#endif
+
close_proc_file (pi);
/* Only wait() for our direct children. Our grandchildren zombies are killed
SYNOPSIS
- void create_procinfo (int pid)
+ struct procinfo * create_procinfo (int pid)
DESCRIPTION
- Allocate a procinfo structure, open the /proc file and then sets up
- the set of signals and faults that are to be traced.
+ Allocate a procinfo structure, open the /proc file and then set up the
+ set of signals and faults that are to be traced. Returns a pointer to
+ the new procinfo structure.
NOTES
*/
-static void
+static struct procinfo *
create_procinfo (pid)
int pid;
{
struct procinfo *pi;
- if (find_procinfo (pid, 1))
- return; /* All done! It already exists */
+ pi = find_procinfo (pid, 1);
+ if (pi != NULL)
+ return pi; /* All done! It already exists */
pi = (struct procinfo *) xmalloc (sizeof (struct procinfo));
prfillset (&pi->prrun.pr_fault);
prdelset (&pi->prrun.pr_fault, FLTPAGE);
+#ifdef PROCFS_DONT_TRACE_FAULTS
+ premptyset (&pi->prrun.pr_fault);
+#endif
+
if (ioctl (pi->fd, PIOCWSTOP, &pi->prstatus) < 0)
proc_init_failed (pi, "PIOCWSTOP failed");
if (ioctl (pi->fd, PIOCSFAULT, &pi->prrun.pr_fault) < 0)
proc_init_failed (pi, "PIOCSFAULT failed");
+
+ return pi;
}
/*
create_procinfo (pid);
add_thread (pid); /* Setup initial thread */
+#ifdef START_INFERIOR_TRAPS_EXPECTED
+ startup_inferior (START_INFERIOR_TRAPS_EXPECTED);
+#else
/* One trap to exec the shell, one to exec the program being debugged. */
startup_inferior (2);
+#endif
}
/*
premptyset (&exitset);
premptyset (&entryset);
+#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. */
+ {
+ int prfs_flags;
+
+ if (ioctl (fd, PIOCGSPCACT, &prfs_flags) < 0)
+ {
+ perror (procname);
+ gdb_flush (gdb_stderr);
+ _exit (127);
+ }
+ prfs_flags |= PRFS_STOPEXEC;
+ if (ioctl (fd, PIOCSSPCACT, &prfs_flags) < 0)
+ {
+ perror (procname);
+ gdb_flush (gdb_stderr);
+ _exit (127);
+ }
+ }
+#else
/* 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);
procfs_notice_signals (pid);
prfillset (&pi->prrun.pr_fault);
prdelset (&pi->prrun.pr_fault, FLTPAGE);
+
+#ifdef PROCFS_DONT_TRACE_FAULTS
+ premptyset (&pi->prrun.pr_fault);
+#endif
+
if (ioctl (pi->fd, PIOCSFAULT, &pi->prrun.pr_fault))
{
print_sys_errmsg ("PIOCSFAULT failed", errno);
if (signal || !pi->was_stopped ||
query ("Was stopped when attached, make it runnable again? "))
{
+ /* Clear any pending signal if we want to detach without
+ a signal. */
+ if (signal == 0)
+ set_proc_siginfo (pi, signal);
+
/* Clear any fault that might have stopped it. */
if (ioctl (pi->fd, PIOCCFAULT, 0))
- {
- print_sys_errmsg (pi->pathname, errno);
+ {
+ print_sys_errmsg (pi->pathname, errno);
printf_unfiltered ("PIOCCFAULT failed.\n");
- }
+ }
/* Make it run again when we close it. */
-#if defined (PIOCSET) /* New method */
+#if defined (PIOCSET) /* New method */
{
- long pr_flags;
- pr_flags = PR_RLC;
- result = ioctl (pi->fd, PIOCSET, &pr_flags);
+ long pr_flags;
+ pr_flags = PR_RLC;
+ result = ioctl (pi->fd, PIOCSET, &pr_flags);
}
#else
-#if defined (PIOCSRLC) /* Original method */
+#if defined (PIOCSRLC) /* Original method */
result = ioctl (pi->fd, PIOCSRLC, 0);
#endif
#endif
if (pi->had_event)
break;
-wait_again:
-
if (!pi)
- pi = wait_fd ();
+ {
+ wait_again:
+
+ pi = wait_fd ();
+ }
if (pid != -1)
for (pi = procinfo_list; pi; pi = pi->next)
statval = (SIGTRAP << 8) | 0177;
break;
+ case SYS_fork:
+#ifdef SYS_vfork
+ case SYS_vfork:
+#endif
+/* At this point, we've detected the completion of a fork (or vfork) call in
+ our child. The grandchild is also stopped because we set inherit-on-fork
+ earlier. (Note that nobody has the grandchilds' /proc file open at this
+ point.) We will release the grandchild from the debugger by opening it's
+ /proc file and then closing it. Since run-on-last-close is set, the
+ grandchild continues on its' merry way. */
+
+ {
+ struct procinfo *pitemp;
+
+ pitemp = create_procinfo (pi->prstatus.pr_rval1);
+ if (pitemp)
+ close_proc_file (pitemp);
+
+ if (ioctl (pi->fd, PIOCRUN, &pi->prrun) != 0)
+ perror_with_name (pi->pathname);
+ }
+ goto wait_again;
#endif /* SYS_sproc */
default:
struct siginfo newsiginfo;
struct siginfo *sip;
+#ifdef PROCFS_DONT_PIOCSSIG_CURSIG
+ /* 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. */
+ if (signo == pip -> prstatus.pr_cursig)
+ return;
+#endif
+
if (signo == pip -> prstatus.pr_info.si_signo)
{
sip = &pip -> prstatus.pr_info;
(sip -> si_signo == SIGSEGV) ||
(sip -> si_signo == SIGBUS))
{
- printf_filtered ("addr=%#x ", sip -> si_addr);
+ printf_filtered ("addr=%#lx ",
+ (unsigned long) sip -> si_addr);
}
else if ((sip -> si_signo == SIGCHLD))
{
if ((sip -> si_signo == SIGILL) ||
(sip -> si_signo == SIGFPE))
{
- printf_filtered ("\t%-16#x %s.\n", sip -> si_addr,
+ printf_filtered ("\t%#-16lx %s.\n",
+ (unsigned long) sip -> si_addr,
"Address of faulting instruction");
}
else if ((sip -> si_signo == SIGSEGV) ||
(sip -> si_signo == SIGBUS))
{
- printf_filtered ("\t%-16#x %s.\n", sip -> si_addr,
+ printf_filtered ("\t%#-16lx %s.\n",
+ (unsigned long) sip -> si_addr,
"Address of faulting memory reference");
}
else if ((sip -> si_signo == SIGCHLD))
signalname (signo)
int signo;
{
- char *name;
+ const char *name;
static char locbuf[32];
name = strsigno (signo);
errnoname (errnum)
int errnum;
{
- char *name;
+ const char *name;
static char locbuf[32];
name = strerrno (errnum);
printf_filtered ("%-8s ",
prismember (&pip -> prstatus.pr_sighold, signo)
? "on" : "off");
+
+#ifdef PROCFS_SIGPEND_OFFSET
+ /* Alpha OSF/1 numbers the pending signals from 1. */
+ printf_filtered ("%-8s ",
+ (signo ? prismember (&pip -> prstatus.pr_sigpend,
+ signo - 1)
+ : 0)
+ ? "yes" : "no");
+#else
printf_filtered ("%-8s ",
prismember (&pip -> prstatus.pr_sigpend, signo)
? "yes" : "no");
+#endif
printf_filtered (" %s\n", safe_strsignal (signo));
}
printf_filtered ("\n");
if (!summary)
{
printf_filtered ("Mapped address spaces:\n\n");
+#ifdef BFD_HOST_64_BIT
+ printf_filtered (" %18s %18s %10s %10s %7s\n",
+#else
printf_filtered ("\t%10s %10s %10s %10s %7s\n",
+#endif
"Start Addr",
" End Addr",
" Size",
{
for (prmap = prmaps; prmap -> pr_size; ++prmap)
{
- printf_filtered ("\t%#10x %#10x %#10x %#10x %7s\n",
- prmap -> pr_vaddr,
- prmap -> pr_vaddr + prmap -> pr_size - 1,
+#ifdef BFD_HOST_64_BIT
+ printf_filtered (" %#18lx %#18lx %#10x %#10x %7s\n",
+#else
+ printf_filtered ("\t%#10lx %#10lx %#10x %#10x %7s\n",
+#endif
+ (unsigned long)prmap -> pr_vaddr,
+ (unsigned long)prmap -> pr_vaddr
+ + prmap -> pr_size - 1,
prmap -> pr_size,
prmap -> pr_off,
mappingflags (prmap -> pr_mflags));
LOCAL FUNCTION
- procfs_set_sproc_trap -- arrange for exec'd child stop on sproc
+ procfs_set_sproc_trap -- arrange for child to stop on sproc().
SYNOPSIS
- void procfs_set_sproc_trap (void)
+ void procfs_set_sproc_trap (struct procinfo *)
DESCRIPTION
This function sets up a trap on sproc system call exits so that we can
- detect the arrival of a new thread. We are called with the child
+ detect the arrival of a new thread. We are called with the new thread
stopped prior to it's first instruction.
Also note that we turn on the inherit-on-fork flag in the child process
praddset (&exitset, SYS_sproc);
+ /* We trap on fork() and vfork() in order to disable debugging in our grand-
+ children and descendant processes. At this time, GDB can only handle
+ threads (multiple processes, one address space). forks (and execs) result
+ in the creation of multiple address spaces, which GDB can't handle yet. */
+
+ praddset (&exitset, SYS_fork);
+#ifdef SYS_vfork
+ praddset (&exitset, SYS_vfork);
+#endif
+
if (ioctl (pi->fd, PIOCSEXIT, &exitset) < 0)
{
print_sys_errmsg (pi->pathname, errno);
procfs_mourn_inferior ()
{
struct procinfo *pi;
+ struct procinfo *next_pi;
- for (pi = procinfo_list; pi; pi = pi->next)
- unconditionally_kill_inferior (pi);
+ for (pi = procinfo_list; pi; pi = next_pi)
+ {
+ next_pi = pi->next;
+ unconditionally_kill_inferior (pi);
+ }
unpush_target (&procfs_ops);
generic_mourn_inferior ();
}
+
/* Mark our target-struct as eligible for stray "run" and "attach" commands. */
static int
procfs_can_run ()
{
return(1);
}
-#ifdef TARGET_CAN_USE_HARDWARE_WATCHPOINT
+#ifdef TARGET_HAS_HARDWARE_WATCHPOINTS
\f
/* Insert a watchpoint */
int
}
#endif
+/* Send a SIGINT to the process group. This acts just like the user typed a
+ ^C on the controlling terminal.
+
+ XXX - This may not be correct for all systems. Some may want to use
+ killpg() instead of kill (-pgrp). */
+
+void
+procfs_stop ()
+{
+ extern pid_t inferior_process_group;
+
+ kill (-inferior_process_group, SIGINT);
+}
+
\f
struct target_ops procfs_ops = {
"procfs", /* to_shortname */
procfs_mourn_inferior, /* to_mourn_inferior */
procfs_can_run, /* to_can_run */
procfs_notice_signals, /* to_notice_signals */
+ 0, /* to_thread_alive */
+ procfs_stop, /* to_stop */
process_stratum, /* to_stratum */
0, /* to_next */
1, /* to_has_all_memory */
void
_initialize_procfs ()
{
+#ifdef HAVE_OPTIONAL_PROC_FS
+ char procname[32];
+ 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, PROC_NAME_FMT, getpid ());
+ if ((fd = open (procname, O_RDONLY)) < 0)
+ return;
+ close (fd);
+#endif
+
add_target (&procfs_ops);
add_info ("proc", info_proc,