⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 procfs.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
  inferior_pid = 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 ("Detaching program: %s pid %d\n",	      exec_file, inferior_pid);      fflush (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 ("\tUsing the running image of %s process %d via /proc.\n",	  attach_flag? "attached": "child", 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;{  int result;  if (!open_proc_file (pid, &pi, O_RDWR))    {      perror_with_name (pi.pathname);      /* NOTREACHED */    }    /*  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.  */#if defined (PIOCSET)	/* New method */	  {	      long pr_flags;	      pr_flags = PR_RLC;	      result = ioctl (pi.fd, PIOCSET, &pr_flags);	  }#else#if defined (PIOCSRLC)	/* Original method */	  result = ioctl (pi.fd, PIOCSRLC, 0);#endif#endif	  if (result < 0)	    {	      print_sys_errmsg (pi.pathname, errno);	      close_proc_file (&pi);	      error ("PIOCSRLC or PIOCSET failed");	    }	  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 ("Ok, gdb will wait for process %u to stop.\n", 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 ();  prfillset (&pi.prrun.pr_fault);  prdelset (&pi.prrun.pr_fault, FLTPAGE);  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;{  int result;  if (signal)    {      set_proc_siginfo (&pi, signal);    }  if (ioctl (pi.fd, PIOCSEXIT, &pi.saved_exitset) < 0)    {      print_sys_errmsg (pi.pathname, errno);      printf ("PIOCSEXIT failed.\n");    }  if (ioctl (pi.fd, PIOCSENTRY, &pi.saved_entryset) < 0)    {      print_sys_errmsg (pi.pathname, errno);      printf ("PIOCSENTRY failed.\n");    }  if (ioctl (pi.fd, PIOCSTRACE, &pi.saved_trace) < 0)    {      print_sys_errmsg (pi.pathname, errno);      printf ("PIOCSTRACE failed.\n");    }  if (ioctl (pi.fd, PIOCSHOLD, &pi.saved_sighold) < 0)    {      print_sys_errmsg (pi.pathname, errno);      printf ("PIOSCHOLD failed.\n");    }  if (ioctl (pi.fd, PIOCSFAULT, &pi.saved_fltset) < 0)    {      print_sys_errmsg (pi.pathname, errno);      printf ("PIOCSFAULT failed.\n");    }  if (ioctl (pi.fd, PIOCSTATUS, &pi.prstatus) < 0)    {      print_sys_errmsg (pi.pathname, errno);      printf ("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 fault that might have stopped it.  */	      if (ioctl (pi.fd, PIOCCFAULT, 0))  		{  		  print_sys_errmsg (pi.pathname, errno);		  printf ("PIOCCFAULT failed.\n");  		}	      /* Make it run again when we close it.  */#if defined (PIOCSET)	/* New method */	      {		  long pr_flags;		  pr_flags = PR_RLC;		  result = ioctl (pi.fd, PIOCSET, &pr_flags);	      }#else#if defined (PIOCSRLC)	/* Original method */	      result = ioctl (pi.fd, PIOCSRLC, 0);#endif#endif	      if (result)		{		  print_sys_errmsg (pi.pathname, errno);		  printf ("PIOCSRLC or PIOCSET failed.\n");		}	    }	}    }  close_proc_file (&pi);  attach_flag = 0;}/*LOCAL FUNCTION	procfs_wait -- emulate wait() as much as possible	Wait for child to do something.  Return pid of child, or -1 in case	of error; store status through argument pointer STATUS.SYNOPSIS	int procfs_wait (int *statloc)DESCRIPTION	Try to emulate wait() as much as possible.  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.NOTES	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 (statloc)     int *statloc;{  short what;  short why;  int statval = 0;  int checkerr = 0;  int rtnval = -1;    if (ioctl (pi.fd, PIOCSTATUS, &pi.prstatus) < 0)    {      checkerr++;    }  else if (!(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.prstatus.pr_pid;      why = pi.prstatus.pr_why;      what = pi.prstatus.pr_what;      if (why == PR_SIGNALLED)	{	  statval = (what << 8) | 0177;	}      else if ((why == PR_SYSEXIT)	       &&	       (#ifdef SYS_exec		what == SYS_exec#else		0 == 0#endif#ifdef SYS_execve		|| what == SYS_execve#endif#ifdef SYS_execv		|| what == SYS_execv#endif		))	{	  statval = (SIGTRAP << 8) | 0177;	}      else if (why == PR_REQUESTED)	{	  statval = (SIGSTOP << 8) | 0177;	}      else if (why == PR_JOBCONTROL)	{	  statval = (what << 8) | 0177;	}      else if (why == PR_FAULTED)	{	  switch (what)	    {	    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 */	    default:	      rtnval = -1;	      error ("PIOCWSTOP, unknown why %d, what %d", why, what);	      /* NOTREACHED */	    }	}      else	{	  rtnval = -1;	  error ("PIOCWSTOP, unknown why %d, what %d", why, what);	  /* NOTREACHED */	}    }  else    {      error ("PIOCWSTOP, stopped for unknown/unhandled reason, flags %#x", 	     pi.prstatus.pr_flags);	  /* NOTREACHED */    }  if (statloc)    {      *statloc = statval;    }  if (rtnval == -1)		/* No more children to wait for */    {      fprintf (stderr, "Child process unexpectedly missing.\n");      *statloc = 42;	/* Claim it exited with signal 42 */      return rtnval;    }  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;  if (pip -> valid)    {      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");	}    }}/*

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -