aboutsummaryrefslogtreecommitdiff
path: root/gdb/procfs.c
diff options
context:
space:
mode:
authorStan Shebs <shebs@codesourcery.com>1999-04-16 01:34:07 +0000
committerStan Shebs <shebs@codesourcery.com>1999-04-16 01:34:07 +0000
commit071ea11e85eb9d529cc5eb3d35f6247466a21b99 (patch)
tree5deda65b8d7b04d1f4cbc534c3206d328e1267ec /gdb/procfs.c
parent1730ec6b1848f0f32154277f788fb29f88d8475b (diff)
downloadgdb-071ea11e85eb9d529cc5eb3d35f6247466a21b99.zip
gdb-071ea11e85eb9d529cc5eb3d35f6247466a21b99.tar.gz
gdb-071ea11e85eb9d529cc5eb3d35f6247466a21b99.tar.bz2
Initial creation of sourceware repository
Diffstat (limited to 'gdb/procfs.c')
-rw-r--r--gdb/procfs.c5826
1 files changed, 0 insertions, 5826 deletions
diff --git a/gdb/procfs.c b/gdb/procfs.c
deleted file mode 100644
index cd1bbe5..0000000
--- a/gdb/procfs.c
+++ /dev/null
@@ -1,5826 +0,0 @@
-/* Machine independent support for SVR4 /proc (process file system) for GDB.
- Copyright 1991, 1992-97, 1998 Free Software Foundation, Inc.
- Written by Fred Fish at Cygnus Support. Changes for sysv4.2mp procfs
- compatibility by Geoffrey Noer at Cygnus Solutions.
-
-This file is part of GDB.
-
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
-
-
-/* N O T E S
-
-For information on the details of using /proc consult section proc(4)
-in the UNIX System V Release 4 System Administrator's Reference Manual.
-
-The general register and floating point register sets are manipulated
-separately. This file makes the assumption that if FP0_REGNUM is
-defined, then support for the floating point register set is desired,
-regardless of whether or not the actual target has floating point hardware.
-
- */
-
-
-#include "defs.h"
-
-#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 "gdb_string.h"
-#include <stropts.h>
-#include <poll.h>
-#include <unistd.h>
-#include "gdb_stat.h"
-
-#include "inferior.h"
-#include "target.h"
-#include "command.h"
-#include "gdbcore.h"
-#include "gdbthread.h"
-
-#if !defined(SYS_lwp_create) && defined(SYS_lwpcreate)
-# define SYS_lwp_create SYS_lwpcreate
-#endif
-
-#if !defined(SYS_lwp_exit) && defined(SYS_lwpexit)
-# define SYS_lwp_exit SYS_lwpexit
-#endif
-
-#if !defined(SYS_lwp_wait) && defined(SYS_lwpwait)
-# define SYS_lwp_wait SYS_lwpwait
-#endif
-
-#if !defined(SYS_lwp_self) && defined(SYS_lwpself)
-# define SYS_lwp_self SYS_lwpself
-#endif
-
-#if !defined(SYS_lwp_info) && defined(SYS_lwpinfo)
-# define SYS_lwp_info SYS_lwpinfo
-#endif
-
-#if !defined(SYS_lwp_private) && defined(SYS_lwpprivate)
-# define SYS_lwp_private SYS_lwpprivate
-#endif
-
-#if !defined(SYS_lwp_kill) && defined(SYS_lwpkill)
-# define SYS_lwp_kill SYS_lwpkill
-#endif
-
-#if !defined(SYS_lwp_suspend) && defined(SYS_lwpsuspend)
-# define SYS_lwp_suspend SYS_lwpsuspend
-#endif
-
-#if !defined(SYS_lwp_continue) && defined(SYS_lwpcontinue)
-# define SYS_lwp_continue SYS_lwpcontinue
-#endif
-
-/* the name of the proc status struct depends on the implementation */
-#ifdef HAVE_PSTATUS_T
- typedef pstatus_t gdb_prstatus_t;
-#else
- typedef prstatus_t gdb_prstatus_t;
-#endif
-
-#define MAX_SYSCALLS 256 /* Maximum number of syscalls for table */
-
-/* proc name formats may vary depending on the proc implementation */
-#ifdef HAVE_MULTIPLE_PROC_FDS
-# ifndef CTL_PROC_NAME_FMT
-# define CTL_PROC_NAME_FMT "/proc/%d/ctl"
-# define AS_PROC_NAME_FMT "/proc/%d/as"
-# define MAP_PROC_NAME_FMT "/proc/%d/map"
-# define STATUS_PROC_NAME_FMT "/proc/%d/status"
-# endif
-#else /* HAVE_MULTIPLE_PROC_FDS */
-# ifndef CTL_PROC_NAME_FMT
-# define CTL_PROC_NAME_FMT "/proc/%05d"
-# define AS_PROC_NAME_FMT "/proc/%05d"
-# define MAP_PROC_NAME_FMT "/proc/%05d"
-# define STATUS_PROC_NAME_FMT "/proc/%05d"
-# endif
-#endif /* HAVE_MULTIPLE_PROC_FDS */
-
-
-/* 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
-
-
-#define MAX_PROC_NAME_SIZE sizeof("/proc/1234567890/status")
-
-struct target_ops procfs_ops;
-
-int procfs_suppress_run = 0; /* Non-zero if procfs should pretend not to
- be a runnable target. Used by targets
- that can sit atop procfs, such as solaris
- thread support. */
-
-#if 1 /* FIXME: Gross and ugly hack to resolve coredep.c global */
-CORE_ADDR kernel_u_addr;
-#endif
-
-#ifdef BROKEN_SIGINFO_H /* Workaround broken SGS <sys/siginfo.h> */
-#undef si_pid
-#define si_pid _data._proc.pid
-#undef si_uid
-#define si_uid _data._proc._pdata._kill.uid
-#endif /* BROKEN_SIGINFO_H */
-
-/* Define structures for passing commands to /proc/pid/ctl file. Note that
- while we create these for the PROCFS_USE_READ_WRITE world, we use them
- and ignore the extra cmd int in other proc schemes.
-*/
-/* generic ctl msg */
-struct proc_ctl {
- int cmd;
- long data;
-};
-
-/* set general registers */
-struct greg_ctl {
- int cmd;
- gdb_gregset_t gregset;
-};
-
-/* set fp registers */
-struct fpreg_ctl {
- int cmd;
- gdb_fpregset_t fpregset;
-};
-
-/* set signals to be traced */
-struct sig_ctl {
- int cmd;
- sigset_t sigset;
-};
-
-/* set faults to be traced */
-struct flt_ctl {
- int cmd;
- fltset_t fltset;
-};
-
-/* set system calls to be traced */
-struct sys_ctl {
- int cmd;
- sysset_t sysset;
-};
-
-/* set current signal to be traced */
-struct sigi_ctl {
- int cmd;
- siginfo_t siginfo;
-};
-
-/* All access to the inferior, either one started by gdb or one that has
- been attached to, is controlled by an instance of a procinfo structure,
- defined below. Since gdb currently only handles one inferior at a time,
- the procinfo structure for the inferior is statically allocated and
- only one exists at any given time. There is a separate procinfo
- structure for use by the "info proc" command, so that we can print
- useful information about any random process without interfering with
- the inferior's procinfo information. */
-
-struct procinfo {
- struct procinfo *next;
- int pid; /* Process ID of inferior */
- int ctl_fd; /* File descriptor for /proc ctl file */
- int status_fd; /* File descriptor for /proc status file */
- int as_fd; /* File descriptor for /proc as file */
- int map_fd; /* File descriptor for /proc map file */
- char *pathname; /* Pathname to /proc entry */
- int had_event; /* poll/select says something happened */
- int was_stopped; /* Nonzero if was stopped prior to attach */
- int nopass_next_sigstop; /* Don't pass a sigstop on next resume */
-#ifndef HAVE_NO_PRRUN_T
- prrun_t prrun; /* Control state when it is run */
-#endif
- gdb_prstatus_t prstatus; /* Current process status info */
- struct greg_ctl gregset; /* General register set */
- struct fpreg_ctl fpregset; /* Floating point register set */
- struct flt_ctl fltset; /* Current traced hardware fault set */
- struct sig_ctl trace; /* Current traced signal set */
- struct sys_ctl exitset; /* Current traced system call exit set */
- struct sys_ctl entryset; /* Current traced system call entry set */
- struct sig_ctl saved_sighold; /* Saved held signal set */
- struct flt_ctl saved_fltset; /* Saved traced hardware fault set */
- struct sig_ctl saved_trace; /* Saved traced signal set */
- struct sys_ctl saved_exitset; /* Saved traced system call exit set */
- struct sys_ctl saved_entryset;/* Saved traced system call entry set */
- int num_syscall_handlers; /* Number of syscall trap handlers
- currently installed */
- /* Pointer to list of syscall trap handlers */
- struct procfs_syscall_handler *syscall_handlers;
- int saved_rtnval; /* return value and status for wait(), */
- int saved_statval; /* as supplied by a syscall handler. */
- int new_child; /* Non-zero if it's a new thread */
-};
-
-/* List of inferior process information */
-static struct procinfo *procinfo_list = NULL;
-static struct pollfd *poll_list; /* pollfds used for waiting on /proc */
-
-static int num_poll_list = 0; /* Number of entries in poll_list */
-
-/* Much of the information used in the /proc interface, particularly for
- printing status information, is kept as tables of structures of the
- following form. These tables can be used to map numeric values to
- their symbolic names and to a string that describes their specific use. */
-
-struct trans {
- int value; /* The numeric value */
- char *name; /* The equivalent symbolic value */
- char *desc; /* Short description of value */
-};
-
-/* Translate bits in the pr_flags member of the prstatus structure, into the
- names and desc information. */
-
-static struct trans pr_flag_table[] =
-{
-#if defined (PR_STOPPED)
- { PR_STOPPED, "PR_STOPPED", "Process is stopped" },
-#endif
-#if defined (PR_ISTOP)
- { 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" },
-#endif
-#if defined (PR_ASLEEP)
- { 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" },
-#endif
-#if defined (PR_RLC)
- { 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" },
-#endif
-#if defined (PR_PCINVAL)
- { PR_PCINVAL, "PR_PCINVAL", "PC refers to an invalid virtual address" },
-#endif
-#if defined (PR_ISSYS)
- { PR_ISSYS, "PR_ISSYS", "Is a system process" },
-#endif
-#if defined (PR_STEP)
- { 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" },
-#endif
-#if defined (PR_ASYNC)
- { PR_ASYNC, "PR_ASYNC", "Asynchronous stop is in effect" },
-#endif
-#if defined (PR_PCOMPAT)
- { PR_PCOMPAT, "PR_PCOMPAT", "Ptrace compatibility mode in effect" },
-#endif
-#if defined (PR_MSACCT)
- { PR_MSACCT, "PR_MSACCT", "Microstate accounting enabled" },
-#endif
-#if defined (PR_BPTADJ)
- { PR_BPTADJ, "PR_BPTADJ", "Breakpoint PC adjustment in effect" },
-#endif
-#if defined (PR_ASLWP)
- { PR_ASLWP, "PR_ASLWP", "Asynchronus signal LWP" },
-#endif
- { 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" },
-#endif
-#if defined (PR_SIGNALLED)
- { PR_SIGNALLED, "PR_SIGNALLED", "Receipt of a traced signal" },
-#endif
-#if defined (PR_SYSENTRY)
- { 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" },
-#endif
-#if defined (PR_JOBCONTROL)
- { PR_JOBCONTROL, "PR_JOBCONTROL", "Default job control stop signal action" },
-#endif
-#if defined (PR_FAULTED)
- { PR_FAULTED, "PR_FAULTED", "Incurred a traced hardware fault" },
-#endif
-#if defined (PR_SUSPENDED)
- { PR_SUSPENDED, "PR_SUSPENDED", "Process suspended" },
-#endif
-#if defined (PR_CHECKPOINT)
- { PR_CHECKPOINT, "PR_CHECKPOINT", "(???)" },
-#endif
- { 0, NULL, NULL }
-};
-
-/* Hardware fault translation table. */
-
-static struct trans faults_table[] =
-{
-#if defined (FLTILL)
- { FLTILL, "FLTILL", "Illegal instruction" },
-#endif
-#if defined (FLTPRIV)
- { FLTPRIV, "FLTPRIV", "Privileged instruction" },
-#endif
-#if defined (FLTBPT)
- { FLTBPT, "FLTBPT", "Breakpoint trap" },
-#endif
-#if defined (FLTTRACE)
- { FLTTRACE, "FLTTRACE", "Trace trap" },
-#endif
-#if defined (FLTACCESS)
- { FLTACCESS, "FLTACCESS", "Memory access fault" },
-#endif
-#if defined (FLTBOUNDS)
- { FLTBOUNDS, "FLTBOUNDS", "Memory bounds violation" },
-#endif
-#if defined (FLTIOVF)
- { FLTIOVF, "FLTIOVF", "Integer overflow" },
-#endif
-#if defined (FLTIZDIV)
- { FLTIZDIV, "FLTIZDIV", "Integer zero divide" },
-#endif
-#if defined (FLTFPE)
- { FLTFPE, "FLTFPE", "Floating-point exception" },
-#endif
-#if defined (FLTSTACK)
- { FLTSTACK, "FLTSTACK", "Unrecoverable stack fault" },
-#endif
-#if defined (FLTPAGE)
- { FLTPAGE, "FLTPAGE", "Recoverable page fault" },
-#endif
- { 0, NULL, NULL }
-};
-
-/* Translation table for signal generation information. See UNIX System
- V Release 4 Programmer's Reference Manual, siginfo(5). */
-
-static struct sigcode {
- int signo;
- int code;
- char *codename;
- char *desc;
-} siginfo_table[] = {
-#if defined (SIGILL) && defined (ILL_ILLOPC)
- { SIGILL, ILL_ILLOPC, "ILL_ILLOPC", "Illegal opcode" },
-#endif
-#if defined (SIGILL) && defined (ILL_ILLOPN)
- { SIGILL, ILL_ILLOPN, "ILL_ILLOPN", "Illegal operand", },
-#endif
-#if defined (SIGILL) && defined (ILL_ILLADR)
- { SIGILL, ILL_ILLADR, "ILL_ILLADR", "Illegal addressing mode" },
-#endif
-#if defined (SIGILL) && defined (ILL_ILLTRP)
- { SIGILL, ILL_ILLTRP, "ILL_ILLTRP", "Illegal trap" },
-#endif
-#if defined (SIGILL) && defined (ILL_PRVOPC)
- { SIGILL, ILL_PRVOPC, "ILL_PRVOPC", "Privileged opcode" },
-#endif
-#if defined (SIGILL) && defined (ILL_PRVREG)
- { SIGILL, ILL_PRVREG, "ILL_PRVREG", "Privileged register" },
-#endif
-#if defined (SIGILL) && defined (ILL_COPROC)
- { SIGILL, ILL_COPROC, "ILL_COPROC", "Coprocessor error" },
-#endif
-#if defined (SIGILL) && defined (ILL_BADSTK)
- { SIGILL, ILL_BADSTK, "ILL_BADSTK", "Internal stack error" },
-#endif
-#if defined (SIGFPE) && defined (FPE_INTDIV)
- { SIGFPE, FPE_INTDIV, "FPE_INTDIV", "Integer divide by zero" },
-#endif
-#if defined (SIGFPE) && defined (FPE_INTOVF)
- { SIGFPE, FPE_INTOVF, "FPE_INTOVF", "Integer overflow" },
-#endif
-#if defined (SIGFPE) && defined (FPE_FLTDIV)
- { 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" },
-#endif
-#if defined (SIGFPE) && defined (FPE_FLTUND)
- { SIGFPE, FPE_FLTUND, "FPE_FLTUND", "Floating point underflow" },
-#endif
-#if defined (SIGFPE) && defined (FPE_FLTRES)
- { 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" },
-#endif
-#if defined (SIGFPE) && defined (FPE_FLTSUB)
- { 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" },
-#endif
-#if defined (SIGSEGV) && defined (SEGV_ACCERR)
- { SIGSEGV, SEGV_ACCERR, "SEGV_ACCERR", "Invalid permissions for object" },
-#endif
-#if defined (SIGBUS) && defined (BUS_ADRALN)
- { SIGBUS, BUS_ADRALN, "BUS_ADRALN", "Invalid address alignment" },
-#endif
-#if defined (SIGBUS) && defined (BUS_ADRERR)
- { 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" },
-#endif
-#if defined (SIGTRAP) && defined (TRAP_BRKPT)
- { SIGTRAP, TRAP_BRKPT, "TRAP_BRKPT", "Process breakpoint" },
-#endif
-#if defined (SIGTRAP) && defined (TRAP_TRACE)
- { SIGTRAP, TRAP_TRACE, "TRAP_TRACE", "Process trace trap" },
-#endif
-#if defined (SIGCLD) && defined (CLD_EXITED)
- { SIGCLD, CLD_EXITED, "CLD_EXITED", "Child has exited" },
-#endif
-#if defined (SIGCLD) && defined (CLD_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" },
-#endif
-#if defined (SIGCLD) && defined (CLD_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" },
-#endif
-#if defined (SIGCLD) && defined (CLD_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" },
-#endif
-#if defined (SIGPOLL) && defined (POLL_OUT)
- { SIGPOLL, POLL_OUT, "POLL_OUT", "Output buffers available" },
-#endif
-#if defined (SIGPOLL) && defined (POLL_MSG)
- { SIGPOLL, POLL_MSG, "POLL_MSG", "Input message available" },
-#endif
-#if defined (SIGPOLL) && defined (POLL_ERR)
- { SIGPOLL, POLL_ERR, "POLL_ERR", "I/O error" },
-#endif
-#if defined (SIGPOLL) && defined (POLL_PRI)
- { SIGPOLL, POLL_PRI, "POLL_PRI", "High priority input available" },
-#endif
-#if defined (SIGPOLL) && defined (POLL_HUP)
- { SIGPOLL, POLL_HUP, "POLL_HUP", "Device disconnected" },
-#endif
- { 0, 0, NULL, NULL }
-};
-
-static char *syscall_table[MAX_SYSCALLS];
-
-/* Prototypes for local functions */
-
-static void procfs_stop PARAMS ((void));
-
-static int procfs_thread_alive PARAMS ((int));
-
-static int procfs_can_run PARAMS ((void));
-
-static void procfs_mourn_inferior PARAMS ((void));
-
-static void procfs_fetch_registers PARAMS ((int));
-
-static int procfs_wait PARAMS ((int, struct target_waitstatus *));
-
-static void procfs_open PARAMS ((char *, int));
-
-static void procfs_files_info PARAMS ((struct target_ops *));
-
-static void procfs_prepare_to_store PARAMS ((void));
-
-static void procfs_detach PARAMS ((char *, int));
-
-static void procfs_attach PARAMS ((char *, int));
-
-static void proc_set_exec_trap PARAMS ((void));
-
-static void procfs_init_inferior PARAMS ((int));
-
-static struct procinfo *create_procinfo PARAMS ((int));
-
-static void procfs_store_registers PARAMS ((int));
-
-static int procfs_xfer_memory PARAMS ((CORE_ADDR, char *, int, int, struct target_ops *));
-
-static void procfs_kill_inferior PARAMS ((void));
-
-static char *sigcodedesc PARAMS ((siginfo_t *));
-
-static char *sigcodename PARAMS ((siginfo_t *));
-
-static struct procinfo *wait_fd PARAMS ((void));
-
-static void remove_fd PARAMS ((struct procinfo *));
-
-static void add_fd PARAMS ((struct procinfo *));
-
-static void set_proc_siginfo PARAMS ((struct procinfo *, int));
-
-static void init_syscall_table PARAMS ((void));
-
-static char *syscallname PARAMS ((int));
-
-static char *signalname PARAMS ((int));
-
-static char *errnoname PARAMS ((int));
-
-static int proc_address_to_fd PARAMS ((struct procinfo *, CORE_ADDR, int));
-
-static int open_proc_file PARAMS ((int, struct procinfo *, int, int));
-
-static void close_proc_file PARAMS ((struct procinfo *));
-
-static void unconditionally_kill_inferior PARAMS ((struct procinfo *));
-
-static NORETURN void proc_init_failed PARAMS ((struct procinfo *, char *, int)) ATTR_NORETURN;
-
-static void info_proc PARAMS ((char *, int));
-
-static void info_proc_flags 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_syscalls 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_faults PARAMS ((struct procinfo *, int));
-
-static char *mappingflags PARAMS ((long));
-
-static char *lookupname PARAMS ((struct trans *, unsigned int, char *));
-
-static char *lookupdesc PARAMS ((struct trans *, unsigned int));
-
-static int do_attach PARAMS ((int pid));
-
-static void do_detach PARAMS ((int siggnal));
-
-static void procfs_create_inferior PARAMS ((char *, char *, char **));
-
-static void procfs_notice_signals PARAMS ((int pid));
-
-static void notice_signals PARAMS ((struct procinfo *, struct sig_ctl *));
-
-static struct procinfo *find_procinfo PARAMS ((pid_t pid, int okfail));
-
-static int procfs_write_pcwstop PARAMS ((struct procinfo *));
-static int procfs_read_status PARAMS ((struct procinfo *));
-static void procfs_write_pckill PARAMS ((struct procinfo *));
-
-typedef int syscall_func_t PARAMS ((struct procinfo *pi, int syscall_num,
- int why, int *rtnval, int *statval));
-
-static void procfs_set_syscall_trap PARAMS ((struct procinfo *pi,
- int syscall_num, int flags,
- syscall_func_t *func));
-
-static void procfs_clear_syscall_trap PARAMS ((struct procinfo *pi,
- int syscall_num, int errok));
-
-#define PROCFS_SYSCALL_ENTRY 0x1 /* Trap on entry to sys call */
-#define PROCFS_SYSCALL_EXIT 0x2 /* Trap on exit from sys call */
-
-static syscall_func_t procfs_exit_handler;
-
-static syscall_func_t procfs_exec_handler;
-
-#ifdef SYS_sproc
-static syscall_func_t procfs_sproc_handler;
-static syscall_func_t procfs_fork_handler;
-#endif
-
-#ifdef SYS_lwp_create
-static syscall_func_t procfs_lwp_creation_handler;
-#endif
-
-static void modify_inherit_on_fork_flag PARAMS ((int fd, int flag));
-static void modify_run_on_last_close_flag PARAMS ((int fd, int flag));
-
-/* */
-
-struct procfs_syscall_handler
-{
- int syscall_num; /* The number of the system call being handled */
- /* The function to be called */
- syscall_func_t *func;
-};
-
-static void procfs_resume PARAMS ((int pid, int step,
- enum target_signal signo));
-
-static void init_procfs_ops PARAMS ((void));
-
-/* External function prototypes that can't be easily included in any
- header file because the args are typedefs in system include files. */
-
-extern void supply_gregset PARAMS ((gdb_gregset_t *));
-
-extern void fill_gregset PARAMS ((gdb_gregset_t *, int));
-
-#ifdef FP0_REGNUM
-extern void supply_fpregset PARAMS ((gdb_fpregset_t *));
-
-extern void fill_fpregset PARAMS ((gdb_fpregset_t *, int));
-#endif
-
-/*
-
-LOCAL FUNCTION
-
- find_procinfo -- convert a process id to a struct procinfo
-
-SYNOPSIS
-
- static struct procinfo * find_procinfo (pid_t pid, int okfail);
-
-DESCRIPTION
-
- Given a process id, look it up in the procinfo chain. Returns
- a struct procinfo *. If can't find pid, then call error(),
- unless okfail is set, in which case, return NULL;
- */
-
-static struct procinfo *
-find_procinfo (pid, okfail)
- pid_t pid;
- int okfail;
-{
- struct procinfo *procinfo;
-
- for (procinfo = procinfo_list; procinfo; procinfo = procinfo->next)
- if (procinfo->pid == pid)
- return procinfo;
-
- if (okfail)
- return NULL;
-
- error ("procfs (find_procinfo): Couldn't locate pid %d", pid);
-}
-
-/*
-
-LOCAL MACRO
-
- current_procinfo -- convert inferior_pid to a struct procinfo
-
-SYNOPSIS
-
- static struct procinfo * current_procinfo;
-
-DESCRIPTION
-
- Looks up inferior_pid in the procinfo chain. Always returns a
- struct procinfo *. If process can't be found, we error() out.
- */
-
-#define current_procinfo find_procinfo (inferior_pid, 0)
-
-/*
-
-LOCAL FUNCTION
-
- add_fd -- Add the fd to the poll/select list
-
-SYNOPSIS
-
- static void add_fd (struct procinfo *);
-
-DESCRIPTION
-
- Add the fd of the supplied procinfo to the list of fds used for
- poll/select operations.
- */
-
-static void
-add_fd (pi)
- struct procinfo *pi;
-{
- if (num_poll_list <= 0)
- poll_list = (struct pollfd *) xmalloc (sizeof (struct pollfd));
- else
- poll_list = (struct pollfd *) xrealloc (poll_list,
- (num_poll_list + 1)
- * sizeof (struct pollfd));
- poll_list[num_poll_list].fd = pi->ctl_fd;
-#ifdef UNIXWARE
- poll_list[num_poll_list].events = POLLWRNORM;
-#else
- poll_list[num_poll_list].events = POLLPRI;
-#endif
-
- num_poll_list++;
-}
-
-/*
-
-LOCAL FUNCTION
-
- remove_fd -- Remove the fd from the poll/select list
-
-SYNOPSIS
-
- static void remove_fd (struct procinfo *);
-
-DESCRIPTION
-
- Remove the fd of the supplied procinfo from the list of fds used
- for poll/select operations.
- */
-
-static void
-remove_fd (pi)
- struct procinfo *pi;
-{
- int i;
-
- for (i = 0; i < num_poll_list; i++)
- {
- if (poll_list[i].fd == pi->ctl_fd)
- {
- if (i != num_poll_list - 1)
- memcpy (poll_list + i, poll_list + i + 1,
- (num_poll_list - i - 1) * sizeof (struct pollfd));
-
- num_poll_list--;
-
- if (num_poll_list == 0)
- free (poll_list);
- else
- poll_list = (struct pollfd *) xrealloc (poll_list,
- num_poll_list
- * sizeof (struct pollfd));
- return;
- }
- }
-}
-
-/*
-
-LOCAL FUNCTION
-
- procfs_read_status - get procfs fd status
-
-SYNOPSIS
-
- static int procfs_read_status (pi) struct procinfo *pi;
-
-DESCRIPTION
-
- Given a pointer to a procinfo struct, get the status of
- the status_fd in the appropriate way. Returns 0 on failure,
- 1 on success.
- */
-
-static int
-procfs_read_status (pi)
- struct procinfo *pi;
-{
-#ifdef PROCFS_USE_READ_WRITE
- if ((lseek (pi->status_fd, 0, SEEK_SET) < 0) ||
- (read (pi->status_fd, (char *) &pi->prstatus,
- sizeof (gdb_prstatus_t)) != sizeof (gdb_prstatus_t)))
-#else
- if (ioctl (pi->status_fd, PIOCSTATUS, &pi->prstatus) < 0)
-#endif
- return 0;
- else
- return 1;
-}
-
-/*
-
-LOCAL FUNCTION
-
- procfs_write_pcwstop - send a PCWSTOP to procfs fd
-
-SYNOPSIS
-
- static int procfs_write_pcwstop (pi) struct procinfo *pi;
-
-DESCRIPTION
-
- Given a pointer to a procinfo struct, send a PCWSTOP to
- the ctl_fd in the appropriate way. Returns 0 on failure,
- 1 on success.
- */
-
-static int
-procfs_write_pcwstop (pi)
- struct procinfo *pi;
-{
-#ifdef PROCFS_USE_READ_WRITE
- long cmd = PCWSTOP;
- if (write (pi->ctl_fd, (char *) &cmd, sizeof (long)) < 0)
-#else
- if (ioctl (pi->ctl_fd, PIOCWSTOP, &pi->prstatus) < 0)
-#endif
- return 0;
- else
- return 1;
-}
-
-/*
-
-LOCAL FUNCTION
-
- procfs_write_pckill - send a kill to procfs fd
-
-SYNOPSIS
-
- static void procfs_write_pckill (pi) struct procinfo *pi;
-
-DESCRIPTION
-
- Given a pointer to a procinfo struct, send a kill to
- the ctl_fd in the appropriate way. Returns 0 on failure,
- 1 on success.
- */
-
-static void
-procfs_write_pckill (pi)
- struct procinfo *pi;
-{
-#ifdef PROCFS_USE_READ_WRITE
- struct proc_ctl pctl;
- pctl.cmd = PCKILL;
- pctl.data = SIGKILL;
- write (pi->ctl_fd, &pctl, sizeof (struct proc_ctl));
-#else
- int signo = SIGKILL;
- ioctl (pi->ctl_fd, PIOCKILL, &signo);
-#endif
-}
-
-static struct procinfo *
-wait_fd ()
-{
- struct procinfo *pi, *next_pi;
-#ifndef LOSING_POLL
- int num_fds;
- int i;
-#endif
-
- set_sigint_trap (); /* Causes SIGINT to be passed on to the
- attached process. */
- set_sigio_trap ();
-
- wait_again:
-#ifndef LOSING_POLL
- while (1)
- {
- num_fds = poll (poll_list, num_poll_list, -1);
- if (num_fds > 0)
- break;
- if (num_fds < 0 && errno == EINTR)
- continue;
- print_sys_errmsg ("poll failed", errno);
- error ("Poll failed, returned %d", num_fds);
- }
-#else /* LOSING_POLL */
- pi = current_procinfo;
-
- while (!procfs_write_pcwstop (pi))
- {
- if (errno == ENOENT)
- {
- /* Process exited. */
- pi->prstatus.pr_flags = 0;
- break;
- }
- else if (errno != EINTR)
- {
- print_sys_errmsg (pi->pathname, errno);
- error ("procfs_write_pcwstop failed");
- }
- }
- pi->had_event = 1;
-#endif /* LOSING_POLL */
-
- clear_sigint_trap ();
- clear_sigio_trap ();
-
-#ifndef LOSING_POLL
-
- for (i = 0; i < num_poll_list && num_fds > 0; i++)
- {
- if (0 == (poll_list[i].revents &
- (POLLWRNORM | POLLPRI | POLLERR | POLLHUP | POLLNVAL)))
- continue;
- for (pi = procinfo_list; pi; pi = next_pi)
- {
- next_pi = pi->next;
- if (poll_list[i].fd == pi->ctl_fd)
- {
- num_fds--;
- if ((poll_list[i].revents & POLLHUP) != 0 ||
- !procfs_read_status(pi))
- { /* The LWP has apparently terminated. */
- if (num_poll_list <= 1)
- {
- pi->prstatus.pr_flags = 0;
- pi->had_event = 1;
- break;
- }
- if (info_verbose)
- printf_filtered ("LWP %d exited.\n",
- (pi->pid >> 16) & 0xffff);
- close_proc_file (pi);
- i--; /* don't skip deleted entry */
- if (num_fds != 0)
- break; /* already another event to process */
- else
- goto wait_again; /* wait for another event */
- }
- pi->had_event = 1;
- break;
- }
- }
- if (!pi)
- error ("wait_fd: Couldn't find procinfo for fd %d\n",
- poll_list[i].fd);
- }
-#endif /* LOSING_POLL */
-
- return pi;
-}
-
-/*
-
-LOCAL FUNCTION
-
- lookupdesc -- translate a value to a summary desc string
-
-SYNOPSIS
-
- static char *lookupdesc (struct trans *transp, unsigned int val);
-
-DESCRIPTION
-
- Given a pointer to a translation table and a value to be translated,
- lookup the desc string and return it.
- */
-
-static char *
-lookupdesc (transp, val)
- struct trans *transp;
- unsigned int val;
-{
- char *desc;
-
- for (desc = NULL; transp -> name != NULL; transp++)
- {
- if (transp -> value == val)
- {
- desc = transp -> desc;
- break;
- }
- }
-
- /* Didn't find a translation for the specified value, set a default one. */
-
- if (desc == NULL)
- {
- desc = "Unknown";
- }
- return (desc);
-}
-
-/*
-
-LOCAL FUNCTION
-
- lookupname -- translate a value to symbolic name
-
-SYNOPSIS
-
- static char *lookupname (struct trans *transp, unsigned int val,
- char *prefix);
-
-DESCRIPTION
-
- Given a pointer to a translation table, a value to be translated,
- and a default prefix to return if the value can't be translated,
- match the value with one of the translation table entries and
- return a pointer to the symbolic name.
-
- If no match is found it just returns the value as a printable string,
- with the given prefix. The previous such value, if any, is freed
- at this time.
- */
-
-static char *
-lookupname (transp, val, prefix)
- struct trans *transp;
- unsigned int val;
- char *prefix;
-{
- static char *locbuf;
- char *name;
-
- for (name = NULL; transp -> name != NULL; transp++)
- {
- if (transp -> value == val)
- {
- name = transp -> name;
- break;
- }
- }
-
- /* Didn't find a translation for the specified value, build a default
- one using the specified prefix and return it. The lifetime of
- the value is only until the next one is needed. */
-
- if (name == NULL)
- {
- if (locbuf != NULL)
- {
- free (locbuf);
- }
- locbuf = xmalloc (strlen (prefix) + 16);
- sprintf (locbuf, "%s %u", prefix, val);
- name = locbuf;
- }
- return (name);
-}
-
-static char *
-sigcodename (sip)
- siginfo_t *sip;
-{
- struct sigcode *scp;
- char *name = NULL;
- static char locbuf[32];
-
- for (scp = siginfo_table; scp -> codename != NULL; scp++)
- {
- if ((scp -> signo == sip -> si_signo) &&
- (scp -> code == sip -> si_code))
- {
- name = scp -> codename;
- break;
- }
- }
- if (name == NULL)
- {
- sprintf (locbuf, "sigcode %u", sip -> si_signo);
- name = locbuf;
- }
- return (name);
-}
-
-static char *
-sigcodedesc (sip)
- siginfo_t *sip;
-{
- struct sigcode *scp;
- char *desc = NULL;
-
- for (scp = siginfo_table; scp -> codename != NULL; scp++)
- {
- if ((scp -> signo == sip -> si_signo) &&
- (scp -> code == sip -> si_code))
- {
- desc = scp -> desc;
- break;
- }
- }
- if (desc == NULL)
- {
- desc = "Unrecognized signal or trap use";
- }
- return (desc);
-}
-
-/*
-
-LOCAL FUNCTION
-
- syscallname - translate a system call number into a system call name
-
-SYNOPSIS
-
- char *syscallname (int syscallnum)
-
-DESCRIPTION
-
- Given a system call number, translate it into the printable name
- of a system call, or into "syscall <num>" if it is an unknown
- number.
- */
-
-static char *
-syscallname (syscallnum)
- int syscallnum;
-{
- static char locbuf[32];
-
- if (syscallnum >= 0 && syscallnum < MAX_SYSCALLS
- && syscall_table[syscallnum] != NULL)
- return syscall_table[syscallnum];
- else
- {
- sprintf (locbuf, "syscall %u", syscallnum);
- return locbuf;
- }
-}
-
-/*
-
-LOCAL FUNCTION
-
- init_syscall_table - initialize syscall translation table
-
-SYNOPSIS
-
- void init_syscall_table (void)
-
-DESCRIPTION
-
- Dynamically initialize the translation table to convert system
- call numbers into printable system call names. Done once per
- gdb run, on initialization.
-
-NOTES
-
- This is awfully ugly, but preprocessor tricks to make it prettier
- tend to be nonportable.
- */
-
-static void
-init_syscall_table ()
-{
-#if defined (SYS_exit)
- syscall_table[SYS_exit] = "exit";
-#endif
-#if defined (SYS_fork)
- syscall_table[SYS_fork] = "fork";
-#endif
-#if defined (SYS_read)
- syscall_table[SYS_read] = "read";
-#endif
-#if defined (SYS_write)
- syscall_table[SYS_write] = "write";
-#endif
-#if defined (SYS_open)
- syscall_table[SYS_open] = "open";
-#endif
-#if defined (SYS_close)
- syscall_table[SYS_close] = "close";
-#endif
-#if defined (SYS_wait)
- syscall_table[SYS_wait] = "wait";
-#endif
-#if defined (SYS_creat)
- syscall_table[SYS_creat] = "creat";
-#endif
-#if defined (SYS_link)
- syscall_table[SYS_link] = "link";
-#endif
-#if defined (SYS_unlink)
- syscall_table[SYS_unlink] = "unlink";
-#endif
-#if defined (SYS_exec)
- syscall_table[SYS_exec] = "exec";
-#endif
-#if defined (SYS_execv)
- syscall_table[SYS_execv] = "execv";
-#endif
-#if defined (SYS_execve)
- syscall_table[SYS_execve] = "execve";
-#endif
-#if defined (SYS_chdir)
- syscall_table[SYS_chdir] = "chdir";
-#endif
-#if defined (SYS_time)
- syscall_table[SYS_time] = "time";
-#endif
-#if defined (SYS_mknod)
- syscall_table[SYS_mknod] = "mknod";
-#endif
-#if defined (SYS_chmod)
- syscall_table[SYS_chmod] = "chmod";
-#endif
-#if defined (SYS_chown)
- syscall_table[SYS_chown] = "chown";
-#endif
-#if defined (SYS_brk)
- syscall_table[SYS_brk] = "brk";
-#endif
-#if defined (SYS_stat)
- syscall_table[SYS_stat] = "stat";
-#endif
-#if defined (SYS_lseek)
- syscall_table[SYS_lseek] = "lseek";
-#endif
-#if defined (SYS_getpid)
- syscall_table[SYS_getpid] = "getpid";
-#endif
-#if defined (SYS_mount)
- syscall_table[SYS_mount] = "mount";
-#endif
-#if defined (SYS_umount)
- syscall_table[SYS_umount] = "umount";
-#endif
-#if defined (SYS_setuid)
- syscall_table[SYS_setuid] = "setuid";
-#endif
-#if defined (SYS_getuid)
- syscall_table[SYS_getuid] = "getuid";
-#endif
-#if defined (SYS_stime)
- syscall_table[SYS_stime] = "stime";
-#endif
-#if defined (SYS_ptrace)
- syscall_table[SYS_ptrace] = "ptrace";
-#endif
-#if defined (SYS_alarm)
- syscall_table[SYS_alarm] = "alarm";
-#endif
-#if defined (SYS_fstat)
- syscall_table[SYS_fstat] = "fstat";
-#endif
-#if defined (SYS_pause)
- syscall_table[SYS_pause] = "pause";
-#endif
-#if defined (SYS_utime)
- syscall_table[SYS_utime] = "utime";
-#endif
-#if defined (SYS_stty)
- syscall_table[SYS_stty] = "stty";
-#endif
-#if defined (SYS_gtty)
- syscall_table[SYS_gtty] = "gtty";
-#endif
-#if defined (SYS_access)
- syscall_table[SYS_access] = "access";
-#endif
-#if defined (SYS_nice)
- syscall_table[SYS_nice] = "nice";
-#endif
-#if defined (SYS_statfs)
- syscall_table[SYS_statfs] = "statfs";
-#endif
-#if defined (SYS_sync)
- syscall_table[SYS_sync] = "sync";
-#endif
-#if defined (SYS_kill)
- syscall_table[SYS_kill] = "kill";
-#endif
-#if defined (SYS_fstatfs)
- syscall_table[SYS_fstatfs] = "fstatfs";
-#endif
-#if defined (SYS_pgrpsys)
- syscall_table[SYS_pgrpsys] = "pgrpsys";
-#endif
-#if defined (SYS_xenix)
- syscall_table[SYS_xenix] = "xenix";
-#endif
-#if defined (SYS_dup)
- syscall_table[SYS_dup] = "dup";
-#endif
-#if defined (SYS_pipe)
- syscall_table[SYS_pipe] = "pipe";
-#endif
-#if defined (SYS_times)
- syscall_table[SYS_times] = "times";
-#endif
-#if defined (SYS_profil)
- syscall_table[SYS_profil] = "profil";
-#endif
-#if defined (SYS_plock)
- syscall_table[SYS_plock] = "plock";
-#endif
-#if defined (SYS_setgid)
- syscall_table[SYS_setgid] = "setgid";
-#endif
-#if defined (SYS_getgid)
- syscall_table[SYS_getgid] = "getgid";
-#endif
-#if defined (SYS_signal)
- syscall_table[SYS_signal] = "signal";
-#endif
-#if defined (SYS_msgsys)
- syscall_table[SYS_msgsys] = "msgsys";
-#endif
-#if defined (SYS_sys3b)
- syscall_table[SYS_sys3b] = "sys3b";
-#endif
-#if defined (SYS_sysi86)
- syscall_table[SYS_sysi86] = "sysi86";
-#endif
-#if defined (SYS_acct)
- syscall_table[SYS_acct] = "acct";
-#endif
-#if defined (SYS_shmsys)
- syscall_table[SYS_shmsys] = "shmsys";
-#endif
-#if defined (SYS_semsys)
- syscall_table[SYS_semsys] = "semsys";
-#endif
-#if defined (SYS_ioctl)
- syscall_table[SYS_ioctl] = "ioctl";
-#endif
-#if defined (SYS_uadmin)
- syscall_table[SYS_uadmin] = "uadmin";
-#endif
-#if defined (SYS_utssys)
- syscall_table[SYS_utssys] = "utssys";
-#endif
-#if defined (SYS_fsync)
- syscall_table[SYS_fsync] = "fsync";
-#endif
-#if defined (SYS_umask)
- syscall_table[SYS_umask] = "umask";
-#endif
-#if defined (SYS_chroot)
- syscall_table[SYS_chroot] = "chroot";
-#endif
-#if defined (SYS_fcntl)
- syscall_table[SYS_fcntl] = "fcntl";
-#endif
-#if defined (SYS_ulimit)
- syscall_table[SYS_ulimit] = "ulimit";
-#endif
-#if defined (SYS_rfsys)
- syscall_table[SYS_rfsys] = "rfsys";
-#endif
-#if defined (SYS_rmdir)
- syscall_table[SYS_rmdir] = "rmdir";
-#endif
-#if defined (SYS_mkdir)
- syscall_table[SYS_mkdir] = "mkdir";
-#endif
-#if defined (SYS_getdents)
- syscall_table[SYS_getdents] = "getdents";
-#endif
-#if defined (SYS_sysfs)
- syscall_table[SYS_sysfs] = "sysfs";
-#endif
-#if defined (SYS_getmsg)
- syscall_table[SYS_getmsg] = "getmsg";
-#endif
-#if defined (SYS_putmsg)
- syscall_table[SYS_putmsg] = "putmsg";
-#endif
-#if defined (SYS_poll)
- syscall_table[SYS_poll] = "poll";
-#endif
-#if defined (SYS_lstat)
- syscall_table[SYS_lstat] = "lstat";
-#endif
-#if defined (SYS_symlink)
- syscall_table[SYS_symlink] = "symlink";
-#endif
-#if defined (SYS_readlink)
- syscall_table[SYS_readlink] = "readlink";
-#endif
-#if defined (SYS_setgroups)
- syscall_table[SYS_setgroups] = "setgroups";
-#endif
-#if defined (SYS_getgroups)
- syscall_table[SYS_getgroups] = "getgroups";
-#endif
-#if defined (SYS_fchmod)
- syscall_table[SYS_fchmod] = "fchmod";
-#endif
-#if defined (SYS_fchown)
- syscall_table[SYS_fchown] = "fchown";
-#endif
-#if defined (SYS_sigprocmask)
- syscall_table[SYS_sigprocmask] = "sigprocmask";
-#endif
-#if defined (SYS_sigsuspend)
- syscall_table[SYS_sigsuspend] = "sigsuspend";
-#endif
-#if defined (SYS_sigaltstack)
- syscall_table[SYS_sigaltstack] = "sigaltstack";
-#endif
-#if defined (SYS_sigaction)
- syscall_table[SYS_sigaction] = "sigaction";
-#endif
-#if defined (SYS_sigpending)
- syscall_table[SYS_sigpending] = "sigpending";
-#endif
-#if defined (SYS_context)
- syscall_table[SYS_context] = "context";
-#endif
-#if defined (SYS_evsys)
- syscall_table[SYS_evsys] = "evsys";
-#endif
-#if defined (SYS_evtrapret)
- syscall_table[SYS_evtrapret] = "evtrapret";
-#endif
-#if defined (SYS_statvfs)
- syscall_table[SYS_statvfs] = "statvfs";
-#endif
-#if defined (SYS_fstatvfs)
- syscall_table[SYS_fstatvfs] = "fstatvfs";
-#endif
-#if defined (SYS_nfssys)
- syscall_table[SYS_nfssys] = "nfssys";
-#endif
-#if defined (SYS_waitsys)
- syscall_table[SYS_waitsys] = "waitsys";
-#endif
-#if defined (SYS_sigsendsys)
- syscall_table[SYS_sigsendsys] = "sigsendsys";
-#endif
-#if defined (SYS_hrtsys)
- syscall_table[SYS_hrtsys] = "hrtsys";
-#endif
-#if defined (SYS_acancel)
- syscall_table[SYS_acancel] = "acancel";
-#endif
-#if defined (SYS_async)
- syscall_table[SYS_async] = "async";
-#endif
-#if defined (SYS_priocntlsys)
- syscall_table[SYS_priocntlsys] = "priocntlsys";
-#endif
-#if defined (SYS_pathconf)
- syscall_table[SYS_pathconf] = "pathconf";
-#endif
-#if defined (SYS_mincore)
- syscall_table[SYS_mincore] = "mincore";
-#endif
-#if defined (SYS_mmap)
- syscall_table[SYS_mmap] = "mmap";
-#endif
-#if defined (SYS_mprotect)
- syscall_table[SYS_mprotect] = "mprotect";
-#endif
-#if defined (SYS_munmap)
- syscall_table[SYS_munmap] = "munmap";
-#endif
-#if defined (SYS_fpathconf)
- syscall_table[SYS_fpathconf] = "fpathconf";
-#endif
-#if defined (SYS_vfork)
- syscall_table[SYS_vfork] = "vfork";
-#endif
-#if defined (SYS_fchdir)
- syscall_table[SYS_fchdir] = "fchdir";
-#endif
-#if defined (SYS_readv)
- syscall_table[SYS_readv] = "readv";
-#endif
-#if defined (SYS_writev)
- syscall_table[SYS_writev] = "writev";
-#endif
-#if defined (SYS_xstat)
- syscall_table[SYS_xstat] = "xstat";
-#endif
-#if defined (SYS_lxstat)
- syscall_table[SYS_lxstat] = "lxstat";
-#endif
-#if defined (SYS_fxstat)
- syscall_table[SYS_fxstat] = "fxstat";
-#endif
-#if defined (SYS_xmknod)
- syscall_table[SYS_xmknod] = "xmknod";
-#endif
-#if defined (SYS_clocal)
- syscall_table[SYS_clocal] = "clocal";
-#endif
-#if defined (SYS_setrlimit)
- syscall_table[SYS_setrlimit] = "setrlimit";
-#endif
-#if defined (SYS_getrlimit)
- syscall_table[SYS_getrlimit] = "getrlimit";
-#endif
-#if defined (SYS_lchown)
- syscall_table[SYS_lchown] = "lchown";
-#endif
-#if defined (SYS_memcntl)
- syscall_table[SYS_memcntl] = "memcntl";
-#endif
-#if defined (SYS_getpmsg)
- syscall_table[SYS_getpmsg] = "getpmsg";
-#endif
-#if defined (SYS_putpmsg)
- syscall_table[SYS_putpmsg] = "putpmsg";
-#endif
-#if defined (SYS_rename)
- syscall_table[SYS_rename] = "rename";
-#endif
-#if defined (SYS_uname)
- syscall_table[SYS_uname] = "uname";
-#endif
-#if defined (SYS_setegid)
- syscall_table[SYS_setegid] = "setegid";
-#endif
-#if defined (SYS_sysconfig)
- syscall_table[SYS_sysconfig] = "sysconfig";
-#endif
-#if defined (SYS_adjtime)
- syscall_table[SYS_adjtime] = "adjtime";
-#endif
-#if defined (SYS_systeminfo)
- syscall_table[SYS_systeminfo] = "systeminfo";
-#endif
-#if defined (SYS_seteuid)
- syscall_table[SYS_seteuid] = "seteuid";
-#endif
-#if defined (SYS_sproc)
- syscall_table[SYS_sproc] = "sproc";
-#endif
-#if defined (SYS_keyctl)
- syscall_table[SYS_keyctl] = "keyctl";
-#endif
-#if defined (SYS_secsys)
- syscall_table[SYS_secsys] = "secsys";
-#endif
-#if defined (SYS_filepriv)
- syscall_table[SYS_filepriv] = "filepriv";
-#endif
-#if defined (SYS_procpriv)
- syscall_table[SYS_procpriv] = "procpriv";
-#endif
-#if defined (SYS_devstat)
- syscall_table[SYS_devstat] = "devstat";
-#endif
-#if defined (SYS_aclipc)
- syscall_table[SYS_aclipc] = "aclipc";
-#endif
-#if defined (SYS_fdevstat)
- syscall_table[SYS_fdevstat] = "fdevstat";
-#endif
-#if defined (SYS_flvlfile)
- syscall_table[SYS_flvlfile] = "flvlfile";
-#endif
-#if defined (SYS_lvlfile)
- syscall_table[SYS_lvlfile] = "lvlfile";
-#endif
-#if defined (SYS_lvlequal)
- syscall_table[SYS_lvlequal] = "lvlequal";
-#endif
-#if defined (SYS_lvlproc)
- syscall_table[SYS_lvlproc] = "lvlproc";
-#endif
-#if defined (SYS_lvlipc)
- syscall_table[SYS_lvlipc] = "lvlipc";
-#endif
-#if defined (SYS_acl)
- syscall_table[SYS_acl] = "acl";
-#endif
-#if defined (SYS_auditevt)
- syscall_table[SYS_auditevt] = "auditevt";
-#endif
-#if defined (SYS_auditctl)
- syscall_table[SYS_auditctl] = "auditctl";
-#endif
-#if defined (SYS_auditdmp)
- syscall_table[SYS_auditdmp] = "auditdmp";
-#endif
-#if defined (SYS_auditlog)
- syscall_table[SYS_auditlog] = "auditlog";
-#endif
-#if defined (SYS_auditbuf)
- syscall_table[SYS_auditbuf] = "auditbuf";
-#endif
-#if defined (SYS_lvldom)
- syscall_table[SYS_lvldom] = "lvldom";
-#endif
-#if defined (SYS_lvlvfs)
- syscall_table[SYS_lvlvfs] = "lvlvfs";
-#endif
-#if defined (SYS_mkmld)
- syscall_table[SYS_mkmld] = "mkmld";
-#endif
-#if defined (SYS_mldmode)
- syscall_table[SYS_mldmode] = "mldmode";
-#endif
-#if defined (SYS_secadvise)
- syscall_table[SYS_secadvise] = "secadvise";
-#endif
-#if defined (SYS_online)
- syscall_table[SYS_online] = "online";
-#endif
-#if defined (SYS_setitimer)
- syscall_table[SYS_setitimer] = "setitimer";
-#endif
-#if defined (SYS_getitimer)
- syscall_table[SYS_getitimer] = "getitimer";
-#endif
-#if defined (SYS_gettimeofday)
- syscall_table[SYS_gettimeofday] = "gettimeofday";
-#endif
-#if defined (SYS_settimeofday)
- syscall_table[SYS_settimeofday] = "settimeofday";
-#endif
-#if defined (SYS_lwp_create)
- syscall_table[SYS_lwp_create] = "_lwp_create";
-#endif
-#if defined (SYS_lwp_exit)
- syscall_table[SYS_lwp_exit] = "_lwp_exit";
-#endif
-#if defined (SYS_lwp_wait)
- syscall_table[SYS_lwp_wait] = "_lwp_wait";
-#endif
-#if defined (SYS_lwp_self)
- syscall_table[SYS_lwp_self] = "_lwp_self";
-#endif
-#if defined (SYS_lwp_info)
- syscall_table[SYS_lwp_info] = "_lwp_info";
-#endif
-#if defined (SYS_lwp_private)
- syscall_table[SYS_lwp_private] = "_lwp_private";
-#endif
-#if defined (SYS_processor_bind)
- syscall_table[SYS_processor_bind] = "processor_bind";
-#endif
-#if defined (SYS_processor_exbind)
- syscall_table[SYS_processor_exbind] = "processor_exbind";
-#endif
-#if defined (SYS_prepblock)
- syscall_table[SYS_prepblock] = "prepblock";
-#endif
-#if defined (SYS_block)
- syscall_table[SYS_block] = "block";
-#endif
-#if defined (SYS_rdblock)
- syscall_table[SYS_rdblock] = "rdblock";
-#endif
-#if defined (SYS_unblock)
- syscall_table[SYS_unblock] = "unblock";
-#endif
-#if defined (SYS_cancelblock)
- syscall_table[SYS_cancelblock] = "cancelblock";
-#endif
-#if defined (SYS_pread)
- syscall_table[SYS_pread] = "pread";
-#endif
-#if defined (SYS_pwrite)
- syscall_table[SYS_pwrite] = "pwrite";
-#endif
-#if defined (SYS_truncate)
- syscall_table[SYS_truncate] = "truncate";
-#endif
-#if defined (SYS_ftruncate)
- syscall_table[SYS_ftruncate] = "ftruncate";
-#endif
-#if defined (SYS_lwp_kill)
- syscall_table[SYS_lwp_kill] = "_lwp_kill";
-#endif
-#if defined (SYS_sigwait)
- syscall_table[SYS_sigwait] = "sigwait";
-#endif
-#if defined (SYS_fork1)
- syscall_table[SYS_fork1] = "fork1";
-#endif
-#if defined (SYS_forkall)
- syscall_table[SYS_forkall] = "forkall";
-#endif
-#if defined (SYS_modload)
- syscall_table[SYS_modload] = "modload";
-#endif
-#if defined (SYS_moduload)
- syscall_table[SYS_moduload] = "moduload";
-#endif
-#if defined (SYS_modpath)
- syscall_table[SYS_modpath] = "modpath";
-#endif
-#if defined (SYS_modstat)
- syscall_table[SYS_modstat] = "modstat";
-#endif
-#if defined (SYS_modadm)
- syscall_table[SYS_modadm] = "modadm";
-#endif
-#if defined (SYS_getksym)
- syscall_table[SYS_getksym] = "getksym";
-#endif
-#if defined (SYS_lwp_suspend)
- syscall_table[SYS_lwp_suspend] = "_lwp_suspend";
-#endif
-#if defined (SYS_lwp_continue)
- syscall_table[SYS_lwp_continue] = "_lwp_continue";
-#endif
-#if defined (SYS_priocntllst)
- syscall_table[SYS_priocntllst] = "priocntllst";
-#endif
-#if defined (SYS_sleep)
- syscall_table[SYS_sleep] = "sleep";
-#endif
-#if defined (SYS_lwp_sema_wait)
- syscall_table[SYS_lwp_sema_wait] = "_lwp_sema_wait";
-#endif
-#if defined (SYS_lwp_sema_post)
- syscall_table[SYS_lwp_sema_post] = "_lwp_sema_post";
-#endif
-#if defined (SYS_lwp_sema_trywait)
- syscall_table[SYS_lwp_sema_trywait] = "lwp_sema_trywait";
-#endif
-#if defined(SYS_fstatvfs64)
- syscall_table[SYS_fstatvfs64] = "fstatvfs64";
-#endif
-#if defined(SYS_statvfs64)
- syscall_table[SYS_statvfs64] = "statvfs64";
-#endif
-#if defined(SYS_ftruncate64)
- syscall_table[SYS_ftruncate64] = "ftruncate64";
-#endif
-#if defined(SYS_truncate64)
- syscall_table[SYS_truncate64] = "truncate64";
-#endif
-#if defined(SYS_getrlimit64)
- syscall_table[SYS_getrlimit64] = "getrlimit64";
-#endif
-#if defined(SYS_setrlimit64)
- syscall_table[SYS_setrlimit64] = "setrlimit64";
-#endif
-#if defined(SYS_lseek64)
- syscall_table[SYS_lseek64] = "lseek64";
-#endif
-#if defined(SYS_mmap64)
- syscall_table[SYS_mmap64] = "mmap64";
-#endif
-#if defined(SYS_pread64)
- syscall_table[SYS_pread64] = "pread64";
-#endif
-#if defined(SYS_creat64)
- syscall_table[SYS_creat64] = "creat64";
-#endif
-#if defined(SYS_dshmsys)
- syscall_table[SYS_dshmsys] = "dshmsys";
-#endif
-#if defined(SYS_invlpg)
- syscall_table[SYS_invlpg] = "invlpg";
-#endif
-#if defined(SYS_cg_ids)
- syscall_table[SYS_cg_ids] = "cg_ids";
-#endif
-#if defined(SYS_cg_processors)
- syscall_table[SYS_cg_processors] = "cg_processors";
-#endif
-#if defined(SYS_cg_info)
- syscall_table[SYS_cg_info] = "cg_info";
-#endif
-#if defined(SYS_cg_bind)
- syscall_table[SYS_cg_bind] = "cg_bind";
-#endif
-#if defined(SYS_cg_current)
- syscall_table[SYS_cg_current] = "cg_current";
-#endif
-#if defined(SYS_cg_memloc)
- syscall_table[SYS_cg_memloc] = "cg_memloc";
-#endif
-}
-
-/*
-
-LOCAL FUNCTION
-
- procfs_kill_inferior - kill any currently inferior
-
-SYNOPSIS
-
- void procfs_kill_inferior (void)
-
-DESCRIPTION
-
- Kill any current inferior.
-
-NOTES
-
- Kills even attached inferiors. Presumably the user has already
- been prompted that the inferior is an attached one rather than
- one started by gdb. (FIXME?)
-
-*/
-
-static void
-procfs_kill_inferior ()
-{
- target_mourn_inferior ();
-}
-
-/*
-
-LOCAL FUNCTION
-
- unconditionally_kill_inferior - terminate the inferior
-
-SYNOPSIS
-
- static void unconditionally_kill_inferior (struct procinfo *)
-
-DESCRIPTION
-
- Kill the specified inferior.
-
-NOTE
-
- A possibly useful enhancement would be to first try sending
- the inferior a terminate signal, politely asking it to commit
- suicide, before we murder it (we could call that
- politely_kill_inferior()).
-
-*/
-
-static void
-unconditionally_kill_inferior (pi)
- struct procinfo *pi;
-{
- int ppid;
- struct proc_ctl pctl;
-
- ppid = pi->prstatus.pr_ppid;
-
-#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->ctl_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 = SIGKILL;
- newsiginfo.si_code = 0;
- newsiginfo.si_errno = 0;
- newsiginfo.si_pid = getpid ();
- newsiginfo.si_uid = getuid ();
- ioctl (pi->ctl_fd, PIOCSSIG, &newsiginfo);
- }
-#else /* PROCFS_NEED_PIOCSSIG_FOR_KILL */
- procfs_write_pckill (pi);
-#endif /* PROCFS_NEED_PIOCSSIG_FOR_KILL */
-
- close_proc_file (pi);
-
-/* Only wait() for our direct children. Our grandchildren zombies are killed
- by the death of their parents. */
-
- if (ppid == getpid())
- wait ((int *) 0);
-}
-
-/*
-
-LOCAL FUNCTION
-
- procfs_xfer_memory -- copy data to or from inferior memory space
-
-SYNOPSIS
-
- int procfs_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len,
- int dowrite, struct target_ops target)
-
-DESCRIPTION
-
- Copy LEN bytes to/from inferior's memory starting at MEMADDR
- from/to debugger memory starting at MYADDR. Copy from inferior
- if DOWRITE is zero or to inferior if DOWRITE is nonzero.
-
- Returns the length copied, which is either the LEN argument or
- zero. This xfer function does not do partial moves, since procfs_ops
- doesn't allow memory operations to cross below us in the target stack
- anyway.
-
-NOTES
-
- The /proc interface makes this an almost trivial task.
- */
-
-static int
-procfs_xfer_memory (memaddr, myaddr, len, dowrite, target)
- CORE_ADDR memaddr;
- char *myaddr;
- int len;
- int dowrite;
- struct target_ops *target; /* ignored */
-{
- int nbytes = 0;
- struct procinfo *pi;
-
- pi = current_procinfo;
-
- if (lseek(pi->as_fd, (off_t) memaddr, SEEK_SET) == (off_t) memaddr)
- {
- if (dowrite)
- {
- nbytes = write (pi->as_fd, myaddr, len);
- }
- else
- {
- nbytes = read (pi->as_fd, myaddr, len);
- }
- if (nbytes < 0)
- {
- nbytes = 0;
- }
- }
- return (nbytes);
-}
-
-/*
-
-LOCAL FUNCTION
-
- procfs_store_registers -- copy register values back to inferior
-
-SYNOPSIS
-
- void procfs_store_registers (int regno)
-
-DESCRIPTION
-
- Store our current register values back into the inferior. If
- REGNO is -1 then store all the register, otherwise store just
- the value specified by REGNO.
-
-NOTES
-
- If we are storing only a single register, we first have to get all
- the current values from the process, overwrite the desired register
- in the gregset with the one we want from gdb's registers, and then
- send the whole set back to the process. For writing all the
- registers, all we have to do is generate the gregset and send it to
- the process.
-
- Also note that the process has to be stopped on an event of interest
- for this to work, which basically means that it has to have been
- run under the control of one of the other /proc ioctl calls and not
- ptrace. Since we don't use ptrace anyway, we don't worry about this
- fine point, but it is worth noting for future reference.
-
- Gdb is confused about what this function is supposed to return.
- Some versions return a value, others return nothing. Some are
- declared to return a value and actually return nothing. Gdb ignores
- anything returned. (FIXME)
-
- */
-
-static void
-procfs_store_registers (regno)
- int regno;
-{
- struct procinfo *pi;
-#ifdef PROCFS_USE_READ_WRITE
- struct greg_ctl greg;
- struct fpreg_ctl fpreg;
-#endif
-
- pi = current_procinfo;
-
-#ifdef PROCFS_USE_READ_WRITE
- if (regno != -1)
- {
- procfs_read_status (pi);
- memcpy ((char *) &greg.gregset,
- (char *) &pi->prstatus.pr_lwp.pr_context.uc_mcontext.gregs,
- sizeof (gdb_gregset_t));
- }
- fill_gregset (&greg.gregset, regno);
- greg.cmd = PCSREG;
- write (pi->ctl_fd, &greg, sizeof (greg));
-#else /* PROCFS_USE_READ_WRITE */
- if (regno != -1)
- {
- ioctl (pi->ctl_fd, PIOCGREG, &pi->gregset.gregset);
- }
- fill_gregset (&pi->gregset.gregset, regno);
- ioctl (pi->ctl_fd, PIOCSREG, &pi->gregset.gregset);
-#endif /* PROCFS_USE_READ_WRITE */
-
-#if defined (FP0_REGNUM)
-
- /* Now repeat everything using the floating point register set, if the
- target has floating point hardware. Since we ignore the returned value,
- we'll never know whether it worked or not anyway. */
-
-#ifdef PROCFS_USE_READ_WRITE
- if (regno != -1)
- {
- procfs_read_status (pi);
- memcpy ((char *) &fpreg.fpregset,
- (char *) &pi->prstatus.pr_lwp.pr_context.uc_mcontext.fpregs,
- sizeof (gdb_fpregset_t));
- }
- fill_fpregset (&fpreg.fpregset, regno);
- fpreg.cmd = PCSFPREG;
- write (pi->ctl_fd, &fpreg, sizeof (fpreg));
-#else /* PROCFS_USE_READ_WRITE */
- if (regno != -1)
- {
- ioctl (pi->ctl_fd, PIOCGFPREG, &pi->fpregset.fpregset);
- }
- fill_fpregset (&pi->fpregset.fpregset, regno);
- ioctl (pi->ctl_fd, PIOCSFPREG, &pi->fpregset.fpregset);
-#endif /* PROCFS_USE_READ_WRITE */
-
-#endif /* FP0_REGNUM */
-
-}
-
-/*
-
-LOCAL FUNCTION
-
- init_procinfo - setup a procinfo struct and connect it to a process
-
-SYNOPSIS
-
- struct procinfo * init_procinfo (int pid)
-
-DESCRIPTION
-
- 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
-
- If proc_init_failed ever gets called, control returns to the command
- processing loop via the standard error handling code.
-
- */
-
-static struct procinfo *
-init_procinfo (pid, kill)
- int pid;
- int kill;
-{
- struct procinfo *pi = (struct procinfo *)
- xmalloc (sizeof (struct procinfo));
- struct sig_ctl sctl;
- struct flt_ctl fctl;
-
- memset ((char *) pi, 0, sizeof (*pi));
- if (!open_proc_file (pid, pi, O_RDWR, 1))
- proc_init_failed (pi, "can't open process file", kill);
-
- /* open_proc_file may modify pid. */
-
- pid = pi -> pid;
-
- /* Add new process to process info list */
-
- pi->next = procinfo_list;
- procinfo_list = pi;
-
- add_fd (pi); /* Add to list for poll/select */
-
- /* Remember some things about the inferior that we will, or might, change
- so that we can restore them when we detach. */
-#ifdef UNIXWARE
- memcpy ((char *) &pi->saved_trace.sigset,
- (char *) &pi->prstatus.pr_sigtrace, sizeof (sigset_t));
- memcpy ((char *) &pi->saved_fltset.fltset,
- (char *) &pi->prstatus.pr_flttrace, sizeof (fltset_t));
- memcpy ((char *) &pi->saved_entryset.sysset,
- (char *) &pi->prstatus.pr_sysentry, sizeof (sysset_t));
- memcpy ((char *) &pi->saved_exitset.sysset,
- (char *) &pi->prstatus.pr_sysexit, sizeof (sysset_t));
-
- /* Set up trace and fault sets, as gdb expects them. */
-
- prfillset (&sctl.sigset);
- notice_signals (pi, &sctl);
- prfillset (&fctl.fltset);
- prdelset (&fctl.fltset, FLTPAGE);
-
-#else /* ! UNIXWARE */
- ioctl (pi->ctl_fd, PIOCGTRACE, &pi->saved_trace.sigset);
- ioctl (pi->ctl_fd, PIOCGHOLD, &pi->saved_sighold.sigset);
- ioctl (pi->ctl_fd, PIOCGFAULT, &pi->saved_fltset.fltset);
- ioctl (pi->ctl_fd, PIOCGENTRY, &pi->saved_entryset.sysset);
- ioctl (pi->ctl_fd, PIOCGEXIT, &pi->saved_exitset.sysset);
-
- /* Set up trace and fault sets, as gdb expects them. */
-
- memset ((char *) &pi->prrun, 0, sizeof (pi->prrun));
- prfillset (&pi->prrun.pr_trace);
- 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
-#endif /* UNIXWARE */
-
- if (!procfs_read_status (pi))
- proc_init_failed (pi, "procfs_read_status failed", kill);
-
- return pi;
-}
-
-/*
-
-LOCAL FUNCTION
-
- create_procinfo - initialize access to a /proc entry
-
-SYNOPSIS
-
- struct procinfo * create_procinfo (int pid)
-
-DESCRIPTION
-
- 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
-
- If proc_init_failed ever gets called, control returns to the command
- processing loop via the standard error handling code.
-
- */
-
-static struct procinfo *
-create_procinfo (pid)
- int pid;
-{
- struct procinfo *pi;
- struct sig_ctl sctl;
- struct flt_ctl fctl;
-
- pi = find_procinfo (pid, 1);
- if (pi != NULL)
- return pi; /* All done! It already exists */
-
- pi = init_procinfo (pid, 1);
-
-#ifndef UNIXWARE
-/* A bug in Solaris (2.5 at least) causes PIOCWSTOP to hang on LWPs that are
- already stopped, even if they all have PR_ASYNC set. */
- if (!(pi->prstatus.pr_flags & PR_STOPPED))
-#endif
- if (!procfs_write_pcwstop (pi))
- proc_init_failed (pi, "procfs_write_pcwstop failed", 1);
-
-#ifdef PROCFS_USE_READ_WRITE
- fctl.cmd = PCSFAULT;
- if (write (pi->ctl_fd, (char *) &fctl, sizeof (struct flt_ctl)) < 0)
- proc_init_failed (pi, "PCSFAULT failed", 1);
-#else
- if (ioctl (pi->ctl_fd, PIOCSFAULT, &pi->prrun.pr_fault) < 0)
- proc_init_failed (pi, "PIOCSFAULT failed", 1);
-#endif
-
- return pi;
-}
-
-/*
-
-LOCAL FUNCTION
-
- procfs_exit_handler - handle entry into the _exit syscall
-
-SYNOPSIS
-
- int procfs_exit_handler (pi, syscall_num, why, rtnvalp, statvalp)
-
-DESCRIPTION
-
- This routine is called when an inferior process enters the _exit()
- system call. It continues the process, and then collects the exit
- status and pid which are returned in *statvalp and *rtnvalp. After
- that it returns non-zero to indicate that procfs_wait should wake up.
-
-NOTES
- There is probably a better way to do this.
-
- */
-
-static int
-procfs_exit_handler (pi, syscall_num, why, rtnvalp, statvalp)
- struct procinfo *pi;
- int syscall_num;
- int why;
- int *rtnvalp;
- int *statvalp;
-{
- struct procinfo *temp_pi, *next_pi;
- struct proc_ctl pctl;
-
-#ifdef UNIXWARE
- pctl.cmd = PCRUN;
- pctl.data = PRCFAULT;
-#else
- pi->prrun.pr_flags = PRCFAULT;
-#endif
-
-#ifdef PROCFS_USE_READ_WRITE
- if (write (pi->ctl_fd, (char *)&pctl, sizeof (struct proc_ctl)) < 0)
-#else
- if (ioctl (pi->ctl_fd, PIOCRUN, &pi->prrun) != 0)
-#endif
- perror_with_name (pi->pathname);
-
- if (attach_flag)
- {
- /* Claim it exited (don't call wait). */
- if (info_verbose)
- printf_filtered ("(attached process has exited)\n");
- *statvalp = 0;
- *rtnvalp = inferior_pid;
- }
- else
- {
- *rtnvalp = wait (statvalp);
- if (*rtnvalp >= 0)
- *rtnvalp = pi->pid;
- }
-
- /* Close ALL open proc file handles,
- except the one that called SYS_exit. */
- for (temp_pi = procinfo_list; temp_pi; temp_pi = next_pi)
- {
- next_pi = temp_pi->next;
- if (temp_pi == pi)
- continue; /* Handled below */
- close_proc_file (temp_pi);
- }
- return 1;
-}
-
-/*
-
-LOCAL FUNCTION
-
- procfs_exec_handler - handle exit from the exec family of syscalls
-
-SYNOPSIS
-
- int procfs_exec_handler (pi, syscall_num, why, rtnvalp, statvalp)
-
-DESCRIPTION
-
- This routine is called when an inferior process is about to finish any
- of the exec() family of system calls. It pretends that we got a
- SIGTRAP (for compatibility with ptrace behavior), and returns non-zero
- to tell procfs_wait to wake up.
-
-NOTES
- This need for compatibility with ptrace is questionable. In the
- future, it shouldn't be necessary.
-
- */
-
-static int
-procfs_exec_handler (pi, syscall_num, why, rtnvalp, statvalp)
- struct procinfo *pi;
- int syscall_num;
- int why;
- int *rtnvalp;
- int *statvalp;
-{
- *statvalp = (SIGTRAP << 8) | 0177;
-
- return 1;
-}
-
-#if defined(SYS_sproc) && !defined(UNIXWARE)
-/* IRIX lwp creation system call */
-
-/*
-
-LOCAL FUNCTION
-
- procfs_sproc_handler - handle exit from the sproc syscall
-
-SYNOPSIS
-
- int procfs_sproc_handler (pi, syscall_num, why, rtnvalp, statvalp)
-
-DESCRIPTION
-
- This routine is called when an inferior process is about to finish an
- sproc() system call. This is the system call that IRIX uses to create
- a lightweight process. When the target process gets this event, we can
- look at rval1 to find the new child processes ID, and create a new
- procinfo struct from that.
-
- After that, it pretends that we got a SIGTRAP, and returns non-zero
- to tell procfs_wait to wake up. Subsequently, wait_for_inferior gets
- woken up, sees the new process and continues it.
-
-NOTES
- We actually never see the child exiting from sproc because we will
- shortly stop the child with PIOCSTOP, which is then registered as the
- event of interest.
- */
-
-static int
-procfs_sproc_handler (pi, syscall_num, why, rtnvalp, statvalp)
- struct procinfo *pi;
- int syscall_num;
- int why;
- int *rtnvalp;
- int *statvalp;
-{
-/* We've just detected the completion of an sproc system call. Now we need to
- setup a procinfo struct for this thread, and notify the thread system of the
- new arrival. */
-
-/* If sproc failed, then nothing interesting happened. Continue the process
- and go back to sleep. */
-
- if (pi->prstatus.pr_errno != 0)
- {
- pi->prrun.pr_flags &= PRSTEP;
- pi->prrun.pr_flags |= PRCFAULT;
-
- if (ioctl (pi->ctl_fd, PIOCRUN, &pi->prrun) != 0)
- perror_with_name (pi->pathname);
-
- return 0;
- }
-
- /* At this point, the new thread is stopped at it's first instruction, and
- the parent is stopped at the exit from sproc. */
-
- /* Notify the caller of the arrival of a new thread. */
- create_procinfo (pi->prstatus.pr_rval1);
-
- *rtnvalp = pi->prstatus.pr_rval1;
- *statvalp = (SIGTRAP << 8) | 0177;
-
- return 1;
-}
-
-/*
-
-LOCAL FUNCTION
-
- procfs_fork_handler - handle exit from the fork syscall
-
-SYNOPSIS
-
- int procfs_fork_handler (pi, syscall_num, why, rtnvalp, statvalp)
-
-DESCRIPTION
-
- This routine is called when an inferior process is about to finish a
- fork() system call. We will open up the new process, and then close
- it, which releases it from the clutches of the debugger.
-
- After that, we continue the target process as though nothing had
- happened.
-
-NOTES
- This is necessary for IRIX because we have to set PR_FORK in order
- to catch the creation of lwps (via sproc()). When an actual fork
- occurs, it becomes necessary to reset the forks debugger flags and
- continue it because we can't hack multiple processes yet.
- */
-
-static int
-procfs_fork_handler (pi, syscall_num, why, rtnvalp, statvalp)
- struct procinfo *pi;
- int syscall_num;
- int why;
- int *rtnvalp;
- int *statvalp;
-{
- struct procinfo *pitemp;
-
-/* 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. */
-
-
- pitemp = create_procinfo (pi->prstatus.pr_rval1);
- if (pitemp)
- close_proc_file (pitemp);
-
- if (ioctl (pi->ctl_fd, PIOCRUN, &pi->prrun) != 0)
- perror_with_name (pi->pathname);
-
- return 0;
-}
-#endif /* SYS_sproc && !UNIXWARE */
-
-/*
-
-LOCAL FUNCTION
-
- procfs_set_inferior_syscall_traps - setup the syscall traps
-
-SYNOPSIS
-
- void procfs_set_inferior_syscall_traps (struct procinfo *pip)
-
-DESCRIPTION
-
- Called for each "procinfo" (process, thread, or LWP) in the
- inferior, to register for notification of and handlers for
- syscall traps in the inferior.
-
- */
-
-static void
-procfs_set_inferior_syscall_traps (pip)
- struct procinfo *pip;
-{
- procfs_set_syscall_trap (pip, SYS_exit, PROCFS_SYSCALL_ENTRY,
- procfs_exit_handler);
-
-#ifndef PRFS_STOPEXEC
-#ifdef SYS_exec
- procfs_set_syscall_trap (pip, SYS_exec, PROCFS_SYSCALL_EXIT,
- procfs_exec_handler);
-#endif
-#ifdef SYS_execv
- procfs_set_syscall_trap (pip, SYS_execv, PROCFS_SYSCALL_EXIT,
- procfs_exec_handler);
-#endif
-#ifdef SYS_execve
- procfs_set_syscall_trap (pip, SYS_execve, PROCFS_SYSCALL_EXIT,
- procfs_exec_handler);
-#endif
-#endif /* PRFS_STOPEXEC */
-
- /* Setup traps on exit from sproc() */
-
-#ifdef SYS_sproc
- procfs_set_syscall_trap (pip, SYS_sproc, PROCFS_SYSCALL_EXIT,
- procfs_sproc_handler);
- procfs_set_syscall_trap (pip, SYS_fork, PROCFS_SYSCALL_EXIT,
- procfs_fork_handler);
-#ifdef SYS_vfork
- procfs_set_syscall_trap (pip, SYS_vfork, PROCFS_SYSCALL_EXIT,
- procfs_fork_handler);
-#endif
-/* Turn on inherit-on-fork flag so that all children of the target process
- start with tracing flags set. This allows us to trap lwp creation. Note
- that we also have to trap on fork and vfork in order to disable all tracing
- in the targets child processes. */
-
- modify_inherit_on_fork_flag (pip->ctl_fd, 1);
-#endif
-
-#ifdef SYS_lwp_create
- procfs_set_syscall_trap (pip, SYS_lwp_create, PROCFS_SYSCALL_EXIT,
- procfs_lwp_creation_handler);
-#endif
-}
-
-/*
-
-LOCAL FUNCTION
-
- procfs_init_inferior - initialize target vector and access to a
- /proc entry
-
-SYNOPSIS
-
- void procfs_init_inferior (int pid)
-
-DESCRIPTION
-
- When gdb starts an inferior, this function is called in the parent
- process immediately after the fork. It waits for the child to stop
- on the return from the exec system call (the child itself takes care
- of ensuring that this is set up), then sets up the set of signals
- and faults that are to be traced. Returns the pid, which may have had
- the thread-id added to it.
-
-NOTES
-
- If proc_init_failed ever gets called, control returns to the command
- processing loop via the standard error handling code.
-
- */
-
-static void
-procfs_init_inferior (pid)
- int pid;
-{
- struct procinfo *pip;
-
- push_target (&procfs_ops);
-
- pip = create_procinfo (pid);
-
- procfs_set_inferior_syscall_traps (pip);
-
- /* create_procinfo may change the pid, so we have to update inferior_pid
- here before calling other gdb routines that need the right pid. */
-
- pid = pip -> pid;
- inferior_pid = pid;
-
- add_thread (pip -> 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
-}
-
-/*
-
-GLOBAL FUNCTION
-
- procfs_notice_signals
-
-SYNOPSIS
-
- static void procfs_notice_signals (int pid);
-
-DESCRIPTION
-
- When the user changes the state of gdb's signal handling via the
- "handle" command, this function gets called to see if any change
- in the /proc interface is required. It is also called internally
- by other /proc interface functions to initialize the state of
- the traced signal set.
-
- One thing it does is that signals for which the state is "nostop",
- "noprint", and "pass", have their trace bits reset in the pr_trace
- field, so that they are no longer traced. This allows them to be
- delivered directly to the inferior without the debugger ever being
- involved.
- */
-
-static void
-procfs_notice_signals (pid)
- int pid;
-{
- struct procinfo *pi;
- struct sig_ctl sctl;
-
- pi = find_procinfo (pid, 0);
-
-#ifdef UNIXWARE
- premptyset (&sctl.sigset);
-#else
- sctl.sigset = pi->prrun.pr_trace;
-#endif
-
- notice_signals (pi, &sctl);
-
-#ifndef UNIXWARE
- pi->prrun.pr_trace = sctl.sigset;
-#endif
-}
-
-static void
-notice_signals (pi, sctl)
- struct procinfo *pi;
- struct sig_ctl *sctl;
-{
- int signo;
-
- for (signo = 0; signo < NSIG; signo++)
- {
- if (signal_stop_state (target_signal_from_host (signo)) == 0 &&
- signal_print_state (target_signal_from_host (signo)) == 0 &&
- signal_pass_state (target_signal_from_host (signo)) == 1)
- {
- prdelset (&sctl->sigset, signo);
- }
- else
- {
- praddset (&sctl->sigset, signo);
- }
- }
-#ifdef PROCFS_USE_READ_WRITE
- sctl->cmd = PCSTRACE;
- if (write (pi->ctl_fd, (char *) sctl, sizeof (struct sig_ctl)) < 0)
-#else
- if (ioctl (pi->ctl_fd, PIOCSTRACE, &sctl->sigset))
-#endif
- {
- print_sys_errmsg ("PIOCSTRACE failed", errno);
- }
-}
-
-/*
-
-LOCAL FUNCTION
-
- proc_set_exec_trap -- arrange for exec'd child to halt at startup
-
-SYNOPSIS
-
- void proc_set_exec_trap (void)
-
-DESCRIPTION
-
- This function is called in the child process when starting up
- an inferior, prior to doing the exec of the actual inferior.
- It sets the child process's exitset to make exit from the exec
- system call an event of interest to stop on, and then simply
- returns. The child does the exec, the system call returns, and
- the child stops at the first instruction, ready for the gdb
- parent process to take control of it.
-
-NOTE
-
- We need to use all local variables since the child may be sharing
- it's data space with the parent, if vfork was used rather than
- fork.
-
- Also note that we want to turn off the inherit-on-fork flag in
- the child process so that any grand-children start with all
- tracing flags cleared.
- */
-
-static void
-proc_set_exec_trap ()
-{
- struct sys_ctl exitset;
- struct sys_ctl entryset;
- char procname[MAX_PROC_NAME_SIZE];
- int fd;
-
- sprintf (procname, CTL_PROC_NAME_FMT, getpid ());
-#ifdef UNIXWARE
- if ((fd = open (procname, O_WRONLY)) < 0)
-#else
- if ((fd = open (procname, O_RDWR)) < 0)
-#endif
- {
- perror (procname);
- gdb_flush (gdb_stderr);
- _exit (127);
- }
- premptyset (&exitset.sysset);
- premptyset (&entryset.sysset);
-
-#ifdef PRFS_STOPEXEC
- /* 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 /* PRFS_STOPEXEC */
- /* 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
- *is* a SYS_execv. So, we try to account for that. */
-
-#ifdef SYS_exec
- praddset (&exitset.sysset, SYS_exec);
-#endif
-#ifdef SYS_execve
- praddset (&exitset.sysset, SYS_execve);
-#endif
-#ifdef SYS_execv
- praddset (&exitset.sysset, SYS_execv);
-#endif
-
-#ifdef PROCFS_USE_READ_WRITE
- exitset.cmd = PCSEXIT;
- if (write (fd, (char *) &exitset, sizeof (struct sys_ctl)) < 0)
-#else
- if (ioctl (fd, PIOCSEXIT, &exitset.sysset) < 0)
-#endif
- {
- perror (procname);
- gdb_flush (gdb_stderr);
- _exit (127);
- }
-#endif /* PRFS_STOPEXEC */
-
- praddset (&entryset.sysset, SYS_exit);
-
-#ifdef PROCFS_USE_READ_WRITE
- entryset.cmd = PCSENTRY;
- if (write (fd, (char *) &entryset, sizeof (struct sys_ctl)) < 0)
-#else
- if (ioctl (fd, PIOCSENTRY, &entryset.sysset) < 0)
-#endif
- {
- perror (procname);
- gdb_flush (gdb_stderr);
- _exit (126);
- }
-
- /* Turn off inherit-on-fork flag so that all grand-children of gdb
- start with tracing flags cleared. */
-
- modify_inherit_on_fork_flag (fd, 0);
-
- /* Turn on run-on-last-close flag so that this process will not hang
- if GDB goes away for some reason. */
-
- modify_run_on_last_close_flag (fd, 1);
-
-#ifndef UNIXWARE /* since this is a solaris-ism, we don't want it */
- /* NOTE: revisit when doing thread support for UW */
-#ifdef PR_ASYNC
- {
- long pr_flags;
- struct proc_ctl pctl;
-
-/* Solaris needs this to make procfs treat all threads seperately. Without
- this, all threads halt whenever something happens to any thread. Since
- GDB wants to control all this itself, it needs to set PR_ASYNC. */
-
- pr_flags = PR_ASYNC;
-#ifdef PROCFS_USE_READ_WRITE
- pctl.cmd = PCSET;
- pctl.data = PR_FORK|PR_ASYNC;
- write (fd, (char *) &pctl, sizeof (struct proc_ctl));
-#else
- ioctl (fd, PIOCSET, &pr_flags);
-#endif
- }
-#endif /* PR_ASYNC */
-#endif /* !UNIXWARE */
-}
-
-/*
-
-GLOBAL FUNCTION
-
- proc_iterate_over_mappings -- call function for every mapped space
-
-SYNOPSIS
-
- int proc_iterate_over_mappings (int (*func)())
-
-DESCRIPTION
-
- Given a pointer to a function, call that function for every
- mapped address space, passing it an open file descriptor for
- the file corresponding to that mapped address space (if any)
- and the base address of the mapped space. Quit when we hit
- the end of the mappings or the function returns nonzero.
- */
-
-#ifdef UNIXWARE
-int
-proc_iterate_over_mappings (func)
- int (*func) PARAMS ((int, CORE_ADDR));
-{
- int nmap;
- int fd;
- int funcstat = 0;
- prmap_t *prmaps;
- prmap_t *prmap;
- struct procinfo *pi;
- struct stat sbuf;
-
- pi = current_procinfo;
-
- if (fstat (pi->map_fd, &sbuf) < 0)
- return 0;
-
- nmap = sbuf.st_size / sizeof (prmap_t);
- prmaps = (prmap_t *) alloca (nmap * sizeof(prmap_t));
- if ((lseek (pi->map_fd, 0, SEEK_SET) == 0) &&
- (read (pi->map_fd, (char *) prmaps, nmap * sizeof (prmap_t)) ==
- (nmap * sizeof (prmap_t))))
- {
- int i = 0;
- for (prmap = prmaps; i < nmap && funcstat == 0; ++prmap, ++i)
- {
- char name[sizeof ("/proc/1234567890/object") +
- sizeof (prmap->pr_mapname)];
- sprintf (name, "/proc/%d/object/%s", pi->pid, prmap->pr_mapname);
- if ((fd = open (name, O_RDONLY)) == -1)
- {
- funcstat = 1;
- break;
- }
- funcstat = (*func) (fd, (CORE_ADDR) prmap->pr_vaddr);
- close (fd);
- }
- }
- return (funcstat);
-}
-#else /* UNIXWARE */
-int
-proc_iterate_over_mappings (func)
- int (*func) PARAMS ((int, CORE_ADDR));
-{
- int nmap;
- int fd;
- int funcstat = 0;
- struct prmap *prmaps;
- struct prmap *prmap;
- struct procinfo *pi;
-
- pi = current_procinfo;
-
- if (ioctl (pi->map_fd, PIOCNMAP, &nmap) == 0)
- {
- prmaps = (struct prmap *) alloca ((nmap + 1) * sizeof (*prmaps));
- if (ioctl (pi->map_fd, PIOCMAP, prmaps) == 0)
- {
- for (prmap = prmaps; prmap -> pr_size && funcstat == 0; ++prmap)
- {
- fd = proc_address_to_fd (pi, (CORE_ADDR) prmap -> pr_vaddr, 0);
- funcstat = (*func) (fd, (CORE_ADDR) prmap -> pr_vaddr);
- close (fd);
- }
- }
- }
- return (funcstat);
-}
-#endif /* UNIXWARE */
-
-#if 0 /* Currently unused */
-/*
-
-GLOBAL FUNCTION
-
- proc_base_address -- find base address for segment containing address
-
-SYNOPSIS
-
- CORE_ADDR proc_base_address (CORE_ADDR addr)
-
-DESCRIPTION
-
- Given an address of a location in the inferior, find and return
- the base address of the mapped segment containing that address.
-
- This is used for example, by the shared library support code,
- where we have the pc value for some location in the shared library
- where we are stopped, and need to know the base address of the
- segment containing that address.
-*/
-
-CORE_ADDR
-proc_base_address (addr)
- CORE_ADDR addr;
-{
- int nmap;
- struct prmap *prmaps;
- struct prmap *prmap;
- CORE_ADDR baseaddr = 0;
- struct procinfo *pi;
-
- pi = current_procinfo;
-
- if (ioctl (pi->map_fd, PIOCNMAP, &nmap) == 0)
- {
- prmaps = (struct prmap *) alloca ((nmap + 1) * sizeof (*prmaps));
- if (ioctl (pi->map_fd, PIOCMAP, prmaps) == 0)
- {
- for (prmap = prmaps; prmap -> pr_size; ++prmap)
- {
- if ((prmap -> pr_vaddr <= (caddr_t) addr) &&
- (prmap -> pr_vaddr + prmap -> pr_size > (caddr_t) addr))
- {
- baseaddr = (CORE_ADDR) prmap -> pr_vaddr;
- break;
- }
- }
- }
- }
- return (baseaddr);
-}
-
-#endif /* 0 */
-
-#ifndef UNIXWARE
-/*
-
-LOCAL FUNCTION
-
- proc_address_to_fd -- return open fd for file mapped to address
-
-SYNOPSIS
-
- int proc_address_to_fd (struct procinfo *pi, CORE_ADDR addr, complain)
-
-DESCRIPTION
-
- Given an address in the current inferior's address space, use the
- /proc interface to find an open file descriptor for the file that
- this address was mapped in from. Return -1 if there is no current
- inferior. Print a warning message if there is an inferior but
- the address corresponds to no file (IE a bogus address).
-
-*/
-
-static int
-proc_address_to_fd (pi, addr, complain)
- struct procinfo *pi;
- CORE_ADDR addr;
- int complain;
-{
- int fd = -1;
-
- if ((fd = ioctl (pi->ctl_fd, PIOCOPENM, (caddr_t *) &addr)) < 0)
- {
- if (complain)
- {
- print_sys_errmsg (pi->pathname, errno);
- warning ("can't find mapped file for address 0x%x", addr);
- }
- }
- return (fd);
-}
-#endif /* !UNIXWARE */
-
-/* Attach to process PID, then initialize for debugging it
- and wait for the trace-trap that results from attaching. */
-
-static void
-procfs_attach (args, from_tty)
- char *args;
- int from_tty;
-{
- char *exec_file;
- int pid;
-
- if (!args)
- error_no_arg ("process-id to attach");
-
- pid = atoi (args);
-
- if (pid == getpid()) /* Trying to masturbate? */
- error ("I refuse to debug myself!");
-
- if (from_tty)
- {
- exec_file = (char *) get_exec_file (0);
-
- if (exec_file)
- printf_unfiltered ("Attaching to program `%s', %s\n", exec_file, target_pid_to_str (pid));
- else
- printf_unfiltered ("Attaching to %s\n", target_pid_to_str (pid));
-
- gdb_flush (gdb_stdout);
- }
-
- inferior_pid = pid = do_attach (pid);
- push_target (&procfs_ops);
-}
-
-
-/* Take a program previously attached to and detaches it.
- The program resumes execution and will no longer stop
- on signals, etc. We'd better not have left any breakpoints
- in the program or it'll die when it hits one. For this
- to work, it may be necessary for the process to have been
- previously attached. It *might* work if the program was
- started via the normal ptrace (PTRACE_TRACEME). */
-
-static void
-procfs_detach (args, from_tty)
- char *args;
- int from_tty;
-{
- int siggnal = 0;
-
- if (from_tty)
- {
- char *exec_file = get_exec_file (0);
- if (exec_file == 0)
- exec_file = "";
- printf_unfiltered ("Detaching from program: %s %s\n",
- exec_file, target_pid_to_str (inferior_pid));
- gdb_flush (gdb_stdout);
- }
- if (args)
- siggnal = atoi (args);
-
- do_detach (siggnal);
- inferior_pid = 0;
- unpush_target (&procfs_ops); /* Pop out of handling an inferior */
-}
-
-/* Get ready to modify the registers array. On machines which store
- individual registers, this doesn't need to do anything. On machines
- which store all the registers in one fell swoop, this makes sure
- that registers contains all the registers from the program being
- debugged. */
-
-static void
-procfs_prepare_to_store ()
-{
-#ifdef CHILD_PREPARE_TO_STORE
- CHILD_PREPARE_TO_STORE ();
-#endif
-}
-
-/* Print status information about what we're accessing. */
-
-static void
-procfs_files_info (ignore)
- struct target_ops *ignore;
-{
- printf_unfiltered ("\tUsing the running image of %s %s via /proc.\n",
- attach_flag? "attached": "child", target_pid_to_str (inferior_pid));
-}
-
-/* ARGSUSED */
-static void
-procfs_open (arg, from_tty)
- char *arg;
- int from_tty;
-{
- error ("Use the \"run\" command to start a Unix child process.");
-}
-
-/*
-
-LOCAL FUNCTION
-
- do_attach -- attach to an already existing process
-
-SYNOPSIS
-
- int do_attach (int pid)
-
-DESCRIPTION
-
- Attach to an already existing process with the specified process
- id. If the process is not already stopped, query whether to
- stop it or not.
-
-NOTES
-
- The option of stopping at attach time is specific to the /proc
- versions of gdb. Versions using ptrace force the attachee
- to stop. (I have changed this version to do so, too. All you
- have to do is "continue" to make it go on. -- gnu@cygnus.com)
-
-*/
-
-static int
-do_attach (pid)
- int pid;
-{
- struct procinfo *pi;
- struct sig_ctl sctl;
- struct flt_ctl fctl;
- int nlwp, *lwps;
-
- pi = init_procinfo (pid, 0);
-
-#ifdef PIOCLWPIDS
- nlwp = pi->prstatus.pr_nlwp;
- lwps = alloca ((2 * nlwp + 2) * sizeof (id_t));
-
- if (ioctl (pi->ctl_fd, PIOCLWPIDS, lwps))
- {
- print_sys_errmsg (pi -> pathname, errno);
- error ("PIOCLWPIDS failed");
- }
-#else /* PIOCLWPIDS */
- nlwp = 1;
- lwps = alloca ((2 * nlwp + 2) * sizeof *lwps);
- lwps[0] = 0;
-#endif
- for (; nlwp > 0; nlwp--, lwps++)
- {
- /* First one has already been created above. */
- if ((pi = find_procinfo ((*lwps << 16) | pid, 1)) == 0)
- pi = init_procinfo ((*lwps << 16) | pid, 0);
-
-#ifdef UNIXWARE
- if (pi->prstatus.pr_lwp.pr_flags & (PR_STOPPED | PR_ISTOP))
-#else
- if (pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP))
-#endif
- {
- pi->was_stopped = 1;
- }
- else
- {
- pi->was_stopped = 0;
- if (1 || query ("Process is currently running, stop it? "))
- {
- long cmd;
- /* Make it run again when we close it. */
- modify_run_on_last_close_flag (pi->ctl_fd, 1);
-#ifdef PROCFS_USE_READ_WRITE
- cmd = PCSTOP;
- if (write (pi->ctl_fd, (char *) &cmd, sizeof (long)) < 0)
-#else
- if (ioctl (pi->ctl_fd, PIOCSTOP, &pi->prstatus) < 0)
-#endif
- {
- print_sys_errmsg (pi->pathname, errno);
- close_proc_file (pi);
- error ("PIOCSTOP failed");
- }
-#ifdef UNIXWARE
- if (!procfs_read_status (pi))
- {
- print_sys_errmsg (pi->pathname, errno);
- close_proc_file (pi);
- error ("procfs_read_status failed");
- }
-#endif
- pi->nopass_next_sigstop = 1;
- }
- else
- {
- printf_unfiltered ("Ok, gdb will wait for %s to stop.\n",
- target_pid_to_str (pi->pid));
- }
- }
-
-#ifdef PROCFS_USE_READ_WRITE
- fctl.cmd = PCSFAULT;
- if (write (pi->ctl_fd, (char *) &fctl, sizeof (struct flt_ctl)) < 0)
- print_sys_errmsg ("PCSFAULT failed", errno);
-#else /* PROCFS_USE_READ_WRITE */
- if (ioctl (pi->ctl_fd, PIOCSFAULT, &pi->prrun.pr_fault))
- {
- print_sys_errmsg ("PIOCSFAULT failed", errno);
- }
- if (ioctl (pi->ctl_fd, PIOCSTRACE, &pi->prrun.pr_trace))
- {
- print_sys_errmsg ("PIOCSTRACE failed", errno);
- }
- add_thread (pi->pid);
- procfs_set_inferior_syscall_traps (pi);
-#endif /* PROCFS_USE_READ_WRITE */
- }
- attach_flag = 1;
- return (pi->pid);
-}
-
-/*
-
-LOCAL FUNCTION
-
- do_detach -- detach from an attached-to process
-
-SYNOPSIS
-
- void do_detach (int signal)
-
-DESCRIPTION
-
- Detach from the current attachee.
-
- If signal is non-zero, the attachee is started running again and sent
- the specified signal.
-
- If signal is zero and the attachee was not already stopped when we
- attached to it, then we make it runnable again when we detach.
-
- Otherwise, we query whether or not to make the attachee runnable
- again, since we may simply want to leave it in the state it was in
- when we attached.
-
- We report any problems, but do not consider them errors, since we
- MUST detach even if some things don't seem to go right. This may not
- be the ideal situation. (FIXME).
- */
-
-static void
-do_detach (signal)
- int signal;
-{
- struct procinfo *pi;
-
- for (pi = procinfo_list; pi; pi = pi->next)
- {
- if (signal)
- {
- set_proc_siginfo (pi, signal);
- }
-#ifdef PROCFS_USE_READ_WRITE
- pi->saved_exitset.cmd = PCSEXIT;
- if (write (pi->ctl_fd, (char *) &pi->saved_exitset,
- sizeof (struct sys_ctl)) < 0)
-#else
- if (ioctl (pi->ctl_fd, PIOCSEXIT, &pi->saved_exitset.sysset) < 0)
-#endif
- {
- print_sys_errmsg (pi->pathname, errno);
- printf_unfiltered ("PIOCSEXIT failed.\n");
- }
-#ifdef PROCFS_USE_READ_WRITE
- pi->saved_entryset.cmd = PCSENTRY;
- if (write (pi->ctl_fd, (char *) &pi->saved_entryset,
- sizeof (struct sys_ctl)) < 0)
-#else
- if (ioctl (pi->ctl_fd, PIOCSENTRY, &pi->saved_entryset.sysset) < 0)
-#endif
- {
- print_sys_errmsg (pi->pathname, errno);
- printf_unfiltered ("PIOCSENTRY failed.\n");
- }
-#ifdef PROCFS_USE_READ_WRITE
- pi->saved_trace.cmd = PCSTRACE;
- if (write (pi->ctl_fd, (char *) &pi->saved_trace,
- sizeof (struct sig_ctl)) < 0)
-#else
- if (ioctl (pi->ctl_fd, PIOCSTRACE, &pi->saved_trace.sigset) < 0)
-#endif
- {
- print_sys_errmsg (pi->pathname, errno);
- printf_unfiltered ("PIOCSTRACE failed.\n");
- }
-#ifndef UNIXWARE
- if (ioctl (pi->ctl_fd, PIOCSHOLD, &pi->saved_sighold.sigset) < 0)
- {
- print_sys_errmsg (pi->pathname, errno);
- printf_unfiltered ("PIOSCHOLD failed.\n");
- }
-#endif
-#ifdef PROCFS_USE_READ_WRITE
- pi->saved_fltset.cmd = PCSFAULT;
- if (write (pi->ctl_fd, (char *) &pi->saved_fltset,
- sizeof (struct flt_ctl)) < 0)
-#else
- if (ioctl (pi->ctl_fd, PIOCSFAULT, &pi->saved_fltset.fltset) < 0)
-#endif
- {
- print_sys_errmsg (pi->pathname, errno);
- printf_unfiltered ("PIOCSFAULT failed.\n");
- }
- if (!procfs_read_status (pi))
- {
- print_sys_errmsg (pi->pathname, errno);
- printf_unfiltered ("procfs_read_status failed.\n");
- }
- else
- {
-#ifdef UNIXWARE
- if (signal || (pi->prstatus.pr_lwp.pr_flags & (PR_STOPPED | PR_ISTOP)))
-#else
- if (signal || (pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP)))
-#endif
- {
- long cmd;
- struct proc_ctl pctl;
-
- 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. */
-#ifdef PROCFS_USE_READ_WRITE
- cmd = PCCFAULT;
- if (write (pi->ctl_fd, (char *) &cmd, sizeof (long)) < 0)
-#else
- if (ioctl (pi->ctl_fd, PIOCCFAULT, 0))
-#endif
- {
- print_sys_errmsg (pi->pathname, errno);
- printf_unfiltered ("PIOCCFAULT failed.\n");
- }
-
- /* Make it run again when we close it. */
-
- modify_run_on_last_close_flag (pi->ctl_fd, 1);
- }
- }
- }
- close_proc_file (pi);
- }
- attach_flag = 0;
-}
-
-/* emulate wait() as much as possible.
- Wait for child to do something. Return pid of child, or -1 in case
- of error; store status in *OURSTATUS.
-
- Not sure why we can't
- just use wait(), but it seems to have problems when applied to a
- process being controlled with the /proc interface.
-
- We have a race problem here with no obvious solution. We need to let
- the inferior run until it stops on an event of interest, which means
- that we need to use the PIOCWSTOP ioctl. However, we cannot use this
- ioctl if the process is already stopped on something that is not an
- event of interest, or the call will hang indefinitely. Thus we first
- use PIOCSTATUS to see if the process is not stopped. If not, then we
- use PIOCWSTOP. But during the window between the two, if the process
- stops for any reason that is not an event of interest (such as a job
- control signal) then gdb will hang. One possible workaround is to set
- an alarm to wake up every minute of so and check to see if the process
- is still running, and if so, then reissue the PIOCWSTOP. But this is
- a real kludge, so has not been implemented. FIXME: investigate
- alternatives.
-
- FIXME: Investigate why wait() seems to have problems with programs
- being control by /proc routines. */
-static int
-procfs_wait (pid, ourstatus)
- int pid;
- struct target_waitstatus *ourstatus;
-{
- short what;
- short why;
- int statval = 0;
- int checkerr = 0;
- int rtnval = -1;
- struct procinfo *pi;
- struct proc_ctl pctl;
-
-scan_again:
-
- /* handle all syscall events first, otherwise we might not
- notice a thread was created until too late. */
-
- for (pi = procinfo_list; pi; pi = pi->next)
- {
- if (!pi->had_event)
- continue;
-
-#ifdef UNIXWARE
- if (! (pi->prstatus.pr_lwp.pr_flags & (PR_STOPPED | PR_ISTOP)) )
- continue;
-
- why = pi->prstatus.pr_lwp.pr_why;
- what = pi->prstatus.pr_lwp.pr_what;
-#else
- if (! (pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP)) )
- continue;
-
- why = pi->prstatus.pr_why;
- what = pi->prstatus.pr_what;
-#endif
- if (why == PR_SYSENTRY || why == PR_SYSEXIT)
- {
- int i;
- int found_handler = 0;
-
- for (i = 0; i < pi->num_syscall_handlers; i++)
- if (pi->syscall_handlers[i].syscall_num == what)
- {
- found_handler = 1;
- pi->saved_rtnval = pi->pid;
- pi->saved_statval = 0;
- if (!pi->syscall_handlers[i].func
- (pi, what, why, &pi->saved_rtnval, &pi->saved_statval))
- pi->had_event = 0;
- break;
- }
-
- if (!found_handler)
- {
- if (why == PR_SYSENTRY)
- error ("PR_SYSENTRY, unhandled system call %d", what);
- else
- error ("PR_SYSEXIT, unhandled system call %d", what);
- }
- }
- }
-
- /* find a relevant process with an event */
-
- for (pi = procinfo_list; pi; pi = pi->next)
- if (pi->had_event && (pid == -1 || pi->pid == pid))
- break;
-
- if (!pi)
- {
- wait_fd ();
- goto scan_again;
- }
-
-#ifdef UNIXWARE
- if (!checkerr && !(pi->prstatus.pr_lwp.pr_flags & (PR_STOPPED | PR_ISTOP)))
-#else
- if (!checkerr && !(pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP)))
-#endif
- {
- if (!procfs_write_pcwstop (pi))
- {
- checkerr++;
- }
- }
- if (checkerr)
- {
- if (errno == ENOENT)
- {
- /* XXX Fixme -- what to do if attached? Can't call wait... */
- rtnval = wait (&statval);
- if ((rtnval) != (PIDGET (inferior_pid)))
- {
- print_sys_errmsg (pi->pathname, errno);
- error ("procfs_wait: wait failed, returned %d", rtnval);
- /* NOTREACHED */
- }
- }
- else
- {
- print_sys_errmsg (pi->pathname, errno);
- error ("PIOCSTATUS or PIOCWSTOP failed.");
- /* NOTREACHED */
- }
- }
-#ifdef UNIXWARE
- else if (pi->prstatus.pr_lwp.pr_flags & (PR_STOPPED | PR_ISTOP))
-#else
- else if (pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP))
-#endif
- {
-#ifdef UNIXWARE
- rtnval = pi->prstatus.pr_pid;
- why = pi->prstatus.pr_lwp.pr_why;
- what = pi->prstatus.pr_lwp.pr_what;
-#else
- rtnval = pi->pid;
- why = pi->prstatus.pr_why;
- what = pi->prstatus.pr_what;
-#endif
-
- switch (why)
- {
- case PR_SIGNALLED:
- statval = (what << 8) | 0177;
- break;
- case PR_SYSENTRY:
- case PR_SYSEXIT:
- rtnval = pi->saved_rtnval;
- statval = pi->saved_statval;
- break;
- case PR_REQUESTED:
- statval = (SIGSTOP << 8) | 0177;
- break;
- case PR_JOBCONTROL:
- statval = (what << 8) | 0177;
- break;
- case PR_FAULTED:
- switch (what)
- {
-#ifdef FLTWATCH
- case FLTWATCH:
- statval = (SIGTRAP << 8) | 0177;
- break;
-#endif
-#ifdef FLTKWATCH
- case FLTKWATCH:
- statval = (SIGTRAP << 8) | 0177;
- break;
-#endif
-#ifndef FAULTED_USE_SIGINFO
- /* Irix, contrary to the documentation, fills in 0 for si_signo.
- Solaris fills in si_signo. I'm not sure about others. */
- case FLTPRIV:
- case FLTILL:
- statval = (SIGILL << 8) | 0177;
- break;
- case FLTBPT:
- case FLTTRACE:
- statval = (SIGTRAP << 8) | 0177;
- break;
- case FLTSTACK:
- case FLTACCESS:
- case FLTBOUNDS:
- statval = (SIGSEGV << 8) | 0177;
- break;
- case FLTIOVF:
- case FLTIZDIV:
- case FLTFPE:
- statval = (SIGFPE << 8) | 0177;
- break;
- case FLTPAGE: /* Recoverable page fault */
-#endif /* not FAULTED_USE_SIGINFO */
- default:
- /* Use the signal which the kernel assigns. This is better than
- trying to second-guess it from the fault. In fact, I suspect
- that FLTACCESS can be either SIGSEGV or SIGBUS. */
-#ifdef UNIXWARE
- statval = ((pi->prstatus.pr_lwp.pr_info.si_signo) << 8) | 0177;
-#else
- statval = ((pi->prstatus.pr_info.si_signo) << 8) | 0177;
-#endif
- break;
- }
- break;
- default:
- error ("PIOCWSTOP, unknown why %d, what %d", why, what);
- }
- /* Stop all the other threads when any of them stops. */
-
- {
- struct procinfo *procinfo, *next_pi;
-
- for (procinfo = procinfo_list; procinfo; procinfo = next_pi)
- {
- next_pi = procinfo->next;
- if (!procinfo->had_event)
- {
-#ifdef PROCFS_USE_READ_WRITE
- long cmd = PCSTOP;
- if (write (pi->ctl_fd, (char *) &cmd, sizeof (long)) < 0)
- {
- print_sys_errmsg (procinfo->pathname, errno);
- error ("PCSTOP failed");
- }
-#else
- /* A bug in Solaris (2.5) causes us to hang when trying to
- stop a stopped process. So, we have to check first in
- order to avoid the hang. */
- if (!procfs_read_status (procinfo))
- {
- /* The LWP has apparently terminated. */
- if (info_verbose)
- printf_filtered ("LWP %d doesn't respond.\n",
- (procinfo->pid >> 16) & 0xffff);
- close_proc_file (procinfo);
- continue;
- }
-
- if (!(procinfo->prstatus.pr_flags & PR_STOPPED))
- if (ioctl (procinfo->ctl_fd, PIOCSTOP, &procinfo->prstatus)
- < 0)
- {
- print_sys_errmsg (procinfo->pathname, errno);
- warning ("PIOCSTOP failed");
- }
-#endif
- }
- }
- }
- }
- else
- {
- error ("PIOCWSTOP, stopped for unknown/unhandled reason, flags %#x",
-#ifdef UNIXWARE
- pi->prstatus.pr_lwp.pr_flags);
-#else
- pi->prstatus.pr_flags);
-#endif
- }
-
- store_waitstatus (ourstatus, statval);
-
- if (rtnval == -1) /* No more children to wait for */
- {
- warning ("Child process unexpectedly missing");
- /* Claim it exited with unknown signal. */
- ourstatus->kind = TARGET_WAITKIND_SIGNALLED;
- ourstatus->value.sig = TARGET_SIGNAL_UNKNOWN;
- return rtnval;
- }
-
- pi->had_event = 0; /* Indicate that we've seen this one */
- return (rtnval);
-}
-
-/*
-
-LOCAL FUNCTION
-
- set_proc_siginfo - set a process's current signal info
-
-SYNOPSIS
-
- void set_proc_siginfo (struct procinfo *pip, int signo);
-
-DESCRIPTION
-
- Given a pointer to a process info struct in PIP and a signal number
- in SIGNO, set the process's current signal and its associated signal
- information. The signal will be delivered to the process immediately
- after execution is resumed, even if it is being held. In addition,
- this particular delivery will not cause another PR_SIGNALLED stop
- even if the signal is being traced.
-
- If we are not delivering the same signal that the prstatus siginfo
- struct contains information about, then synthesize a siginfo struct
- to match the signal we are doing to deliver, make it of the type
- "generated by a user process", and send this synthesized copy. When
- used to set the inferior's signal state, this will be required if we
- are not currently stopped because of a traced signal, or if we decide
- to continue with a different signal.
-
- Note that when continuing the inferior from a stop due to receipt
- of a traced signal, we either have set PRCSIG to clear the existing
- signal, or we have to call this function to do a PIOCSSIG with either
- the existing siginfo struct from pr_info, or one we have synthesized
- appropriately for the signal we want to deliver. Otherwise if the
- signal is still being traced, the inferior will immediately stop
- again.
-
- See siginfo(5) for more details.
-*/
-
-static void
-set_proc_siginfo (pip, signo)
- struct procinfo *pip;
- int signo;
-{
- struct siginfo newsiginfo;
- struct siginfo *sip;
- struct sigi_ctl sictl;
-
-#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. */
-#ifdef UNIXWARE
- if (signo == pip -> prstatus.pr_lwp.pr_cursig)
-#else
- if (signo == pip -> prstatus.pr_cursig)
-#endif
- return;
-#endif
-
-#ifdef UNIXWARE
- if (signo == pip->prstatus.pr_lwp.pr_info.si_signo)
- {
- memcpy ((char *) &sictl.siginfo, (char *) &pip->prstatus.pr_lwp.pr_info,
- sizeof (siginfo_t));
- }
-#else
- if (signo == pip -> prstatus.pr_info.si_signo)
- {
- sip = &pip -> prstatus.pr_info;
- }
-#endif
- else
- {
-#ifdef UNIXWARE
- siginfo_t *sip = &sictl.siginfo;
- memset ((char *) sip, 0, sizeof (siginfo_t));
-#else
- memset ((char *) &newsiginfo, 0, sizeof (newsiginfo));
- sip = &newsiginfo;
-#endif
- sip -> si_signo = signo;
- sip -> si_code = 0;
- sip -> si_errno = 0;
- sip -> si_pid = getpid ();
- sip -> si_uid = getuid ();
- }
-#ifdef PROCFS_USE_READ_WRITE
- sictl.cmd = PCSSIG;
- if (write (pip->ctl_fd, (char *) &sictl, sizeof (struct sigi_ctl)) < 0)
-#else
- if (ioctl (pip->ctl_fd, PIOCSSIG, sip) < 0)
-#endif
- {
- print_sys_errmsg (pip -> pathname, errno);
- warning ("PIOCSSIG failed");
- }
-}
-
-/* Resume execution of process PID. If STEP is nozero, then
- just single step it. If SIGNAL is nonzero, restart it with that
- signal activated. */
-
-static void
-procfs_resume (pid, step, signo)
- int pid;
- int step;
- enum target_signal signo;
-{
- int signal_to_pass;
- struct procinfo *pi, *procinfo, *next_pi;
- struct proc_ctl pctl;
-
- pi = find_procinfo (pid == -1 ? inferior_pid : pid, 0);
-
- errno = 0;
-#ifdef UNIXWARE
- pctl.cmd = PCRUN;
- pctl.data = PRCFAULT;
-#else
- pi->prrun.pr_flags = PRSTRACE | PRSFAULT | PRCFAULT;
-#endif
-
-#if 0
- /* It should not be necessary. If the user explicitly changes the value,
- value_assign calls write_register_bytes, which writes it. */
-/* It may not be absolutely necessary to specify the PC value for
- restarting, but to be safe we use the value that gdb considers
- to be current. One case where this might be necessary is if the
- user explicitly changes the PC value that gdb considers to be
- current. FIXME: Investigate if this is necessary or not. */
-
-#ifdef PRSVADDR_BROKEN
-/* Can't do this under Solaris running on a Sparc, as there seems to be no
- place to put nPC. In fact, if you use this, nPC seems to be set to some
- random garbage. We have to rely on the fact that PC and nPC have been
- written previously via PIOCSREG during a register flush. */
-
- pi->prrun.pr_vaddr = (caddr_t) *(int *) &registers[REGISTER_BYTE (PC_REGNUM)];
- pi->prrun.pr_flags != PRSVADDR;
-#endif
-#endif
-
- if (signo == TARGET_SIGNAL_STOP && pi->nopass_next_sigstop)
- /* When attaching to a child process, if we forced it to stop with
- a PIOCSTOP, then we will have set the nopass_next_sigstop flag.
- Upon resuming the first time after such a stop, we explicitly
- inhibit sending it another SIGSTOP, which would be the normal
- result of default signal handling. One potential drawback to
- this is that we will also ignore any attempt to by the user
- to explicitly continue after the attach with a SIGSTOP. Ultimately
- this problem should be dealt with by making the routines that
- deal with the inferior a little smarter, and possibly even allow
- an inferior to continue running at the same time as gdb. (FIXME?) */
- signal_to_pass = 0;
- else if (signo == TARGET_SIGNAL_TSTP
-#ifdef UNIXWARE
- && pi->prstatus.pr_lwp.pr_cursig == SIGTSTP
- && pi->prstatus.pr_lwp.pr_action.sa_handler == SIG_DFL
-#else
- && pi->prstatus.pr_cursig == SIGTSTP
- && pi->prstatus.pr_action.sa_handler == SIG_DFL
-#endif
- )
-
- /* We are about to pass the inferior a SIGTSTP whose action is
- SIG_DFL. The SIG_DFL action for a SIGTSTP is to stop
- (notifying the parent via wait()), and then keep going from the
- same place when the parent is ready for you to keep going. So
- under the debugger, it should do nothing (as if the program had
- been stopped and then later resumed. Under ptrace, this
- happens for us, but under /proc, the system obligingly stops
- the process, and wait_for_inferior would have no way of
- distinguishing that type of stop (which indicates that we
- should just start it again), with a stop due to the pr_trace
- field of the prrun_t struct.
-
- Note that if the SIGTSTP is being caught, we *do* need to pass it,
- because the handler needs to get executed. */
- signal_to_pass = 0;
- else
- signal_to_pass = target_signal_to_host (signo);
-
- if (signal_to_pass)
- {
- set_proc_siginfo (pi, signal_to_pass);
- }
- else
- {
-#ifdef UNIXWARE
- pctl.data |= PRCSIG;
-#else
- pi->prrun.pr_flags |= PRCSIG;
-#endif
- }
- pi->nopass_next_sigstop = 0;
- if (step)
- {
-#ifdef UNIXWARE
- pctl.data |= PRSTEP;
-#else
- pi->prrun.pr_flags |= PRSTEP;
-#endif
- }
- pi->had_event = 0;
- /* Don't try to start a process unless it's stopped on an
- `event of interest'. Doing so will cause errors. */
-
- if (!procfs_read_status (pi))
- {
- /* The LWP has apparently terminated. */
- if (info_verbose)
- printf_filtered ("LWP %d doesn't respond.\n",
- (pi->pid >> 16) & 0xffff);
- close_proc_file (pi);
- }
- else
- {
-#ifdef PROCFS_USE_READ_WRITE
- if (write (pi->ctl_fd, (char *) &pctl, sizeof (struct proc_ctl)) < 0)
-#else
- if ((pi->prstatus.pr_flags & PR_ISTOP)
- && ioctl (pi->ctl_fd, PIOCRUN, &pi->prrun) != 0)
-#endif
- {
- /* The LWP has apparently terminated. */
- if (info_verbose)
- printf_filtered ("LWP %d doesn't respond.\n",
- (pi->pid >> 16) & 0xffff);
- close_proc_file (pi);
- }
- }
-
- /* Continue all the other threads that haven't had an event of interest.
- Also continue them if they have NOPASS_NEXT_SIGSTOP set; this is only
- set by do_attach, and means this is the first resume after an attach.
- All threads were CSTOP'd by do_attach, and should be resumed now. */
-
- if (pid == -1)
- for (procinfo = procinfo_list; procinfo; procinfo = next_pi)
- {
- next_pi = procinfo->next;
- if (pi != procinfo)
- if (!procinfo->had_event ||
- (procinfo->nopass_next_sigstop && signo == TARGET_SIGNAL_STOP))
- {
- procinfo->had_event = procinfo->nopass_next_sigstop = 0;
-#ifdef PROCFS_USE_READ_WRITE
- pctl.data = PRCFAULT | PRCSIG;
- if (write (procinfo->ctl_fd, (char *) &pctl,
- sizeof (struct proc_ctl)) < 0)
- {
- if (!procfs_read_status (procinfo))
- fprintf_unfiltered(gdb_stderr,
- "procfs_read_status failed, errno=%d\n",
- errno);
- print_sys_errmsg (procinfo->pathname, errno);
- error ("PCRUN failed");
- }
-#else
- procinfo->prrun.pr_flags &= PRSTEP;
- procinfo->prrun.pr_flags |= PRCFAULT | PRCSIG;
- if (!procfs_read_status (procinfo))
- {
- /* The LWP has apparently terminated. */
- if (info_verbose)
- printf_filtered ("LWP %d doesn't respond.\n",
- (procinfo->pid >> 16) & 0xffff);
- close_proc_file (procinfo);
- continue;
- }
-
- /* Don't try to start a process unless it's stopped on an
- `event of interest'. Doing so will cause errors. */
-
- if ((procinfo->prstatus.pr_flags & PR_ISTOP)
- && ioctl (procinfo->ctl_fd, PIOCRUN, &procinfo->prrun) < 0)
- {
- if (!procfs_read_status (procinfo))
- fprintf_unfiltered(gdb_stderr,
- "procfs_read_status failed, errno=%d\n",
- errno);
- print_sys_errmsg (procinfo->pathname, errno);
- warning ("PIOCRUN failed");
- }
-#endif
- }
- procfs_read_status (procinfo);
- }
-}
-
-/*
-
-LOCAL FUNCTION
-
- procfs_fetch_registers -- fetch current registers from inferior
-
-SYNOPSIS
-
- void procfs_fetch_registers (int regno)
-
-DESCRIPTION
-
- Read the current values of the inferior's registers, both the
- general register set and floating point registers (if supported)
- and update gdb's idea of their current values.
-
-*/
-
-static void
-procfs_fetch_registers (regno)
- int regno;
-{
- struct procinfo *pi;
-
- pi = current_procinfo;
-
-#ifdef UNIXWARE
- if (procfs_read_status (pi))
- {
- supply_gregset (&pi->prstatus.pr_lwp.pr_context.uc_mcontext.gregs);
-#if defined (FP0_REGNUM)
- supply_fpregset (&pi->prstatus.pr_lwp.pr_context.uc_mcontext.fpregs);
-#endif
- }
-#else /* UNIXWARE */
- if (ioctl (pi->ctl_fd, PIOCGREG, &pi->gregset.gregset) != -1)
- {
- supply_gregset (&pi->gregset.gregset);
- }
-#if defined (FP0_REGNUM)
- if (ioctl (pi->ctl_fd, PIOCGFPREG, &pi->fpregset.fpregset) != -1)
- {
- supply_fpregset (&pi->fpregset.fpregset);
- }
-#endif
-#endif /* UNIXWARE */
-}
-
-/*
-
-LOCAL FUNCTION
-
- proc_init_failed - called when /proc access initialization fails
-fails
-
-SYNOPSIS
-
- static void proc_init_failed (struct procinfo *pi,
- char *why, int kill_p)
-
-DESCRIPTION
-
- This function is called whenever initialization of access to a /proc
- entry fails. It prints a suitable error message, does some cleanup,
- and then invokes the standard error processing routine which dumps
- us back into the command loop. If KILL_P is true, sends SIGKILL.
- */
-
-static void
-proc_init_failed (pi, why, kill_p)
- struct procinfo *pi;
- char *why;
- int kill_p;
-{
- print_sys_errmsg (pi->pathname, errno);
- if (kill_p)
- kill (pi->pid, SIGKILL);
- close_proc_file (pi);
- error (why);
- /* NOTREACHED */
-}
-
-/*
-
-LOCAL FUNCTION
-
- close_proc_file - close any currently open /proc entry
-
-SYNOPSIS
-
- static void close_proc_file (struct procinfo *pip)
-
-DESCRIPTION
-
- Close any currently open /proc entry and mark the process information
- entry as invalid. In order to ensure that we don't try to reuse any
- stale information, the pid, fd, and pathnames are explicitly
- invalidated, which may be overkill.
-
- */
-
-static void
-close_proc_file (pip)
- struct procinfo *pip;
-{
- struct procinfo *procinfo;
-
- delete_thread (pip->pid); /* remove thread from GDB's thread list */
- remove_fd (pip); /* Remove fd from poll/select list */
-
- close (pip->ctl_fd);
-#ifdef HAVE_MULTIPLE_PROC_FDS
- close (pip->as_fd);
- close (pip->status_fd);
- close (pip->map_fd);
-#endif
-
- free (pip -> pathname);
-
- /* Unlink pip from the procinfo chain. Note pip might not be on the list. */
-
- if (procinfo_list == pip)
- procinfo_list = pip->next;
- else
- {
- for (procinfo = procinfo_list; procinfo; procinfo = procinfo->next)
- {
- if (procinfo->next == pip)
- {
- procinfo->next = pip->next;
- break;
- }
- }
- free (pip);
- }
-}
-
-/*
-
-LOCAL FUNCTION
-
- open_proc_file - open a /proc entry for a given process id
-
-SYNOPSIS
-
- static int open_proc_file (int pid, struct procinfo *pip, int mode)
-
-DESCRIPTION
-
- Given a process id and a mode, close the existing open /proc
- entry (if any) and open one for the new process id, in the
- specified mode. Once it is open, then mark the local process
- information structure as valid, which guarantees that the pid,
- fd, and pathname fields match an open /proc entry. Returns
- zero if the open fails, nonzero otherwise.
-
- Note that the pathname is left intact, even when the open fails,
- so that callers can use it to construct meaningful error messages
- rather than just "file open failed".
-
- Note that for Solaris, the process-id also includes an LWP-id, so we
- actually attempt to open that. If we are handed a pid with a 0 LWP-id,
- then we will ask the kernel what it is and add it to the pid. Hence,
- the pid can be changed by us.
- */
-
-static int
-open_proc_file (pid, pip, mode, control)
- int pid;
- struct procinfo *pip;
- int mode;
- int control;
-{
- int tmp, tmpfd;
-
- pip -> next = NULL;
- pip -> had_event = 0;
- pip -> pathname = xmalloc (MAX_PROC_NAME_SIZE);
- pip -> pid = pid;
-
-#ifndef PIOCOPENLWP
- tmp = pid;
-#else
- tmp = pid & 0xffff;
-#endif
-
-#ifdef HAVE_MULTIPLE_PROC_FDS
- sprintf (pip->pathname, STATUS_PROC_NAME_FMT, tmp);
- if ((pip->status_fd = open (pip->pathname, O_RDONLY)) < 0)
- {
- return 0;
- }
-
- sprintf (pip->pathname, AS_PROC_NAME_FMT, tmp);
- if ((pip->as_fd = open (pip->pathname, O_RDWR)) < 0)
- {
- close (pip->status_fd);
- return 0;
- }
-
- sprintf (pip->pathname, MAP_PROC_NAME_FMT, tmp);
- if ((pip->map_fd = open (pip->pathname, O_RDONLY)) < 0)
- {
- close (pip->status_fd);
- close (pip->as_fd);
- return 0;
- }
-
- sprintf (pip->pathname, MAP_PROC_NAME_FMT, tmp);
- if ((pip->map_fd = open (pip->pathname, O_RDONLY)) < 0)
- {
- close (pip->status_fd);
- close (pip->as_fd);
- return 0;
- }
-
- if (control)
- {
- sprintf (pip->pathname, CTL_PROC_NAME_FMT, tmp);
- if ((pip->ctl_fd = open (pip->pathname, O_WRONLY)) < 0)
- {
- close (pip->status_fd);
- close (pip->as_fd);
- close (pip->map_fd);
- return 0;
- }
- }
-
-#else /* HAVE_MULTIPLE_PROC_FDS */
- sprintf (pip -> pathname, CTL_PROC_NAME_FMT, tmp);
-
- if ((tmpfd = open (pip -> pathname, mode)) < 0)
- return 0;
-
-#ifndef PIOCOPENLWP
- pip -> ctl_fd = tmpfd;
- pip -> as_fd = tmpfd;
- pip -> map_fd = tmpfd;
- pip -> status_fd = tmpfd;
-#else
- tmp = (pid >> 16) & 0xffff; /* Extract thread id */
-
- if (tmp == 0)
- { /* Don't know thread id yet */
- if (ioctl (tmpfd, PIOCSTATUS, &pip -> prstatus) < 0)
- {
- print_sys_errmsg (pip -> pathname, errno);
- close (tmpfd);
- error ("open_proc_file: PIOCSTATUS failed");
- }
-
- tmp = pip -> prstatus.pr_who; /* Get thread id from prstatus_t */
- pip -> pid = (tmp << 16) | pid; /* Update pip */
- }
-
- if ((pip -> ctl_fd = ioctl (tmpfd, PIOCOPENLWP, &tmp)) < 0)
- {
- close (tmpfd);
- return 0;
- }
-
-#ifdef PIOCSET /* New method */
- {
- long pr_flags;
- pr_flags = PR_ASYNC;
- ioctl (pip -> ctl_fd, PIOCSET, &pr_flags);
- }
-#endif
-
- /* keep extra fds in sync */
- pip->as_fd = pip->ctl_fd;
- pip->map_fd = pip->ctl_fd;
- pip->status_fd = pip->ctl_fd;
-
- close (tmpfd); /* All done with main pid */
-#endif /* PIOCOPENLWP */
-
-#endif /* HAVE_MULTIPLE_PROC_FDS */
-
- return 1;
-}
-
-static char *
-mappingflags (flags)
- long flags;
-{
- static char asciiflags[8];
-
- strcpy (asciiflags, "-------");
-#if defined (MA_PHYS)
- if (flags & MA_PHYS) asciiflags[0] = 'd';
-#endif
- if (flags & MA_STACK) asciiflags[1] = 's';
- if (flags & MA_BREAK) asciiflags[2] = 'b';
- if (flags & MA_SHARED) asciiflags[3] = 's';
- if (flags & MA_READ) asciiflags[4] = 'r';
- if (flags & MA_WRITE) asciiflags[5] = 'w';
- if (flags & MA_EXEC) asciiflags[6] = 'x';
- return (asciiflags);
-}
-
-static void
-info_proc_flags (pip, summary)
- struct procinfo *pip;
- int summary;
-{
- struct trans *transp;
-#ifdef UNIXWARE
- long flags = pip->prstatus.pr_flags | pip->prstatus.pr_lwp.pr_flags;
-#else
- long flags = pip->prstatus.pr_flags;
-#endif
-
- printf_filtered ("%-32s", "Process status flags:");
- if (!summary)
- {
- printf_filtered ("\n\n");
- }
- for (transp = pr_flag_table; transp -> name != NULL; transp++)
- {
- if (flags & transp -> value)
- {
- if (summary)
- {
- printf_filtered ("%s ", transp -> name);
- }
- else
- {
- printf_filtered ("\t%-16s %s.\n", transp -> name, transp -> desc);
- }
- }
- }
- printf_filtered ("\n");
-}
-
-static void
-info_proc_stop (pip, summary)
- struct procinfo *pip;
- int summary;
-{
- struct trans *transp;
- int why;
- int what;
-
-#ifdef UNIXWARE
- why = pip -> prstatus.pr_lwp.pr_why;
- what = pip -> prstatus.pr_lwp.pr_what;
-#else
- why = pip -> prstatus.pr_why;
- what = pip -> prstatus.pr_what;
-#endif
-
-#ifdef UNIXWARE
- if (pip -> prstatus.pr_lwp.pr_flags & PR_STOPPED)
-#else
- if (pip -> prstatus.pr_flags & PR_STOPPED)
-#endif
- {
- printf_filtered ("%-32s", "Reason for stopping:");
- if (!summary)
- {
- printf_filtered ("\n\n");
- }
- for (transp = pr_why_table; transp -> name != NULL; transp++)
- {
- if (why == transp -> value)
- {
- if (summary)
- {
- printf_filtered ("%s ", transp -> name);
- }
- else
- {
- printf_filtered ("\t%-16s %s.\n",
- transp -> name, transp -> desc);
- }
- break;
- }
- }
-
- /* Use the pr_why field to determine what the pr_what field means, and
- print more information. */
-
- switch (why)
- {
- case PR_REQUESTED:
- /* pr_what is unused for this case */
- break;
- case PR_JOBCONTROL:
- case PR_SIGNALLED:
- if (summary)
- {
- printf_filtered ("%s ", signalname (what));
- }
- else
- {
- printf_filtered ("\t%-16s %s.\n", signalname (what),
- safe_strsignal (what));
- }
- break;
- case PR_SYSENTRY:
- if (summary)
- {
- printf_filtered ("%s ", syscallname (what));
- }
- else
- {
- printf_filtered ("\t%-16s %s.\n", syscallname (what),
- "Entered this system call");
- }
- break;
- case PR_SYSEXIT:
- if (summary)
- {
- printf_filtered ("%s ", syscallname (what));
- }
- else
- {
- printf_filtered ("\t%-16s %s.\n", syscallname (what),
- "Returned from this system call");
- }
- break;
- case PR_FAULTED:
- if (summary)
- {
- printf_filtered ("%s ",
- lookupname (faults_table, what, "fault"));
- }
- else
- {
- printf_filtered ("\t%-16s %s.\n",
- lookupname (faults_table, what, "fault"),
- lookupdesc (faults_table, what));
- }
- break;
- }
- printf_filtered ("\n");
- }
-}
-
-static void
-info_proc_siginfo (pip, summary)
- struct procinfo *pip;
- int summary;
-{
- struct siginfo *sip;
-
-#ifdef UNIXWARE
- if ((pip -> prstatus.pr_lwp.pr_flags & PR_STOPPED) &&
- (pip -> prstatus.pr_lwp.pr_why == PR_SIGNALLED ||
- pip -> prstatus.pr_lwp.pr_why == PR_FAULTED))
-#else
- if ((pip -> prstatus.pr_flags & PR_STOPPED) &&
- (pip -> prstatus.pr_why == PR_SIGNALLED ||
- pip -> prstatus.pr_why == PR_FAULTED))
-#endif
- {
- printf_filtered ("%-32s", "Additional signal/fault info:");
-#ifdef UNIXWARE
- sip = &pip -> prstatus.pr_lwp.pr_info;
-#else
- sip = &pip -> prstatus.pr_info;
-#endif
- if (summary)
- {
- printf_filtered ("%s ", signalname (sip -> si_signo));
- if (sip -> si_errno > 0)
- {
- printf_filtered ("%s ", errnoname (sip -> si_errno));
- }
- if (sip -> si_code <= 0)
- {
- printf_filtered ("sent by %s, uid %d ",
- target_pid_to_str (sip -> si_pid),
- sip -> si_uid);
- }
- else
- {
- printf_filtered ("%s ", sigcodename (sip));
- if ((sip -> si_signo == SIGILL) ||
- (sip -> si_signo == SIGFPE) ||
- (sip -> si_signo == SIGSEGV) ||
- (sip -> si_signo == SIGBUS))
- {
- printf_filtered ("addr=%#lx ",
- (unsigned long) sip -> si_addr);
- }
- else if ((sip -> si_signo == SIGCHLD))
- {
- printf_filtered ("child %s, status %u ",
- target_pid_to_str (sip -> si_pid),
- sip -> si_status);
- }
- else if ((sip -> si_signo == SIGPOLL))
- {
- printf_filtered ("band %u ", sip -> si_band);
- }
- }
- }
- else
- {
- printf_filtered ("\n\n");
- printf_filtered ("\t%-16s %s.\n", signalname (sip -> si_signo),
- safe_strsignal (sip -> si_signo));
- if (sip -> si_errno > 0)
- {
- printf_filtered ("\t%-16s %s.\n",
- errnoname (sip -> si_errno),
- safe_strerror (sip -> si_errno));
- }
- if (sip -> si_code <= 0)
- {
- printf_filtered ("\t%-16u %s\n", sip -> si_pid, /* XXX need target_pid_to_str() */
- "PID of process sending signal");
- printf_filtered ("\t%-16u %s\n", sip -> si_uid,
- "UID of process sending signal");
- }
- else
- {
- printf_filtered ("\t%-16s %s.\n", sigcodename (sip),
- sigcodedesc (sip));
- if ((sip -> si_signo == SIGILL) ||
- (sip -> si_signo == SIGFPE))
- {
- 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%#-16lx %s.\n",
- (unsigned long) sip -> si_addr,
- "Address of faulting memory reference");
- }
- else if ((sip -> si_signo == SIGCHLD))
- {
- printf_filtered ("\t%-16u %s.\n", sip -> si_pid, /* XXX need target_pid_to_str() */
- "Child process ID");
- printf_filtered ("\t%-16u %s.\n", sip -> si_status,
- "Child process exit value or signal");
- }
- else if ((sip -> si_signo == SIGPOLL))
- {
- printf_filtered ("\t%-16u %s.\n", sip -> si_band,
- "Band event for POLL_{IN,OUT,MSG}");
- }
- }
- }
- printf_filtered ("\n");
- }
-}
-
-static void
-info_proc_syscalls (pip, summary)
- struct procinfo *pip;
- int summary;
-{
- int syscallnum;
-
- if (!summary)
- {
-
-#if 0 /* FIXME: Needs to use gdb-wide configured info about system calls. */
- if (pip -> prstatus.pr_flags & PR_ASLEEP)
- {
- int syscallnum = pip -> prstatus.pr_reg[R_D0];
- if (summary)
- {
- printf_filtered ("%-32s", "Sleeping in system call:");
- printf_filtered ("%s", syscallname (syscallnum));
- }
- else
- {
- printf_filtered ("Sleeping in system call '%s'.\n",
- syscallname (syscallnum));
- }
- }
-#endif
-
-#ifndef UNIXWARE
- if (ioctl (pip -> ctl_fd, PIOCGENTRY, &pip -> entryset) < 0)
- {
- print_sys_errmsg (pip -> pathname, errno);
- error ("PIOCGENTRY failed");
- }
-
- if (ioctl (pip -> ctl_fd, PIOCGEXIT, &pip -> exitset) < 0)
- {
- print_sys_errmsg (pip -> pathname, errno);
- error ("PIOCGEXIT failed");
- }
-#endif
-
- printf_filtered ("System call tracing information:\n\n");
-
- printf_filtered ("\t%-12s %-8s %-8s\n",
- "System call",
- "Entry",
- "Exit");
- for (syscallnum = 0; syscallnum < MAX_SYSCALLS; syscallnum++)
- {
- QUIT;
- if (syscall_table[syscallnum] != NULL)
- printf_filtered ("\t%-12s ", syscall_table[syscallnum]);
- else
- printf_filtered ("\t%-12d ", syscallnum);
-
-#ifdef UNIXWARE
- printf_filtered ("%-8s ",
- prismember (&pip->prstatus.pr_sysentry, syscallnum)
- ? "on" : "off");
- printf_filtered ("%-8s ",
- prismember (&pip->prstatus.pr_sysexit, syscallnum)
- ? "on" : "off");
-#else
- printf_filtered ("%-8s ",
- prismember (&pip -> entryset, syscallnum)
- ? "on" : "off");
- printf_filtered ("%-8s ",
- prismember (&pip -> exitset, syscallnum)
- ? "on" : "off");
-#endif
- printf_filtered ("\n");
- }
- printf_filtered ("\n");
- }
-}
-
-static char *
-signalname (signo)
- int signo;
-{
- const char *name;
- static char locbuf[32];
-
- name = strsigno (signo);
- if (name == NULL)
- {
- sprintf (locbuf, "Signal %d", signo);
- }
- else
- {
- sprintf (locbuf, "%s (%d)", name, signo);
- }
- return (locbuf);
-}
-
-static char *
-errnoname (errnum)
- int errnum;
-{
- const char *name;
- static char locbuf[32];
-
- name = strerrno (errnum);
- if (name == NULL)
- {
- sprintf (locbuf, "Errno %d", errnum);
- }
- else
- {
- sprintf (locbuf, "%s (%d)", name, errnum);
- }
- return (locbuf);
-}
-
-static void
-info_proc_signals (pip, summary)
- struct procinfo *pip;
- int summary;
-{
- int signo;
-
- if (!summary)
- {
-#ifndef PROCFS_USE_READ_WRITE
- if (ioctl (pip -> ctl_fd, PIOCGTRACE, &pip -> trace) < 0)
- {
- print_sys_errmsg (pip -> pathname, errno);
- error ("PIOCGTRACE failed");
- }
-#endif
-
- printf_filtered ("Disposition of signals:\n\n");
- printf_filtered ("\t%-15s %-8s %-8s %-8s %s\n\n",
- "Signal", "Trace", "Hold", "Pending", "Description");
- for (signo = 0; signo < NSIG; signo++)
- {
- QUIT;
- printf_filtered ("\t%-15s ", signalname (signo));
-#ifdef UNIXWARE
- printf_filtered ("%-8s ",
- prismember (&pip -> prstatus.pr_sigtrace, signo)
- ? "on" : "off");
- printf_filtered ("%-8s ",
- prismember (&pip -> prstatus.pr_lwp.pr_context.uc_sigmask, signo)
- ? "on" : "off");
-#else
- printf_filtered ("%-8s ",
- prismember (&pip -> trace, signo)
- ? "on" : "off");
- printf_filtered ("%-8s ",
- prismember (&pip -> prstatus.pr_sighold, signo)
- ? "on" : "off");
-#endif
-
-#ifdef UNIXWARE
- if (prismember (&pip->prstatus.pr_sigpend, signo) ||
- prismember (&pip->prstatus.pr_lwp.pr_lwppend, signo))
- printf_filtered("%-8s ", "yes");
- else
- printf_filtered("%-8s ", "no");
-#else /* UNIXWARE */
-#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
-#endif /* UNIXWARE */
- printf_filtered (" %s\n", safe_strsignal (signo));
- }
- printf_filtered ("\n");
- }
-}
-
-static void
-info_proc_faults (pip, summary)
- struct procinfo *pip;
- int summary;
-{
- struct trans *transp;
-
- if (!summary)
- {
-#ifndef UNIXWARE
- if (ioctl (pip -> ctl_fd, PIOCGFAULT, &pip->fltset.fltset) < 0)
- {
- print_sys_errmsg (pip -> pathname, errno);
- error ("PIOCGFAULT failed");
- }
-#endif
-
- printf_filtered ("Current traced hardware fault set:\n\n");
- printf_filtered ("\t%-12s %-8s\n", "Fault", "Trace");
-
- for (transp = faults_table; transp -> name != NULL; transp++)
- {
- QUIT;
- printf_filtered ("\t%-12s ", transp -> name);
-#ifdef UNIXWARE
- printf_filtered ("%-8s", prismember (&pip->prstatus.pr_flttrace, transp -> value)
- ? "on" : "off");
-#else
- printf_filtered ("%-8s", prismember (&pip->fltset.fltset, transp -> value)
- ? "on" : "off");
-#endif
- printf_filtered ("\n");
- }
- printf_filtered ("\n");
- }
-}
-
-static void
-info_proc_mappings (pip, summary)
- struct procinfo *pip;
- int summary;
-{
- int nmap;
- struct prmap *prmaps;
- struct prmap *prmap;
- struct stat sbuf;
-
- 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",
- " Offset",
- "Flags");
-#ifdef PROCFS_USE_READ_WRITE
- if (fstat (pip->map_fd, &sbuf) == 0)
- {
- nmap = sbuf.st_size / sizeof (prmap_t);
- prmaps = (struct prmap *) alloca ((nmap + 1) * sizeof (*prmaps));
- if ((lseek (pip->map_fd, 0, SEEK_SET) == 0) &&
- (read (pip->map_fd, (char *) prmaps,
- nmap * sizeof (*prmaps)) == (nmap * sizeof (*prmaps))))
- {
- int i = 0;
- for (prmap = prmaps; i < nmap; ++prmap, ++i)
-#else
- if (ioctl (pip -> ctl_fd, PIOCNMAP, &nmap) == 0)
- {
- prmaps = (struct prmap *) alloca ((nmap + 1) * sizeof (*prmaps));
- if (ioctl (pip -> ctl_fd, PIOCMAP, prmaps) == 0)
- {
- for (prmap = prmaps; prmap -> pr_size; ++prmap)
-#endif /* PROCFS_USE_READ_WRITE */
- {
-#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));
- }
- }
- }
- printf_filtered ("\n");
- }
-}
-
-/*
-
-LOCAL FUNCTION
-
- info_proc -- implement the "info proc" command
-
-SYNOPSIS
-
- void info_proc (char *args, int from_tty)
-
-DESCRIPTION
-
- Implement gdb's "info proc" command by using the /proc interface
- to print status information about any currently running process.
-
- Examples of the use of "info proc" are:
-
- info proc (prints summary info for current inferior)
- info proc 123 (prints summary info for process with pid 123)
- info proc mappings (prints address mappings)
- info proc times (prints process/children times)
- info proc id (prints pid, ppid, gid, sid, etc)
- FIXME: i proc id not implemented.
- info proc status (prints general process state info)
- FIXME: i proc status not implemented.
- info proc signals (prints info about signal handling)
- info proc all (prints all info)
-
- */
-
-static void
-info_proc (args, from_tty)
- char *args;
- int from_tty;
-{
- int pid;
- struct procinfo *pip;
- struct cleanup *old_chain;
- char **argv;
- int argsize;
- int summary = 1;
- int flags = 0;
- int syscalls = 0;
- int signals = 0;
- int faults = 0;
- int mappings = 0;
- int times = 0;
- int id = 0;
- int status = 0;
- int all = 0;
- int nlwp;
- int *lwps;
-
- old_chain = make_cleanup (null_cleanup, 0);
-
- /* Default to using the current inferior if no pid specified. Note
- that inferior_pid may be 0, hence we set okerr. */
-
- pid = inferior_pid & 0x7fffffff; /* strip off sol-thread bit */
- if (!(pip = find_procinfo (pid, 1))) /* inferior_pid no good? */
- pip = procinfo_list; /* take first available */
- pid = pid & 0xffff; /* extract "real" pid */
-
- if (args != NULL)
- {
- if ((argv = buildargv (args)) == NULL)
- {
- nomem (0);
- }
- make_cleanup (freeargv, (char *) argv);
-
- while (*argv != NULL)
- {
- argsize = strlen (*argv);
- if (argsize >= 1 && strncmp (*argv, "all", argsize) == 0)
- {
- summary = 0;
- all = 1;
- }
- else if (argsize >= 2 && strncmp (*argv, "faults", argsize) == 0)
- {
- summary = 0;
- faults = 1;
- }
- else if (argsize >= 2 && strncmp (*argv, "flags", argsize) == 0)
- {
- summary = 0;
- flags = 1;
- }
- else if (argsize >= 1 && strncmp (*argv, "id", argsize) == 0)
- {
- summary = 0;
- id = 1;
- }
- else if (argsize >= 1 && strncmp (*argv, "mappings", argsize) == 0)
- {
- summary = 0;
- mappings = 1;
- }
- else if (argsize >= 2 && strncmp (*argv, "signals", argsize) == 0)
- {
- summary = 0;
- signals = 1;
- }
- else if (argsize >= 2 && strncmp (*argv, "status", argsize) == 0)
- {
- summary = 0;
- status = 1;
- }
- else if (argsize >= 2 && strncmp (*argv, "syscalls", argsize) == 0)
- {
- summary = 0;
- syscalls = 1;
- }
- else if (argsize >= 1 && strncmp (*argv, "times", argsize) == 0)
- {
- summary = 0;
- times = 1;
- }
- else if ((pid = atoi (*argv)) > 0)
- {
- pip = (struct procinfo *) xmalloc (sizeof (struct procinfo));
- memset (pip, 0, sizeof (*pip));
-
- pip->pid = pid;
- if (!open_proc_file (pid, pip, O_RDONLY, 0))
- {
- perror_with_name (pip -> pathname);
- /* NOTREACHED */
- }
- pid = pip->pid;
- make_cleanup (close_proc_file, pip);
- }
- else if (**argv != '\000')
- {
- error ("Unrecognized or ambiguous keyword `%s'.", *argv);
- }
- argv++;
- }
- }
-
- /* If we don't have a valid open process at this point, then we have no
- inferior or didn't specify a specific pid. */
-
- if (!pip)
- {
- error ("\
-No process. Start debugging a program or specify an explicit process ID.");
- }
-
- if (!procfs_read_status (pip))
- {
- print_sys_errmsg (pip -> pathname, errno);
- error ("procfs_read_status failed");
- }
-
-#ifndef PROCFS_USE_READ_WRITE
-#ifdef PIOCLWPIDS
- nlwp = pip->prstatus.pr_nlwp;
- lwps = alloca ((2 * nlwp + 2) * sizeof (*lwps));
-
- if (ioctl (pip->ctl_fd, PIOCLWPIDS, lwps))
- {
- print_sys_errmsg (pip -> pathname, errno);
- error ("PIOCLWPIDS failed");
- }
-#else /* PIOCLWPIDS */
- nlwp = 1;
- lwps = alloca ((2 * nlwp + 2) * sizeof *lwps);
- lwps[0] = 0;
-#endif /* PIOCLWPIDS */
-
- for (; nlwp > 0; nlwp--, lwps++)
- {
- pip = find_procinfo ((*lwps << 16) | pid, 1);
-
- if (!pip)
- {
- pip = (struct procinfo *) xmalloc (sizeof (struct procinfo));
- memset (pip, 0, sizeof (*pip));
- if (!open_proc_file ((*lwps << 16) | pid, pip, O_RDONLY, 0))
- continue;
-
- make_cleanup (close_proc_file, pip);
-
- if (!procfs_read_status (pip))
- {
- print_sys_errmsg (pip -> pathname, errno);
- error ("procfs_read_status failed");
- }
- }
-
-#endif /* PROCFS_USE_READ_WRITE */
-
- /* Print verbose information of the requested type(s), or just a summary
- of the information for all types. */
-
- printf_filtered ("\nInformation for %s.%d:\n\n", pip -> pathname, *lwps);
- if (summary || all || flags)
- {
- info_proc_flags (pip, summary);
- }
- if (summary || all)
- {
- info_proc_stop (pip, summary);
-#ifdef UNIXWARE
- supply_gregset (&pip->prstatus.pr_lwp.pr_context.uc_mcontext.gregs);
-#else
- supply_gregset (&pip->prstatus.pr_reg);
-#endif
- printf_filtered ("PC: ");
- print_address (read_pc (), gdb_stdout);
- printf_filtered ("\n");
- }
- if (summary || all || signals || faults)
- {
- info_proc_siginfo (pip, summary);
- }
- if (summary || all || syscalls)
- {
- info_proc_syscalls (pip, summary);
- }
- if (summary || all || mappings)
- {
- info_proc_mappings (pip, summary);
- }
- if (summary || all || signals)
- {
- info_proc_signals (pip, summary);
- }
- if (summary || all || faults)
- {
- info_proc_faults (pip, summary);
- }
- printf_filtered ("\n");
-
- /* All done, deal with closing any temporary process info structure,
- freeing temporary memory , etc. */
-
- do_cleanups (old_chain);
-#ifndef PROCFS_USE_READ_WRITE
- }
-#endif
-}
-
-/*
-
-LOCAL FUNCTION
-
- modify_inherit_on_fork_flag - Change the inherit-on-fork flag
-
-SYNOPSIS
-
- void modify_inherit_on_fork_flag (fd, flag)
-
-DESCRIPTION
-
- Call this routine to modify the inherit-on-fork flag. This routine is
- just a nice wrapper to hide the #ifdefs needed by various systems to
- control this flag.
-
- */
-
-static void
-modify_inherit_on_fork_flag (fd, flag)
- int fd;
- int flag;
-{
-#if defined (PIOCSET) || defined (PCSET)
- long pr_flags;
-#endif
- int retval = 0;
- struct proc_ctl pctl;
-
-#if defined (PIOCSET) || defined (PCSET) /* New method */
- pr_flags = PR_FORK;
- if (flag)
- {
-#ifdef PROCFS_USE_READ_WRITE
- pctl.cmd = PCSET;
- pctl.data = PR_FORK;
- if (write (fd, (char *) &pctl, sizeof (struct proc_ctl)) < 0)
- retval = -1;
-#else
- retval = ioctl (fd, PIOCSET, &pr_flags);
-#endif
- }
- else
- {
-#ifdef PROCFS_USE_READ_WRITE
- pctl.cmd = PCRESET;
- pctl.data = PR_FORK;
- if (write (fd, (char *) &pctl, sizeof (struct proc_ctl)) < 0)
- retval = -1;
-#else
- retval = ioctl (fd, PIOCRESET, &pr_flags);
-#endif
- }
-
-#else
-#ifdef PIOCSFORK /* Original method */
- if (flag)
- {
- retval = ioctl (fd, PIOCSFORK, NULL);
- }
- else
- {
- retval = ioctl (fd, PIOCRFORK, NULL);
- }
-#else
- Neither PR_FORK nor PIOCSFORK exist!!!
-#endif
-#endif
-
- if (!retval)
- return;
-
- print_sys_errmsg ("modify_inherit_on_fork_flag", errno);
- error ("PIOCSFORK or PR_FORK modification failed");
-}
-
-/*
-
-LOCAL FUNCTION
-
- modify_run_on_last_close_flag - Change the run-on-last-close flag
-
-SYNOPSIS
-
- void modify_run_on_last_close_flag (fd, flag)
-
-DESCRIPTION
-
- Call this routine to modify the run-on-last-close flag. This routine
- is just a nice wrapper to hide the #ifdefs needed by various systems to
- control this flag.
-
- */
-
-static void
-modify_run_on_last_close_flag (fd, flag)
- int fd;
- int flag;
-{
-#if defined (PIOCSET) || defined (PCSET)
- long pr_flags;
-#endif
- int retval = 0;
- struct proc_ctl pctl;
-
-#if defined (PIOCSET) || defined (PCSET) /* New method */
- pr_flags = PR_RLC;
- if (flag)
- {
-#ifdef PROCFS_USE_READ_WRITE
- pctl.cmd = PCSET;
- pctl.data = PR_RLC;
- if (write (fd, (char *) &pctl, sizeof (struct proc_ctl)) < 0)
- retval = -1;
-#else
- retval = ioctl (fd, PIOCSET, &pr_flags);
-#endif
- }
- else
- {
-#ifdef PROCFS_USE_READ_WRITE
- pctl.cmd = PCRESET;
- pctl.data = PR_RLC;
- if (write (fd, (char *) &pctl, sizeof (struct proc_ctl)) < 0)
- retval = -1;
-#else
- retval = ioctl (fd, PIOCRESET, &pr_flags);
-#endif
- }
-
-#else
-#ifdef PIOCSRLC /* Original method */
- if (flag)
- retval = ioctl (fd, PIOCSRLC, NULL);
- else
- retval = ioctl (fd, PIOCRRLC, NULL);
-#else
- Neither PR_RLC nor PIOCSRLC exist!!!
-#endif
-#endif
-
- if (!retval)
- return;
-
- print_sys_errmsg ("modify_run_on_last_close_flag", errno);
- error ("PIOCSRLC or PR_RLC modification failed");
-}
-
-/*
-
-LOCAL FUNCTION
-
- procfs_clear_syscall_trap -- Deletes the trap for the specified system call.
-
-SYNOPSIS
-
- void procfs_clear_syscall_trap (struct procinfo *, int syscall_num, int errok)
-
-DESCRIPTION
-
- This function function disables traps for the specified system call.
- errok is non-zero if errors should be ignored.
- */
-
-static void
-procfs_clear_syscall_trap (pi, syscall_num, errok)
- struct procinfo *pi;
- int syscall_num;
- int errok;
-{
- sysset_t sysset;
- int goterr, i;
-
-#ifndef UNIXWARE
- goterr = ioctl (pi->ctl_fd, PIOCGENTRY, &sysset) < 0;
-
- if (goterr && !errok)
- {
- print_sys_errmsg (pi->pathname, errno);
- error ("PIOCGENTRY failed");
- }
-
- if (!goterr)
- {
- prdelset (&sysset, syscall_num);
-
- if ((ioctl (pi->ctl_fd, PIOCSENTRY, &sysset) < 0) && !errok)
- {
- print_sys_errmsg (pi->pathname, errno);
- error ("PIOCSENTRY failed");
- }
- }
-
- goterr = ioctl (pi->ctl_fd, PIOCGEXIT, &sysset) < 0;
-
- if (goterr && !errok)
- {
- procfs_clear_syscall_trap (pi, syscall_num, 1);
- print_sys_errmsg (pi->pathname, errno);
- error ("PIOCGEXIT failed");
- }
-
- if (!goterr)
- {
- praddset (&sysset, syscall_num);
-
- if ((ioctl (pi->ctl_fd, PIOCSEXIT, &sysset) < 0) && !errok)
- {
- procfs_clear_syscall_trap (pi, syscall_num, 1);
- print_sys_errmsg (pi->pathname, errno);
- error ("PIOCSEXIT failed");
- }
- }
-#endif
-
- if (!pi->syscall_handlers)
- {
- if (!errok)
- error ("procfs_clear_syscall_trap: syscall_handlers is empty");
- return;
- }
-
- /* Remove handler func from the handler list */
-
- for (i = 0; i < pi->num_syscall_handlers; i++)
- if (pi->syscall_handlers[i].syscall_num == syscall_num)
- {
- if (i + 1 != pi->num_syscall_handlers)
- { /* Not the last entry.
- Move subsequent entries fwd. */
- memcpy (&pi->syscall_handlers[i], &pi->syscall_handlers[i + 1],
- (pi->num_syscall_handlers - i - 1)
- * sizeof (struct procfs_syscall_handler));
- }
-
- pi->syscall_handlers = xrealloc (pi->syscall_handlers,
- (pi->num_syscall_handlers - 1)
- * sizeof (struct procfs_syscall_handler));
- pi->num_syscall_handlers--;
- return;
- }
-
- if (!errok)
- error ("procfs_clear_syscall_trap: Couldn't find handler for sys call %d",
- syscall_num);
-}
-
-/*
-
-LOCAL FUNCTION
-
- procfs_set_syscall_trap -- arrange for a function to be called when the
- child executes the specified system call.
-
-SYNOPSIS
-
- void procfs_set_syscall_trap (struct procinfo *, int syscall_num, int flags,
- syscall_func_t *function)
-
-DESCRIPTION
-
- This function sets up an entry and/or exit trap for the specified system
- call. When the child executes the specified system call, your function
- will be called with the call #, a flag that indicates entry or exit, and
- pointers to rtnval and statval (which are used by procfs_wait). The
- function should return non-zero if something interesting happened, zero
- otherwise.
- */
-
-static void
-procfs_set_syscall_trap (pi, syscall_num, flags, func)
- struct procinfo *pi;
- int syscall_num;
- int flags;
- syscall_func_t *func;
-{
- sysset_t sysset;
-
-#ifndef UNIXWARE
- if (flags & PROCFS_SYSCALL_ENTRY)
- {
- if (ioctl (pi->ctl_fd, PIOCGENTRY, &sysset) < 0)
- {
- print_sys_errmsg (pi->pathname, errno);
- error ("PIOCGENTRY failed");
- }
-
- praddset (&sysset, syscall_num);
-
- if (ioctl (pi->ctl_fd, PIOCSENTRY, &sysset) < 0)
- {
- print_sys_errmsg (pi->pathname, errno);
- error ("PIOCSENTRY failed");
- }
- }
-
- if (flags & PROCFS_SYSCALL_EXIT)
- {
- if (ioctl (pi->ctl_fd, PIOCGEXIT, &sysset) < 0)
- {
- procfs_clear_syscall_trap (pi, syscall_num, 1);
- print_sys_errmsg (pi->pathname, errno);
- error ("PIOCGEXIT failed");
- }
-
- praddset (&sysset, syscall_num);
-
- if (ioctl (pi->ctl_fd, PIOCSEXIT, &sysset) < 0)
- {
- procfs_clear_syscall_trap (pi, syscall_num, 1);
- print_sys_errmsg (pi->pathname, errno);
- error ("PIOCSEXIT failed");
- }
- }
-#endif
-
- if (!pi->syscall_handlers)
- {
- pi->syscall_handlers = xmalloc (sizeof (struct procfs_syscall_handler));
- pi->syscall_handlers[0].syscall_num = syscall_num;
- pi->syscall_handlers[0].func = func;
- pi->num_syscall_handlers = 1;
- }
- else
- {
- int i;
-
- for (i = 0; i < pi->num_syscall_handlers; i++)
- if (pi->syscall_handlers[i].syscall_num == syscall_num)
- {
- pi->syscall_handlers[i].func = func;
- return;
- }
-
- pi->syscall_handlers = xrealloc (pi->syscall_handlers, (i + 1)
- * sizeof (struct procfs_syscall_handler));
- pi->syscall_handlers[i].syscall_num = syscall_num;
- pi->syscall_handlers[i].func = func;
- pi->num_syscall_handlers++;
- }
-}
-
-#ifdef SYS_lwp_create
-
-/*
-
-LOCAL FUNCTION
-
- procfs_lwp_creation_handler - handle exit from the _lwp_create syscall
-
-SYNOPSIS
-
- int procfs_lwp_creation_handler (pi, syscall_num, why, rtnvalp, statvalp)
-
-DESCRIPTION
-
- This routine is called both when an inferior process and it's new lwp
- are about to finish a _lwp_create() system call. This is the system
- call that Solaris uses to create a lightweight process. When the
- target process gets this event, we can look at sysarg[2] to find the
- new childs lwp ID, and create a procinfo struct from that. After that,
- we pretend that we got a SIGTRAP, and return non-zero to tell
- procfs_wait to wake up. Subsequently, wait_for_inferior gets woken up,
- sees the new process and continues it.
-
- When we see the child exiting from lwp_create, we just contine it,
- since everything was handled when the parent trapped.
-
-NOTES
- In effect, we are only paying attention to the parent's completion of
- the lwp_create syscall. If we only paid attention to the child
- instead, then we wouldn't detect the creation of a suspended thread.
- */
-
-static int
-procfs_lwp_creation_handler (pi, syscall_num, why, rtnvalp, statvalp)
- struct procinfo *pi;
- int syscall_num;
- int why;
- int *rtnvalp;
- int *statvalp;
-{
- int lwp_id;
- struct procinfo *childpi;
- struct proc_ctl pctl;
-
- /* We've just detected the completion of an lwp_create system call. Now we
- need to setup a procinfo struct for this thread, and notify the thread
- system of the new arrival. */
-
- /* If lwp_create failed, then nothing interesting happened. Continue the
- process and go back to sleep. */
-
-#ifdef UNIXWARE
- /* Joel ... can you check this logic out please? JKJ */
- if (pi->prstatus.pr_lwp.pr_context.uc_mcontext.gregs[R_EFL] & 1)
- { /* _lwp_create failed */
- pctl.cmd = PCRUN;
- pctl.data = PRCFAULT;
-
- if (write (pi->ctl_fd, (char *) &pctl, sizeof (struct proc_ctl)) < 0)
- perror_with_name (pi->pathname);
-
- return 0;
- }
-#else /* UNIXWARE */
- if (PROCFS_GET_CARRY (pi->prstatus.pr_reg))
- { /* _lwp_create failed */
- pi->prrun.pr_flags &= PRSTEP;
- pi->prrun.pr_flags |= PRCFAULT;
-
- if (ioctl (pi->ctl_fd, PIOCRUN, &pi->prrun) != 0)
- perror_with_name (pi->pathname);
-
- return 0;
- }
-#endif
-
- /* At this point, the new thread is stopped at it's first instruction, and
- the parent is stopped at the exit from lwp_create. */
-
- if (pi->new_child) /* Child? */
- { /* Yes, just continue it */
-#ifdef UNIXWARE
- pctl.cmd = PCRUN;
- pctl.data = PRCFAULT;
-
- if (write(pi->ctl_fd, (char *)&pctl, sizeof (struct proc_ctl)) < 0)
-#else /* !UNIXWARE */
- pi->prrun.pr_flags &= PRSTEP;
- pi->prrun.pr_flags |= PRCFAULT;
-
- if ((pi->prstatus.pr_flags & PR_ISTOP)
- && ioctl (pi->ctl_fd, PIOCRUN, &pi->prrun) != 0)
-#endif /* !UNIXWARE */
- perror_with_name (pi->pathname);
-
- pi->new_child = 0; /* No longer new */
-
- return 0;
- }
-
- /* We're the proud parent of a new thread. Setup an exit trap for lwp_create
- in the child and continue the parent. */
-
- /* Third arg is pointer to new thread id. */
-#ifdef UNIXWARE
- lwp_id = read_memory_integer (pi->prstatus.pr_lwp.pr_sysarg[2], sizeof (int));
-#else
- lwp_id = read_memory_integer (pi->prstatus.pr_sysarg[2], sizeof (int));
-#endif
-
- lwp_id = (lwp_id << 16) | PIDGET (pi->pid);
-
- childpi = create_procinfo (lwp_id);
-
- /* The new process has actually inherited the lwp_create syscall trap from
- it's parent, but we still have to call this to register handlers for
- that child. */
-
- procfs_set_inferior_syscall_traps (childpi);
- add_thread (lwp_id);
- printf_filtered ("[New %s]\n", target_pid_to_str (lwp_id));
-
- /* Continue the parent */
-#ifdef UNIXWARE
- pctl.cmd = PCRUN;
- pctl.data = PRCFAULT;
-
- if (write(pi->ctl_fd, (char *)&pctl, sizeof (struct proc_ctl)) < 0)
-#else
- pi->prrun.pr_flags &= PRSTEP;
- pi->prrun.pr_flags |= PRCFAULT;
- if (ioctl (pi->ctl_fd, PIOCRUN, &pi->prrun) != 0)
-#endif
- perror_with_name (pi->pathname);
-
- /* The new child may have been created in one of two states:
- SUSPENDED or RUNNABLE. If runnable, we will simply signal it to run.
- If suspended, we flag it to be continued later, when it has an event. */
-
-#ifdef UNIXWARE
- if (childpi->prstatus.pr_lwp.pr_why == PR_SUSPENDED)
-#else
- if (childpi->prstatus.pr_why == PR_SUSPENDED)
-#endif
- childpi->new_child = 1; /* Flag this as an unseen child process */
- else
- {
- /* Continue the child */
-#ifdef UNIXWARE
- pctl.cmd = PCRUN;
- pctl.data = PRCFAULT;
-
- if (write(pi->ctl_fd, (char *)&pctl, sizeof (struct proc_ctl)) < 0)
-#else
- childpi->prrun.pr_flags &= PRSTEP;
- childpi->prrun.pr_flags |= PRCFAULT;
-
- if (ioctl (childpi->ctl_fd, PIOCRUN, &childpi->prrun) != 0)
-#endif
- perror_with_name (childpi->pathname);
- }
- return 0;
-}
-#endif /* SYS_lwp_create */
-
-/* Fork an inferior process, and start debugging it with /proc. */
-
-static void
-procfs_create_inferior (exec_file, allargs, env)
- char *exec_file;
- char *allargs;
- char **env;
-{
- char *shell_file = getenv ("SHELL");
- char *tryname;
- if (shell_file != NULL && strchr (shell_file, '/') == NULL)
- {
-
- /* We will be looking down the PATH to find shell_file. If we
- just do this the normal way (via execlp, which operates by
- attempting an exec for each element of the PATH until it
- finds one which succeeds), then there will be an exec for
- each failed attempt, each of which will cause a PR_SYSEXIT
- stop, and we won't know how to distinguish the PR_SYSEXIT's
- for these failed execs with the ones for successful execs
- (whether the exec has succeeded is stored at that time in the
- carry bit or some such architecture-specific and
- non-ABI-specified place).
-
- So I can't think of anything better than to search the PATH
- now. This has several disadvantages: (1) There is a race
- condition; if we find a file now and it is deleted before we
- exec it, we lose, even if the deletion leaves a valid file
- further down in the PATH, (2) there is no way to know exactly
- what an executable (in the sense of "capable of being
- exec'd") file is. Using access() loses because it may lose
- if the caller is the superuser; failing to use it loses if
- there are ACLs or some such. */
-
- char *p;
- char *p1;
- /* FIXME-maybe: might want "set path" command so user can change what
- path is used from within GDB. */
- char *path = getenv ("PATH");
- int len;
- struct stat statbuf;
-
- if (path == NULL)
- path = "/bin:/usr/bin";
-
- tryname = alloca (strlen (path) + strlen (shell_file) + 2);
- for (p = path; p != NULL; p = p1 ? p1 + 1: NULL)
- {
- p1 = strchr (p, ':');
- if (p1 != NULL)
- len = p1 - p;
- else
- len = strlen (p);
- strncpy (tryname, p, len);
- tryname[len] = '\0';
- strcat (tryname, "/");
- strcat (tryname, shell_file);
- if (access (tryname, X_OK) < 0)
- continue;
- if (stat (tryname, &statbuf) < 0)
- continue;
- if (!S_ISREG (statbuf.st_mode))
- /* We certainly need to reject directories. I'm not quite
- as sure about FIFOs, sockets, etc., but I kind of doubt
- that people want to exec() these things. */
- continue;
- break;
- }
- if (p == NULL)
- /* Not found. This must be an error rather than merely passing
- the file to execlp(), because execlp() would try all the
- exec()s, causing GDB to get confused. */
- error ("Can't find shell %s in PATH", shell_file);
-
- shell_file = tryname;
- }
-
- fork_inferior (exec_file, allargs, env,
- proc_set_exec_trap, procfs_init_inferior, NULL, shell_file);
-
- /* We are at the first instruction we care about. */
- /* Pedal to the metal... */
-
- proceed ((CORE_ADDR) -1, TARGET_SIGNAL_0, 0);
-}
-
-/* Clean up after the inferior dies. */
-
-static void
-procfs_mourn_inferior ()
-{
- struct procinfo *pi;
- struct procinfo *next_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 ()
-{
- /* This variable is controlled by modules that sit atop procfs that may layer
- their own process structure atop that provided here. sol-thread.c does
- this because of the Solaris two-level thread model. */
-
- return !procfs_suppress_run;
-}
-#ifdef TARGET_HAS_HARDWARE_WATCHPOINTS
-#ifndef UNIXWARE
-
-/* Insert a watchpoint */
-int
-procfs_set_watchpoint(pid, addr, len, rw)
- int pid;
- CORE_ADDR addr;
- int len;
- int rw;
-{
- struct procinfo *pi;
- prwatch_t wpt;
-
- pi = find_procinfo (pid == -1 ? inferior_pid : pid, 0);
- wpt.pr_vaddr = (caddr_t)addr;
- wpt.pr_size = len;
- wpt.pr_wflags = ((rw & 1) ? MA_READ : 0) | ((rw & 2) ? MA_WRITE : 0);
- if (ioctl (pi->ctl_fd, PIOCSWATCH, &wpt) < 0)
- {
- if (errno == E2BIG)
- return -1;
- /* Currently it sometimes happens that the same watchpoint gets
- deleted twice - don't die in this case (FIXME please) */
- if (errno == ESRCH && len == 0)
- return 0;
- print_sys_errmsg (pi->pathname, errno);
- error ("PIOCSWATCH failed");
- }
- return 0;
-}
-
-int
-procfs_stopped_by_watchpoint(pid)
- int pid;
-{
- struct procinfo *pi;
- short what;
- short why;
-
- pi = find_procinfo (pid == -1 ? inferior_pid : pid, 0);
- if (pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP))
- {
- why = pi->prstatus.pr_why;
- what = pi->prstatus.pr_what;
- if (why == PR_FAULTED
-#if defined (FLTWATCH) && defined (FLTKWATCH)
- && (what == FLTWATCH || what == FLTKWATCH)
-#else
-#ifdef FLTWATCH
- && (what == FLTWATCH)
-#endif
-#ifdef FLTKWATCH
- && (what == FLTKWATCH)
-#endif
-#endif
- )
- return what;
- }
- return 0;
-}
-#endif /* !UNIXWARE */
-#endif /* TARGET_HAS_HARDWARE_WATCHPOINTS */
-
-/* Why is this necessary? Shouldn't dead threads just be removed from the
- thread database? */
-
-static int
-procfs_thread_alive (pid)
- int pid;
-{
- struct procinfo *pi, *next_pi;
-
- for (pi = procinfo_list; pi; pi = next_pi)
- {
- next_pi = pi->next;
- if (pi -> pid == pid)
- if (procfs_read_status (pi)) /* alive */
- return 1;
- else /* defunct (exited) */
- {
- close_proc_file (pi);
- return 0;
- }
- }
- return 0;
-}
-
-int
-procfs_first_available ()
-{
- struct procinfo *pi;
-
- for (pi = procinfo_list; pi; pi = pi->next)
- {
- if (procfs_read_status (pi))
- return pi->pid;
- }
- return -1;
-}
-
-int
-procfs_get_pid_fd (pid)
- int pid;
-{
- struct procinfo *pi = find_procinfo (pid, 1);
-
- if (pi == NULL)
- return -1;
-
- return pi->ctl_fd;
-}
-
-/* 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). */
-
-static void
-procfs_stop ()
-{
- extern pid_t inferior_process_group;
-
- kill (-inferior_process_group, SIGINT);
-}
-
-/* Convert a pid to printable form. */
-
-#ifdef TIDGET
-char *
-procfs_pid_to_str (pid)
- int pid;
-{
- static char buf[100];
-
- sprintf (buf, "Kernel thread %d", TIDGET (pid));
-
- return buf;
-}
-#endif /* TIDGET */
-
-
-static void
-init_procfs_ops ()
-{
- procfs_ops.to_shortname = "procfs";
- procfs_ops.to_longname = "Unix /proc child process";
- procfs_ops.to_doc = "Unix /proc child process (started by the \"run\" command).";
- procfs_ops.to_open = procfs_open;
- procfs_ops.to_attach = procfs_attach;
- procfs_ops.to_detach = procfs_detach;
- procfs_ops.to_resume = procfs_resume;
- procfs_ops.to_wait = procfs_wait;
- procfs_ops.to_fetch_registers = procfs_fetch_registers;
- procfs_ops.to_store_registers = procfs_store_registers;
- procfs_ops.to_prepare_to_store = procfs_prepare_to_store;
- procfs_ops.to_xfer_memory = procfs_xfer_memory;
- procfs_ops.to_files_info = procfs_files_info;
- procfs_ops.to_insert_breakpoint = memory_insert_breakpoint;
- procfs_ops.to_remove_breakpoint = memory_remove_breakpoint;
- procfs_ops.to_terminal_init = terminal_init_inferior;
- procfs_ops.to_terminal_inferior = terminal_inferior;
- procfs_ops.to_terminal_ours_for_output = terminal_ours_for_output;
- procfs_ops.to_terminal_ours = terminal_ours;
- procfs_ops.to_terminal_info = child_terminal_info;
- procfs_ops.to_kill = procfs_kill_inferior;
- procfs_ops.to_create_inferior = procfs_create_inferior;
- procfs_ops.to_mourn_inferior = procfs_mourn_inferior;
- procfs_ops.to_can_run = procfs_can_run;
- procfs_ops.to_notice_signals = procfs_notice_signals;
- procfs_ops.to_thread_alive = procfs_thread_alive;
- procfs_ops.to_stop = procfs_stop;
- procfs_ops.to_stratum = process_stratum;
- procfs_ops.to_has_all_memory = 1;
- procfs_ops.to_has_memory = 1;
- procfs_ops.to_has_stack = 1;
- procfs_ops.to_has_registers = 1;
- procfs_ops.to_has_execution = 1;
- procfs_ops.to_magic = OPS_MAGIC;
-}
-
-void
-_initialize_procfs ()
-{
-#ifdef HAVE_OPTIONAL_PROC_FS
- char procname[MAX_PROC_NAME_SIZE];
- int fd;
-
- /* If we have an optional /proc filesystem (e.g. under OSF/1),
- don't add procfs support if we cannot access the running
- GDB via /proc. */
- sprintf (procname, STATUS_PROC_NAME_FMT, getpid ());
- if ((fd = open (procname, O_RDONLY)) < 0)
- return;
- close (fd);
-#endif
-
- init_procfs_ops ();
- add_target (&procfs_ops);
-
- add_info ("processes", info_proc,
-"Show process status information using /proc entry.\n\
-Specify process id or use current inferior by default.\n\
-Specify keywords for detailed information; default is summary.\n\
-Keywords are: `all', `faults', `flags', `id', `mappings', `signals',\n\
-`status', `syscalls', and `times'.\n\
-Unambiguous abbreviations may be used.");
-
- init_syscall_table ();
-}