pi->ignore_next_sigstop = 0;
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;}/*LOCAL FUNCTION	procfs_exit_handler - handle entry into the _exit syscallSYNOPSIS	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 intprocfs_exit_handler (pi, syscall_num, why, rtnvalp, statvalp)     struct procinfo *pi;     int syscall_num;     int why;     int *rtnvalp;     int *statvalp;{  pi->prrun.pr_flags = PRCFAULT;  if (ioctl (pi->fd, PIOCRUN, &pi->prrun) != 0)    perror_with_name (pi->pathname);  *rtnvalp = wait (statvalp);  if (*rtnvalp >= 0)    *rtnvalp = pi->pid;  return 1;}/*LOCAL FUNCTION	procfs_exec_handler - handle exit from the exec family of syscallsSYNOPSIS	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 intprocfs_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;}#ifdef SYS_sproc		/* IRIX lwp creation system call *//*LOCAL FUNCTION	procfs_sproc_handler - handle exit from the sproc syscallSYNOPSIS	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 intprocfs_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->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 syscallSYNOPSIS	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 intprocfs_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->fd, PIOCRUN, &pi->prrun) != 0)    perror_with_name (pi->pathname);  return 0;}#endif /* SYS_sproc *//*LOCAL FUNCTION	procfs_init_inferior - initialize target vector and access to a	/proc entrySYNOPSIS	int 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 intprocfs_init_inferior (pid)     int pid;{  struct procinfo *pip;  push_target (&procfs_ops);  pip = create_procinfo (pid);#ifndef PIOCSSPCACT  procfs_set_syscall_trap (pip, SYS_exit, PROCFS_SYSCALL_ENTRY,			   procfs_exit_handler);#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  /* PIOCSSPCACT */  /* 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->fd, 1);#endif#ifdef SYS_lwp_create  procfs_set_syscall_trap (pip, SYS_lwp_create, PROCFS_SYSCALL_EXIT,			   procfs_lwp_creation_handler);#endif  /* 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  return pid;}/*GLOBAL FUNCTION	procfs_notice_signalsSYNOPSIS	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 voidprocfs_notice_signals (pid)     int pid;{  int signo;  struct procinfo *pi;  pi = find_procinfo (pid, 0);  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 (&pi->prrun.pr_trace, signo);	}      else	{	  praddset (&pi->prrun.pr_trace, signo);	}    }  if (ioctl (pi->fd, PIOCSTRACE, &pi->prrun.pr_trace))    {      print_sys_errmsg ("PIOCSTRACE failed", errno);    }}/*LOCAL FUNCTION	proc_set_exec_trap -- arrange for exec'd child to halt at startupSYNOPSIS	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 voidproc_set_exec_trap (){  sysset_t exitset;  sysset_t entryset;  auto char procname[32];  int fd;    sprintf (procname, PROC_NAME_FMT, getpid ());  if ((fd = open (procname, O_RDWR)) < 0)    {      perror (procname);      gdb_flush (gdb_stderr);      _exit (127);    }  premptyset (&exitset);  premptyset (&entryset);#ifdef PIOCSSPCACT  /* Under Alpha OSF/1 we have to use a PIOCSSPCACT ioctl to trace     exits from exec system calls because of the user level loader.     Starting with OSF/1-4.0, tracing the entry to the exit system     call no longer works. So we have to use PRFS_STOPTERM to trace     termination of the inferior.  */  {    int prfs_flags;    if (ioctl (fd, PIOCGSPCACT, &prfs_flags) < 0)      {	perror (procname);	gdb_flush (gdb_stderr);	_exit (127);      }    prfs_flags |= PRFS_STOPEXEC | PRFS_STOPTERM;    if (ioctl (fd, PIOCSSPCACT, &prfs_flags) < 0)      {	perror (procname);	gdb_flush (gdb_stderr);	_exit (127);      }  }#else /* PIOCSSPCACT */  /* 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, SYS_exec);#endif#ifdef SYS_execve  praddset (&exitset, SYS_execve);#endif#ifdef SYS_execv  praddset (&exitset, SYS_execv);#endif  if (ioctl (fd, PIOCSEXIT, &exitset) < 0)    {      perror (procname);      gdb_flush (gdb_stderr);      _exit (127);    }  praddset (&entryset, SYS_exit);  if (ioctl (fd, PIOCSENTRY, &entryset) < 0)    {      perror (procname);      gdb_flush (gdb_stderr);      _exit (126);    }#endif /* PIOCSSPCACT */  /* 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);#ifdef PR_ASYNC  {    long pr_flags;/* 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;    ioctl (fd, PIOCSET, &pr_flags);  }#endif	/* PR_ASYNC */}/*GLOBAL FUNCTION	proc_iterate_over_mappings -- call function for every mapped spaceSYNOPSIS	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. */intproc_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->fd, PIOCNMAP, &nmap) == 0)    {      prmaps = (struct prmap *) alloca ((nmap + 1) * sizeof (*prmaps));      if (ioctl (pi->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);}#if 0	/* Currently unused *//*GLOBAL FUNCTION	proc_base_address -- find base address for segment containing addressSYNOPSIS	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_ADDRproc_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->fd, PIOCNMAP, &nmap) == 0)    {      prmaps = (struct prmap *) alloca ((nmap + 1) * sizeof (*prmaps));      if (ioctl (pi->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 *//*LOCAL FUNCTION	proc_address_to_fd -- return open fd for file mapped to addressSYNOPSIS	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 intproc_address_to_fd (pi, addr, complain)     struct procinfo *pi;     CORE_ADDR addr;     int complain;{  int fd = -1;  if ((fd = ioctl (pi->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);}/* Attach to process PID, then initialize for debugging it   and wait for the trace-trap that results from attaching.  */static voidprocfs_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 voidprocfs_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 voidprocfs_prepare_to_store (){#ifdef CHILD_PREPARE_TO_STORE  CHILD_PREPARE_TO_STORE ();#endif}/* Print status information about what we're accessing.  */static voidprocfs_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 voidprocfs_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 processSYNOPSIS	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 intdo_attach (pid)     int pid;{  struct procinfo *pi;  pi = (struct procinfo *) xmalloc (sizeof (struct procinfo));  if (!open_proc_file (pid, pi, O_RDWR))    {      free (pi);      perror_with_name (pi->pathname);      /* NOTREACHED */    }    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 */  /*  Get current status of process and if it is not already stopped,      then stop it.  Remember whether or not it was stopped when we first      examined it. */    if (ioctl (pi->fd, PIOCSTATUS, &pi->prstatus) < 0)    {      print_sys_errmsg (pi->pathname, errno);      close_proc_file (pi);      error ("PIOCSTATUS failed");    }  if (pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP))    {      pi->was_stopped = 1;    }  else    {      pi->was_stopped = 0;      if (1 || query ("Process is currently running, stop it? "))	{	  /* Make it run again when we close it.  */	  modify_run_on_last_close_flag (pi->fd, 1);	  if (ioctl (pi->fd, PIOCSTOP, &pi->prstatus) < 0)	    {	      print_sys_errmsg (pi->pathname, errno);	      close_proc_file (pi);	      error ("PIOCSTOP failed");	    }	  pi->nopass_next_sigstop = 1;	}      else	{	  printf_unfiltered ("Ok, gdb will wait for %s to stop.\n", target_pid_to_str (pid));	}    }  /*  Remember some things about the inferior that we will, or might, change      so that we can restore them when we detach. */    ioctl (pi->fd, PIOCGTRACE, &pi->saved_trace);  ioctl (pi->fd, PIOCGHOLD, &pi->saved_sighold);  ioctl (pi->fd, PIOCGFAULT, &pi->saved_fltset);  ioctl (pi->fd, PIOCGENTRY, &pi->saved_entryset);  ioctl (pi->fd, PIOCGEXIT, &pi->saved_exitset);    /* Set up trace and fault sets, as gdb expects them. */    memset (&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, PIOCSFAULT, &pi->prrun.pr_fault))    {      print_sys_errmsg ("PIOCSFAULT failed", errno);    }  if (ioctl (pi->fd, PIOCSTRACE, &pi->prrun.pr_trace))    {      print_sys_errmsg ("PIOCSTRACE failed", errno);    }  attach_flag = 1;  return (pid);}/*LOCAL FUNCTION	do_detach -- detach from an attached-to processSYNOPSIS	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 voiddo_detach (signal)     int signal;{  struct procinfo *pi;  pi = current_procinfo;  if (signal)    {      set_proc_siginfo (pi, signal);    }  if (ioctl (pi->fd, PIOCSEXIT, &pi->saved_exitset) < 0)    {      print_sys_errmsg (pi->pathname, errno);      printf_unfiltered ("PIOCSEXIT failed.\n");    }  if (ioctl (pi->fd, PIOCSENTRY, &pi->saved_entryset) < 0)    {      print_sys_errmsg (pi->pathname, errno);      printf_unfiltered ("PIOCSENTRY failed.\n");    }  if (ioctl (pi->fd, PIOCSTRACE, &pi->saved_trace) < 0)    {      print_sys_errmsg (pi->pathname, errno);      printf_unfiltered ("PIOCSTRACE failed.\n");    }  if (ioctl (pi->fd, PIOCSHOLD, &pi->saved_sighold) < 0)    {      print_sys_errmsg (pi->pathname, errno);      printf_unfiltered ("PIOSCHOLD failed.\n");    }  if (ioctl (pi->fd, PIOCSFAULT, &pi->saved_fltset) < 0)    {      print_sys_errmsg (pi->pathname, errno);      printf_unfiltered ("PIOCSFAULT failed.\n");    }  if (ioctl (pi->fd, PIOCSTATUS, &pi->prstatus) < 0)    {      print_sys_errmsg (pi->pathname, errno);      printf_unfiltered ("PIOCSTATUS failed.\n");    }  else    {      if (signal || (pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP)))	{	  if (signal || !pi->was_stopped ||	      query ("Was stopped when attached, make it runnable again? "))	    {	      /* Clear any pending signal if we want to detach without		 a signal.  */	      if (signal == 0)		set_proc_siginfo (pi, signal);	      /* Clear any fault that might have stopped it.  */	      if (ioctl (pi->fd, PIOCCFAULT, 0))		{		  print_sys_errmsg (pi->pathname, errno);		  printf_unfiltered ("PIOCCFAULT failed.\n");		}	      /* Make it run again when we close it.  */	      modify_run_on_last_close_flag (pi->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 intprocfs_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;  if (pid != -1)		/* Non-specific process? */    pi = NULL;  else    for (pi = procinfo_list; pi; pi = pi->next)      if (pi->had_event)	break;  if (!pi)    {    wait_again:      if (pi)	pi->had_event = 0;      pi = wait_fd ();    }  if (pid != -1)    for (pi = procinfo_list; pi; pi = pi->next)      if (pi->pid == pid && pi->had_event)	break;  if (!pi && !checkerr)    goto wait_again;  if (!checkerr && !(pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP)))    {      if (ioctl (pi->fd, PIOCWSTOP, &pi->prstatus) < 0)	{	  checkerr++;	}    }      if (checkerr)    {      if (errno == ENOENT)	{	  rtnval = wait (&statval);	  if (rtnval != inferior_pid)	    {	      print_sys_errmsg (pi->pathname, errno);	      error ("PIOCWSTOP, wait failed, returned %d", rtnval);	      /* NOTREACHED */	    }	}      else	{	  print_sys_errmsg (pi->pathname, errno);	  error ("PIOCSTATUS or PIOCWSTOP failed.");	  /* NOTREACHED */	}    }  else if (pi->prstatus.pr_flags & (PR_STOPPED | PR_ISTOP))    {      rtnval = pi->pid;      why = pi->prstatus.pr_why;      what = pi->prstatus.pr_what;      switch (why)	{	case PR_SIGNALLED:	  statval = (what << 8) | 0177;	  break;	case PR_SYSENTRY:	case 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;		  if (!pi->syscall_handlers[i].func (pi, what, why,						     &rtnval, &statval))		    goto wait_again;		  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);	  }	  break;#ifdef PR_DEAD	case (short)PR_DEAD:	  {	    int dummy;	    /* The inferior process is about to terminate.	       pr_what has the process's exit or return value.	       A PIOCRUN ioctl must be used to restart the process so it	       can finish exiting.  */	    pi->prrun.pr_flags = PRCFAULT;	    if (ioctl (pi->fd, PIOCRUN, &pi->prrun) != 0)	      perror_with_name (pi->pathname);	    if (wait (&dummy) < 0)	      rtnval = -1;	    statval = pi->prstatus.pr_what;	  }	  break;#endif	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.  */	      statval = ((pi->prstatus.pr_info.si_signo) << 8) | 0177;	      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;	for (procinfo = procinfo_list; procinfo; procinfo = procinfo->next)	  {	    if (!procinfo->had_event)	      {		/* 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 (ioctl (procinfo->fd, PIOCSTATUS, &procinfo->prstatus) < 0)		  {		    print_sys_errmsg (procinfo->pathname, errno);		    error ("PIOCSTATUS failed");		  }		if (!(procinfo->prstatus.pr_flags & PR_STOPPED))		  if (ioctl (procinfo->fd, PIOCSTOP, &procinfo->prstatus) < 0)		    {		      print_sys_errmsg (procinfo->pathname, errno);		      error ("PIOCSTOP failed");		    }	      }	  }      }    }  else    {      error ("PIOCWSTOP, stopped for unknown/unhandled reason, flags %#x", 	     pi->prstatus.pr_flags);    }  store_waitstatus (ourstatus, statval);  if (rtnval == -1)		/* No more children to wait for */    {      fprintf_unfiltered (gdb_stderr, "Child process unexpectedly missing.\n");      /* 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 infoSYNOPSIS	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 voidset_proc_siginfo (pip, signo)     struct procinfo *pip;     int signo;{  struct siginfo newsiginfo;  struct siginfo *sip;#ifdef PROCFS_DONT_PIOCSSIG_CURSIG  /* With Alpha OSF/1 procfs, the kernel gets really confused if it     receives a PIOCSSIG with a signal identical to the current signal,     it messes up the current signal. Work around the kernel bug.  */  if (signo == pip -> prstatus.pr_cursig)    return;#endif  if (signo == pip -> prstatus.pr_info.si_signo)    {      sip = &pip -> prstatus.pr_info;    }  else    {      memset ((char *) &newsiginfo, 0, sizeof (newsiginfo));      sip = &newsiginfo;      sip -> si_signo = signo;      sip -> si_code = 0;      sip -> si_errno = 0;      sip -> si_pid = getpid ();      sip -> si_uid = getuid ();    }  if (ioctl (pip -> fd, PIOCSSIG, sip) < 0)    {      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 voidprocfs_resume (pid, step, signo)     int pid;     int step;     enum target_signal signo;{  int signal_to_pass;  struct procinfo *pi, *procinfo;  pi = find_procinfo (pid == -1 ? inferior_pid : pid, 0);  errno = 0;  pi->prrun.pr_flags = PRSTRACE | PRSFAULT | PRCFAULT;#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	   && pi->prstatus.pr_cursig == SIGTSTP	   && pi->prstatus.pr_action.sa_handler == SIG_DFL)    /* 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    {      pi->prrun.pr_flags |= PRCSIG;    }  pi->nopass_next_sigstop = 0;  if (step)    {      pi->prrun.pr_flags |= PRSTEP;    }  /* Don't try to start a process unless it's stopped on an     `event of interest'.  Doing so will cause errors.  */  if ((pi->prstatus.pr_flags & PR_ISTOP)       && ioctl (pi->fd, PIOCRUN, &pi->prrun) != 0)    {      perror_with_name (pi->pathname);      /* NOTREACHED */    }  pi->had_event = 0;  /* Continue all the other threads that haven't had an event of     interest.  */  if (pid == -1)    for (procinfo = procinfo_list; procinfo; procinfo = procinfo->next)      {	if (pi != procinfo && !procinfo->had_event)	  {	    procinfo->prrun.pr_flags &= PRSTEP;	    procinfo->prrun.pr_flags |= PRCFAULT | PRCSIG;	    ioctl (procinfo->fd, PIOCSTATUS, &procinfo->prstatus);	    /* 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->fd, PIOCRUN, &procinfo->prrun) < 0)	      {		if (ioctl (procinfo->fd, PIOCSTATUS, &procinfo->prstatus) < 0)		  {		    fprintf_unfiltered(gdb_stderr, "PIOCSTATUS failed, errno=%d\n", errno);		  }		print_sys_errmsg (procinfo->pathname, errno);		error ("PIOCRUN failed");	      }	    ioctl (procinfo->fd, PIOCSTATUS, &procinfo->prstatus);	  }      }}