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

📄 procfs.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 5 页
字号:
      unconditionally_kill_inferior ();      target_mourn_inferior ();    }}/*LOCAL FUNCTION	unconditionally_kill_inferior - terminate the inferiorSYNOPSIS	static void unconditionally_kill_inferior (void)DESCRIPTION	Kill the current inferior.  Should not be called until it	is at least tested that there is an 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.*/static voidunconditionally_kill_inferior (){  int signo;    signo = SIGKILL;  ioctl (pi.fd, PIOCKILL, &signo);  close_proc_file (&pi);  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;  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;{  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	procfs_init_inferior - initialize access to a /proc entrySYNOPSIS	void procfs_init_inferior (int pid)DESCRIPTION	When gdb starts an inferior, this function is called in the parent	process immediately after the fork.  It waits for the child to stop	on the return from the exec system call (the child itself takes care	of ensuring that this is set up), then sets up the set of signals	and faults that are to be traced.NOTES	If proc_init_failed ever gets called, control returns to the command	processing loop via the standard error handling code. */static voidprocfs_init_inferior (pid)     int pid;{  push_target (&procfs_ops);  if (!open_proc_file (pid, &pi, O_RDWR))    {      proc_init_failed ("can't open process file");    }  else    {      memset ((char *) &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, PIOCWSTOP, &pi.prstatus) < 0)	{	  proc_init_failed ("PIOCWSTOP failed");	}      else if (ioctl (pi.fd, PIOCSFAULT, &pi.prrun.pr_fault) < 0)	{	  proc_init_failed ("PIOCSFAULT failed");	}    }}/*GLOBAL FUNCTION	procfs_notice_signalsSYNOPSIS	static void procfs_notice_signals (void);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 (){  int signo;  if (pi.valid)    {      for (signo = 0; signo < NSIG; signo++)	{	  if (signal_stop_state (signo) == 0 &&	      signal_print_state (signo) == 0 &&	      signal_pass_state (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;  auto char procname[32];  int fd;    sprintf (procname, PROC_NAME_FMT, getpid ());  if ((fd = open (procname, O_RDWR)) < 0)    {      perror (procname);      fflush (stderr);      _exit (127);    }  premptyset (&exitset);  /* 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);      fflush (stderr);      _exit (127);    }  /* Turn off inherit-on-fork flag so that all grand-children of gdb     start with tracing flags cleared. */#if defined (PIOCRESET)	/* New method */  {      long pr_flags;      pr_flags = PR_FORK;      ioctl (fd, PIOCRESET, &pr_flags);  }#else#if defined (PIOCRFORK)	/* Original method */  ioctl (fd, PIOCRFORK, NULL);#endif#endif  /* Turn on run-on-last-close flag so that this process will not hang     if GDB goes away for some reason.  */#if defined (PIOCSET)	/* New method */  {      long pr_flags;      pr_flags = PR_RLC;      (void) ioctl (fd, PIOCSET, &pr_flags);  }#else#if defined (PIOCSRLC)	/* Original method */  (void) ioctl (fd, PIOCSRLC, 0);#endif#endif}/*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;  if (pi.valid && (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 ((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;  if (pi.valid && (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 (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 (addr, complain)     CORE_ADDR addr;     int complain;{  int fd = -1;  if (pi.valid)    {      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 ("Attaching program `%s', pid %d\n", exec_file, pid);      else	printf ("Attaching pid %d\n", pid);      fflush (stdout);    }  do_attach (pid);

⌨️ 快捷键说明

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