static void procfs_kill_inferior PARAMS ((void));
pi = (procinfo *) xmalloc (sizeof (procinfo)); memset (pi, 0, sizeof (procinfo)); pi->pid = pid; pi->tid = tid;
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));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 *)) 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 struct procinfo *find_procinfo PARAMS ((pid_t pid, int okfail));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_sprocstatic syscall_func_t procfs_sproc_handler;static syscall_func_t procfs_fork_handler;#endif#ifdef SYS_lwp_createstatic syscall_func_t procfs_lwp_creation_handler;#endifstatic 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));/* External function prototypes that can't be easily included in any   header file because the args are typedefs in system include files. */extern void supply_gregset PARAMS ((gregset_t *));extern void fill_gregset PARAMS ((gregset_t *, int));extern void supply_fpregset PARAMS ((fpregset_t *));extern void fill_fpregset PARAMS ((fpregset_t *, int));/*LOCAL FUNCTION	find_procinfo -- convert a process id to a struct procinfoSYNOPSIS	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 procinfoSYNOPSIS	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 listSYNOPSIS	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 voidadd_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->fd;  poll_list[num_poll_list].events = POLLPRI;  num_poll_list++;}static voidremove_fd (pi)     struct procinfo *pi;{  int i;  for (i = 0; i < num_poll_list; i++)    {      if (poll_list[i].fd == pi->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;	}    }}static struct procinfo *wait_fd (){  struct procinfo *pi;#ifndef LOSING_POLL  int num_fds;  int i;#endif  set_sigint_trap ();	/* Causes SIGINT to be passed on to the			   attached process. */  set_sigio_trap ();#ifndef LOSING_POLL  num_fds = poll (poll_list, num_poll_list, -1);#else  pi = current_procinfo;  while (ioctl (pi->fd, PIOCWSTOP, &pi->prstatus) < 0)    {      if (errno == ENOENT)	{	  /* Process exited.  */	  pi->prstatus.pr_flags = 0;	  break;	}      else if (errno != EINTR)	{	  print_sys_errmsg (pi->pathname, errno);	  error ("PIOCWSTOP failed");	}    }  pi->had_event = 1;#endif      clear_sigint_trap ();  clear_sigio_trap ();#ifndef LOSING_POLL  if (num_fds <= 0)    {      print_sys_errmsg ("poll failed\n", errno);      error ("Poll failed, returned %d", num_fds);    }  for (i = 0; i < num_poll_list && num_fds > 0; i++)    {      if ((poll_list[i].revents & (POLLPRI|POLLERR|POLLHUP|POLLNVAL)) == 0)	continue;      for (pi = procinfo_list; pi; pi = pi->next)	{	  if (poll_list[i].fd == pi->fd)	    {	      if (ioctl (pi->fd, PIOCSTATUS, &pi->prstatus) < 0)		{		  print_sys_errmsg (pi->pathname, errno);		  error ("PIOCSTATUS failed");		}	      num_fds--;	      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 stringSYNOPSIS	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 nameSYNOPSIS	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 nameSYNOPSIS	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 tableSYNOPSIS	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 voidinit_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_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}/*LOCAL FUNCTION	procfs_kill_inferior - kill any currently inferiorSYNOPSIS	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 voidprocfs_kill_inferior (){  target_mourn_inferior ();}/*LOCAL FUNCTION	unconditionally_kill_inferior - terminate the inferiorSYNOPSIS	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 voidunconditionally_kill_inferior (pi)     struct procinfo *pi;{  int signo;  int ppid;    ppid = pi->prstatus.pr_ppid;  signo = SIGKILL;#ifdef PROCFS_NEED_CLEAR_CURSIG_FOR_KILL  /* Alpha OSF/1-3.x procfs needs a clear of the current signal     before the PIOCKILL, otherwise it might generate a corrupted core     file for the inferior.  */  ioctl (pi->fd, PIOCSSIG, NULL);#endif#ifdef PROCFS_NEED_PIOCSSIG_FOR_KILL  /* Alpha OSF/1-2.x procfs needs a PIOCSSIG call with a SIGKILL signal     to kill the inferior, otherwise it might remain stopped with a     pending SIGKILL.     We do not check the result of the PIOCSSIG, the inferior might have     died already.  */  {    struct siginfo newsiginfo;    memset ((char *) &newsiginfo, 0, sizeof (newsiginfo));    newsiginfo.si_signo = signo;    newsiginfo.si_code = 0;    newsiginfo.si_errno = 0;    newsiginfo.si_pid = getpid ();    newsiginfo.si_uid = getuid ();    ioctl (pi->fd, PIOCSSIG, &newsiginfo);  }#else  ioctl (pi->fd, PIOCKILL, &signo);#endif  close_proc_file (pi);/* Only wait() for our direct children.  Our grandchildren zombies are killed   by the death of their parents.  */  if (ppid == getpid())    wait ((int *) 0);}/*LOCAL FUNCTION	procfs_xfer_memory -- copy data to or from inferior memory spaceSYNOPSIS	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 intprocfs_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->fd, (off_t) memaddr, 0) == (off_t) memaddr)    {      if (dowrite)	{	  nbytes = write (pi->fd, myaddr, len);	}      else	{	  nbytes = read (pi->fd, myaddr, len);	}      if (nbytes < 0)	{	  nbytes = 0;	}    }  return (nbytes);}/*LOCAL FUNCTION	procfs_store_registers -- copy register values back to inferiorSYNOPSIS	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 voidprocfs_store_registers (regno)     int regno;{  struct procinfo *pi;  pi = current_procinfo;  if (regno != -1)    {      ioctl (pi->fd, PIOCGREG, &pi->gregset);    }  fill_gregset (&pi->gregset, regno);  ioctl (pi->fd, PIOCSREG, &pi->gregset);#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. */  if (regno != -1)    {      ioctl (pi->fd, PIOCGFPREG, &pi->fpregset);    }  fill_fpregset (&pi->fpregset, regno);  ioctl (pi->fd, PIOCSFPREG, &pi->fpregset);#endif	/* FP0_REGNUM */}/*LOCAL FUNCTION	create_procinfo - initialize access to a /proc entrySYNOPSIS	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;  pi = find_procinfo (pid, 1);  if (pi != NULL)    return pi;			/* All done!  It already exists */  pi = (struct procinfo *) xmalloc (sizeof (struct procinfo));  if (!open_proc_file (pid, pi, O_RDWR))    proc_init_failed (pi, "can't open process file");  /* 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 */  pi->num_syscall_handlers = 0;  pi->syscall_handlers = NULL;  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  if (ioctl (pi->fd, PIOCSTATUS, &pi->prstatus) < 0)    proc_init_failed (pi, "PIOCSTATUS failed");/* 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))    if (ioctl (pi->fd, PIOCWSTOP, &pi->prstatus) < 0)      proc_init_failed (pi, "PIOCWSTOP failed");  if (ioctl (pi->fd, PIOCSFAULT, &pi->prrun.pr_fault) < 0)    proc_init_failed (pi, "PIOCSFAULT failed");  return pi;}