📄 procfs.c
字号:
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 + -