📄 procfs.c
字号:
LOCAL FUNCTION procfs_resume -- resume execution of the inferior processSYNOPSIS void procfs_resume (int step, int signo)DESCRIPTION Resume execution of the inferior process. If STEP is nozero, then just single step it. If SIGNAL is nonzero, restart it with that signal activated.NOTE 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. 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?) */static voidprocfs_resume (step, signo) int step; int signo;{ errno = 0; pi.prrun.pr_flags = PRSTRACE | PRSFAULT | PRCFAULT;#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 *) ®isters[REGISTER_BYTE (PC_REGNUM)]; pi.prrun.pr_flags != PRSVADDR;#endif if (signo && !(signo == SIGSTOP && pi.nopass_next_sigstop)) { set_proc_siginfo (&pi, signo); } else { pi.prrun.pr_flags |= PRCSIG; } pi.nopass_next_sigstop = 0; if (step) { pi.prrun.pr_flags |= PRSTEP; } if (ioctl (pi.fd, PIOCRUN, &pi.prrun) != 0) { perror_with_name (pi.pathname); /* NOTREACHED */ }}/*LOCAL FUNCTION procfs_fetch_registers -- fetch current registers from inferiorSYNOPSIS void procfs_fetch_registers (int regno)DESCRIPTION Read the current values of the inferior's registers, both the general register set and floating point registers (if supported) and update gdb's idea of their current values.*/static voidprocfs_fetch_registers (regno) int regno;{ if (ioctl (pi.fd, PIOCGREG, &pi.gregset) != -1) { supply_gregset (&pi.gregset); }#if defined (FP0_REGNUM) if (ioctl (pi.fd, PIOCGFPREG, &pi.fpregset) != -1) { supply_fpregset (&pi.fpregset); }#endif}/*GLOBAL FUNCTION fetch_core_registers -- fetch current registers from core file dataSYNOPSIS void fetch_core_registers (char *core_reg_sect, unsigned core_reg_size, int which, unsigned in reg_addr)DESCRIPTION Read the values of either the general register set (WHICH equals 0) or the floating point register set (WHICH equals 2) from the core file data (pointed to by CORE_REG_SECT), and update gdb's idea of their current values. The CORE_REG_SIZE parameter is ignored.NOTES Use the indicated sizes to validate the gregset and fpregset structures.*/voidfetch_core_registers (core_reg_sect, core_reg_size, which, reg_addr) char *core_reg_sect; unsigned core_reg_size; int which; unsigned int reg_addr; /* Unused in this version */{ if (which == 0) { if (core_reg_size != sizeof (pi.gregset)) { warning ("wrong size gregset struct in core file"); } else { memcpy ((char *) &pi.gregset, core_reg_sect, sizeof (pi.gregset)); supply_gregset (&pi.gregset); } } else if (which == 2) { if (core_reg_size != sizeof (pi.fpregset)) { warning ("wrong size fpregset struct in core file"); } else { memcpy ((char *) &pi.fpregset, core_reg_sect, sizeof (pi.fpregset));#if defined (FP0_REGNUM) supply_fpregset (&pi.fpregset);#endif } }}/*LOCAL FUNCTION proc_init_failed - called whenever /proc access initialization failsSYNOPSIS static void proc_init_failed (char *why)DESCRIPTION This function is called whenever initialization of access to a /proc entry fails. It prints a suitable error message, does some cleanup, and then invokes the standard error processing routine which dumps us back into the command loop. */static voidproc_init_failed (why) char *why;{ print_sys_errmsg (pi.pathname, errno); kill (pi.pid, SIGKILL); close_proc_file (&pi); error (why); /* NOTREACHED */}/*LOCAL FUNCTION close_proc_file - close any currently open /proc entrySYNOPSIS static void close_proc_file (struct procinfo *pip)DESCRIPTION Close any currently open /proc entry and mark the process information entry as invalid. In order to ensure that we don't try to reuse any stale information, the pid, fd, and pathnames are explicitly invalidated, which may be overkill. */static voidclose_proc_file (pip) struct procinfo *pip;{ pip -> pid = 0; if (pip -> valid) { close (pip -> fd); } pip -> fd = -1; if (pip -> pathname) { free (pip -> pathname); pip -> pathname = NULL; } pip -> valid = 0;}/*LOCAL FUNCTION open_proc_file - open a /proc entry for a given process idSYNOPSIS static int open_proc_file (int pid, struct procinfo *pip, int mode)DESCRIPTION Given a process id and a mode, close the existing open /proc entry (if any) and open one for the new process id, in the specified mode. Once it is open, then mark the local process information structure as valid, which guarantees that the pid, fd, and pathname fields match an open /proc entry. Returns zero if the open fails, nonzero otherwise. Note that the pathname is left intact, even when the open fails, so that callers can use it to construct meaningful error messages rather than just "file open failed". */static intopen_proc_file (pid, pip, mode) int pid; struct procinfo *pip; int mode;{ pip -> valid = 0; /* FIXME, what is this? ?! */ if (pip -> valid) { close (pip -> fd); } if (pip -> pathname == NULL) { pip -> pathname = xmalloc (32); } sprintf (pip -> pathname, PROC_NAME_FMT, pid); if ((pip -> fd = open (pip -> pathname, mode)) >= 0) { pip -> valid = 1; pip -> pid = pid; } return (pip -> valid);}static char *mappingflags (flags) long flags;{ static char asciiflags[8]; strcpy (asciiflags, "-------");#if defined (MA_PHYS) if (flags & MA_PHYS) asciiflags[0] = 'd';#endif if (flags & MA_STACK) asciiflags[1] = 's'; if (flags & MA_BREAK) asciiflags[2] = 'b'; if (flags & MA_SHARED) asciiflags[3] = 's'; if (flags & MA_READ) asciiflags[4] = 'r'; if (flags & MA_WRITE) asciiflags[5] = 'w'; if (flags & MA_EXEC) asciiflags[6] = 'x'; return (asciiflags);}static voidinfo_proc_flags (pip, summary) struct procinfo *pip; int summary;{ struct trans *transp; printf_filtered ("%-32s", "Process status flags:"); if (!summary) { printf_filtered ("\n\n"); } for (transp = pr_flag_table; transp -> name != NULL; transp++) { if (pip -> prstatus.pr_flags & transp -> value) { if (summary) { printf_filtered ("%s ", transp -> name); } else { printf_filtered ("\t%-16s %s.\n", transp -> name, transp -> desc); } } } printf_filtered ("\n");}static voidinfo_proc_stop (pip, summary) struct procinfo *pip; int summary;{ struct trans *transp; int why; int what; why = pip -> prstatus.pr_why; what = pip -> prstatus.pr_what; if (pip -> prstatus.pr_flags & PR_STOPPED) { printf_filtered ("%-32s", "Reason for stopping:"); if (!summary) { printf_filtered ("\n\n"); } for (transp = pr_why_table; transp -> name != NULL; transp++) { if (why == transp -> value) { if (summary) { printf_filtered ("%s ", transp -> name); } else { printf_filtered ("\t%-16s %s.\n", transp -> name, transp -> desc); } break; } } /* Use the pr_why field to determine what the pr_what field means, and print more information. */ switch (why) { case PR_REQUESTED: /* pr_what is unused for this case */ break; case PR_JOBCONTROL: case PR_SIGNALLED: if (summary) { printf_filtered ("%s ", signalname (what)); } else { printf_filtered ("\t%-16s %s.\n", signalname (what), safe_strsignal (what)); } break; case PR_SYSENTRY: if (summary) { printf_filtered ("%s ", syscallname (what)); } else { printf_filtered ("\t%-16s %s.\n", syscallname (what), "Entered this system call"); } break; case PR_SYSEXIT: if (summary) { printf_filtered ("%s ", syscallname (what)); } else { printf_filtered ("\t%-16s %s.\n", syscallname (what), "Returned from this system call"); } break; case PR_FAULTED: if (summary) { printf_filtered ("%s ", lookupname (faults_table, what, "fault")); } else { printf_filtered ("\t%-16s %s.\n", lookupname (faults_table, what, "fault"), lookupdesc (faults_table, what)); } break; } printf_filtered ("\n"); }}static voidinfo_proc_siginfo (pip, summary) struct procinfo *pip; int summary;{ struct siginfo *sip; if ((pip -> prstatus.pr_flags & PR_STOPPED) && (pip -> prstatus.pr_why == PR_SIGNALLED || pip -> prstatus.pr_why == PR_FAULTED)) { printf_filtered ("%-32s", "Additional signal/fault info:"); sip = &pip -> prstatus.pr_info; if (summary) { printf_filtered ("%s ", signalname (sip -> si_signo)); if (sip -> si_errno > 0) { printf_filtered ("%s ", errnoname (sip -> si_errno)); } if (sip -> si_code <= 0) { printf_filtered ("sent by pid %d, uid %d ", sip -> si_pid, sip -> si_uid); } else { printf_filtered ("%s ", sigcodename (sip)); if ((sip -> si_signo == SIGILL) || (sip -> si_signo == SIGFPE) || (sip -> si_signo == SIGSEGV) || (sip -> si_signo == SIGBUS)) { printf_filtered ("addr=%#x ", sip -> si_addr); } else if ((sip -> si_signo == SIGCHLD)) { printf_filtered ("child pid %u, status %u ", sip -> si_pid, sip -> si_status); } else if ((sip -> si_signo == SIGPOLL)) { printf_filtered ("band %u ", sip -> si_band); } } } else { printf_filtered ("\n\n"); printf_filtered ("\t%-16s %s.\n", signalname (sip -> si_signo), safe_strsignal (sip -> si_signo)); if (sip -> si_errno > 0) { printf_filtered ("\t%-16s %s.\n", errnoname (sip -> si_errno), safe_strerror (sip -> si_errno)); } if (sip -> si_code <= 0) { printf_filtered ("\t%-16u %s\n", sip -> si_pid, "PID of process sending signal"); printf_filtered ("\t%-16u %s\n", sip -> si_uid, "UID of process sending signal"); } else { printf_filtered ("\t%-16s %s.\n", sigcodename (sip), sigcodedesc (sip)); if ((sip -> si_signo == SIGILL) || (sip -> si_signo == SIGFPE)) { printf_filtered ("\t%-16#x %s.\n", sip -> si_addr, "Address of faulting instruction"); } else if ((sip -> si_signo == SIGSEGV) || (sip -> si_signo == SIGBUS)) { printf_filtered ("\t%-16#x %s.\n", sip -> si_addr, "Address of faulting memory reference"); } else if ((sip -> si_signo == SIGCHLD)) { printf_filtered ("\t%-16u %s.\n", sip -> si_pid, "Child process ID"); printf_filtered ("\t%-16u %s.\n", sip -> si_status, "Child process exit value or signal"); } else if ((sip -> si_signo == SIGPOLL)) { printf_filtered ("\t%-16u %s.\n", sip -> si_band, "Band event for POLL_{IN,OUT,MSG}"); } } } printf_filtered ("\n"); }}static voidinfo_proc_syscalls (pip, summary) struct procinfo *pip; int summary;{ int syscallnum; if (!summary) {#if 0 /* FIXME: Needs to use gdb-wide configu
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -