X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fprocfs.c;h=4c8ab5ccfe9d532b274b55f387fd30aeacd2dda3;hb=25286543da71d927d59a7479e7e1bd0a1b9e1321;hp=79f54aa658807bdb549a5adefab87d7eb3aee7e1;hpb=4ed3a9ea66ca93b7dea29c5cdc23d80e77e442bb;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/procfs.c b/gdb/procfs.c index 79f54aa658..4c8ab5ccfe 100644 --- a/gdb/procfs.c +++ b/gdb/procfs.c @@ -1,5 +1,5 @@ /* Machine independent support for SVR4 /proc (process file system) for GDB. - Copyright (C) 1991 Free Software Foundation, Inc. + Copyright 1991, 1992 Free Software Foundation, Inc. Written by Fred Fish at Cygnus Support. This file is part of GDB. @@ -34,8 +34,6 @@ regardless of whether or not the actual target has floating point hardware. #include "defs.h" -#ifdef USE_PROC_FS /* Entire file goes away if not using /proc */ - #include #include #include @@ -45,6 +43,7 @@ regardless of whether or not the actual target has floating point hardware. #include "inferior.h" #include "target.h" #include "command.h" +#include "gdbcore.h" #define MAX_SYSCALLS 256 /* Maximum number of syscalls for table */ @@ -52,6 +51,8 @@ regardless of whether or not the actual target has floating point hardware. #define PROC_NAME_FMT "/proc/%05d" #endif +extern struct target_ops procfs_ops; /* Forward declaration */ + #if 1 /* FIXME: Gross and ugly hack to resolve coredep.c global */ CORE_ADDR kernel_u_addr; #endif @@ -362,7 +363,7 @@ static int proc_address_to_fd PARAMS ((CORE_ADDR, int)); static int -open_proc_file PARAMS ((int, struct procinfo *)); +open_proc_file PARAMS ((int, struct procinfo *, int)); static void close_proc_file PARAMS ((struct procinfo *)); @@ -406,6 +407,18 @@ lookupname PARAMS ((struct trans *, unsigned int, char *)); static char * lookupdesc PARAMS ((struct trans *, unsigned int)); +static int +do_attach PARAMS ((int pid)); + +static void +do_detach PARAMS ((int siggnal)); + +static void +procfs_create_inferior PARAMS ((char *, char *, char **)); + +static void +procfs_notice_signals PARAMS ((void)); + /* External function prototypes that can't be easily included in any header file because the args are typedefs in system include files. */ @@ -545,7 +558,8 @@ sigcodename (sip) return (name); } -static char *sigcodedesc (sip) +static char * +sigcodedesc (sip) siginfo_t *sip; { struct sigcode *scp; @@ -1031,46 +1045,13 @@ ptrace (request, pid, arg3, arg4) /* -GLOBAL FUNCTION - - kill_inferior_fast -- kill inferior while gdb is exiting - -SYNOPSIS - - void kill_inferior_fast (void) - -DESCRIPTION - - This is used when GDB is exiting. It gives less chance of error. - -NOTES - - Don't attempt to kill attached inferiors since we may be called - when gdb is in the process of aborting, and killing the attached - inferior may be very anti-social. This is particularly true if we - were attached just so we could use the /proc facilities to get - detailed information about it's status. - -*/ - -void -kill_inferior_fast () -{ - if (inferior_pid != 0 && !attach_flag) - { - unconditionally_kill_inferior (); - } -} - -/* - -GLOBAL FUNCTION +LOCAL FUNCTION - kill_inferior - kill any currently inferior + procfs_kill_inferior - kill any currently inferior SYNOPSIS - void kill_inferior (void) + void procfs_kill_inferior (void) DESCRIPTION @@ -1084,8 +1065,8 @@ NOTES */ -void -kill_inferior () +static void +procfs_kill_inferior () { if (inferior_pid != 0) { @@ -1130,13 +1111,13 @@ unconditionally_kill_inferior () /* -GLOBAL FUNCTION +LOCAL FUNCTION - child_xfer_memory -- copy data to or from inferior memory space + procfs_xfer_memory -- copy data to or from inferior memory space SYNOPSIS - int child_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, + int procfs_xfer_memory (CORE_ADDR memaddr, char *myaddr, int len, int dowrite, struct target_ops target) DESCRIPTION @@ -1146,7 +1127,7 @@ DESCRIPTION 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 child_ops + 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. @@ -1155,9 +1136,8 @@ NOTES The /proc interface makes this an almost trivial task. */ - -int -child_xfer_memory (memaddr, myaddr, len, dowrite, target) +static int +procfs_xfer_memory (memaddr, myaddr, len, dowrite, target) CORE_ADDR memaddr; char *myaddr; int len; @@ -1186,13 +1166,13 @@ child_xfer_memory (memaddr, myaddr, len, dowrite, target) /* -GLOBAL FUNCTION +LOCAL FUNCTION - store_inferior_registers -- copy register values back to inferior + procfs_store_registers -- copy register values back to inferior SYNOPSIS - void store_inferior_registers (int regno) + void procfs_store_registers (int regno) DESCRIPTION @@ -1222,8 +1202,8 @@ NOTES */ -void -store_inferior_registers (regno) +static void +procfs_store_registers (regno) int regno; { if (regno != -1) @@ -1252,13 +1232,13 @@ store_inferior_registers (regno) /* -GLOBAL FUNCTION +LOCAL FUNCTION - inferior_proc_init - initialize access to a /proc entry + procfs_init_inferior - initialize access to a /proc entry SYNOPSIS - void inferior_proc_init (int pid) + void procfs_init_inferior (int pid) DESCRIPTION @@ -1275,11 +1255,14 @@ NOTES */ -void -inferior_proc_init (pid) +static void +procfs_init_inferior (pid) int pid; { - if (!open_proc_file (pid, &pi)) + + push_target (&procfs_ops); + + if (!open_proc_file (pid, &pi, O_RDWR)) { proc_init_failed ("can't open process file"); } @@ -1287,7 +1270,7 @@ inferior_proc_init (pid) { memset ((char *) &pi.prrun, 0, sizeof (pi.prrun)); prfillset (&pi.prrun.pr_trace); - proc_signal_handling_change (); + procfs_notice_signals (); prfillset (&pi.prrun.pr_fault); prdelset (&pi.prrun.pr_fault, FLTPAGE); if (ioctl (pi.fd, PIOCWSTOP, &pi.prstatus) < 0) @@ -1305,11 +1288,11 @@ inferior_proc_init (pid) GLOBAL FUNCTION - proc_signal_handling_change + procfs_notice_signals SYNOPSIS - void proc_signal_handling_change (void); + static void procfs_notice_signals (void); DESCRIPTION @@ -1326,8 +1309,8 @@ DESCRIPTION involved. */ -void -proc_signal_handling_change () +static void +procfs_notice_signals () { int signo; @@ -1355,7 +1338,7 @@ proc_signal_handling_change () /* -GLOBAL FUNCTION +LOCAL FUNCTION proc_set_exec_trap -- arrange for exec'd child to halt at startup @@ -1384,7 +1367,7 @@ NOTE tracing flags cleared. */ -void +static void proc_set_exec_trap () { sysset_t exitset; @@ -1435,6 +1418,21 @@ proc_set_exec_trap () #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 } @@ -1483,6 +1481,7 @@ proc_iterate_over_mappings (func) return (funcstat); } +#if 0 /* Currently unused */ /* GLOBAL FUNCTION @@ -1504,9 +1503,6 @@ DESCRIPTION segment containing that address. */ - -#if 0 /* Currently unused */ - CORE_ADDR proc_base_address (addr) CORE_ADDR addr; @@ -1579,17 +1575,117 @@ proc_address_to_fd (addr, complain) } -#ifdef ATTACH_DETACH +/* Attach to process PID, then initialize for debugging it + and wait for the trace-trap that results from attaching. */ + +static void +procfs_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 to program `%s', %s\n", exec_file, target_pid_to_str (pid)); + else + printf ("Attaching to %s\n", target_pid_to_str (pid)); + + fflush (stdout); + } + + do_attach (pid); + 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 void +procfs_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 from program: %s %s\n", + exec_file, target_pid_to_str (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 void +procfs_prepare_to_store () +{ +#ifdef CHILD_PREPARE_TO_STORE + CHILD_PREPARE_TO_STORE (); +#endif +} + +/* Print status information about what we're accessing. */ + +static void +procfs_files_info (ignore) + struct target_ops *ignore; +{ + printf ("\tUsing the running image of %s %s via /proc.\n", + attach_flag? "attached": "child", target_pid_to_str (inferior_pid)); +} + +/* ARGSUSED */ +static void +procfs_open (arg, from_tty) + char *arg; + int from_tty; +{ + error ("Use the \"run\" command to start a Unix child process."); +} /* -GLOBAL FUNCTION +LOCAL FUNCTION - attach -- attach to an already existing process + do_attach -- attach to an already existing process SYNOPSIS - int attach (int pid) + int do_attach (int pid) DESCRIPTION @@ -1601,15 +1697,18 @@ NOTES The option of stopping at attach time is specific to the /proc versions of gdb. Versions using ptrace force the attachee - to stop. + 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) */ -int -attach (pid) +static int +do_attach (pid) int pid; { - if (!open_proc_file (pid, &pi)) + int result; + + if (!open_proc_file (pid, &pi, O_RDWR)) { perror_with_name (pi.pathname); /* NOTREACHED */ @@ -1632,8 +1731,26 @@ attach (pid) else { pi.was_stopped = 0; - if (query ("Process is currently running, stop it? ")) + 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); @@ -1644,10 +1761,10 @@ attach (pid) } else { - printf ("Ok, gdb will wait for process %u to stop.\n", pid); + printf ("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. */ @@ -1661,7 +1778,7 @@ attach (pid) memset (&pi.prrun, 0, sizeof (pi.prrun)); prfillset (&pi.prrun.pr_trace); - proc_signal_handling_change (); + procfs_notice_signals (); prfillset (&pi.prrun.pr_fault); prdelset (&pi.prrun.pr_fault, FLTPAGE); if (ioctl (pi.fd, PIOCSFAULT, &pi.prrun.pr_fault)) @@ -1678,13 +1795,13 @@ attach (pid) /* -GLOBAL FUNCTION +LOCAL FUNCTION - detach -- detach from an attached-to process + do_detach -- detach from an attached-to process SYNOPSIS - void detach (int signal) + void do_detach (int signal) DESCRIPTION @@ -1705,10 +1822,12 @@ DESCRIPTION be the ideal situation. (FIXME). */ -void -detach (signal) +static void +do_detach (signal) int signal; { + int result; + if (signal) { set_proc_siginfo (&pi, signal); @@ -1750,12 +1869,29 @@ detach (signal) if (signal || !pi.was_stopped || query ("Was stopped when attached, make it runnable again? ")) { - memset (&pi.prrun, 0, sizeof (pi.prrun)); - pi.prrun.pr_flags = PRCFAULT; - if (ioctl (pi.fd, PIOCRUN, &pi.prrun)) + /* 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 ("PIOCRUN failed.\n"); + printf ("PIOCSRLC or PIOCSET failed.\n"); } } } @@ -1764,17 +1900,18 @@ detach (signal) attach_flag = 0; } -#endif /* ATTACH_DETACH */ - /* -GLOBAL FUNCTION +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. - proc_wait -- emulate wait() as much as possible SYNOPSIS - int proc_wait (int *statloc) + int procfs_wait (int *statloc) DESCRIPTION @@ -1803,8 +1940,8 @@ NOTES */ -int -proc_wait (statloc) +static int +procfs_wait (statloc) int *statloc; { short what; @@ -1819,10 +1956,17 @@ proc_wait (statloc) } else if (!(pi.prstatus.pr_flags & (PR_STOPPED | PR_ISTOP))) { + if (attach_flag) + set_sigint_trap(); /* Causes SIGINT to be passed on to the + attached process. */ + if (ioctl (pi.fd, PIOCWSTOP, &pi.prstatus) < 0) { checkerr++; } + + if (attach_flag) + clear_sigint_trap(); } if (checkerr) { @@ -1831,6 +1975,7 @@ proc_wait (statloc) rtnval = wait (&statval); if (rtnval != inferior_pid) { + print_sys_errmsg (pi.pathname, errno); error ("PIOCWSTOP, wait failed, returned %d", rtnval); /* NOTREACHED */ } @@ -1919,10 +2064,19 @@ proc_wait (statloc) 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); } @@ -1996,50 +2150,30 @@ set_proc_siginfo (pip, signo) } } -/* - -GLOBAL FUNCTION - - child_resume -- resume execution of the inferior process - -SYNOPSIS - - void child_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?) - */ +/* Resume execution of process PID. If STEP is nozero, then + just single step it. If SIGNAL is nonzero, restart it with that + signal activated. */ -void -child_resume (step, signo) +static void +procfs_resume (pid, step, signo) + int pid; int step; int signo; { + int signal_to_pass; + 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 @@ -2048,11 +2182,46 @@ child_resume (step, signo) pi.prrun.pr_vaddr = (caddr_t) *(int *) ®isters[REGISTER_BYTE (PC_REGNUM)]; pi.prrun.pr_flags != PRSVADDR; +#endif #endif - if (signo && !(signo == SIGSTOP && pi.nopass_next_sigstop)) + if (signo == SIGSTOP && 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 == SIGTSTP + && 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 = signo; + + if (signal_to_pass) { - set_proc_siginfo (&pi, signo); + set_proc_siginfo (&pi, signal_to_pass); } else { @@ -2072,13 +2241,13 @@ child_resume (step, signo) /* -GLOBAL FUNCTION +LOCAL FUNCTION - fetch_inferior_registers -- fetch current registers from inferior + procfs_fetch_registers -- fetch current registers from inferior SYNOPSIS - void fetch_inferior_registers (int regno) + void procfs_fetch_registers (int regno) DESCRIPTION @@ -2088,8 +2257,8 @@ DESCRIPTION */ -void -fetch_inferior_registers (regno) +static void +procfs_fetch_registers (regno) int regno; { if (ioctl (pi.fd, PIOCGREG, &pi.gregset) != -1) @@ -2106,66 +2275,6 @@ fetch_inferior_registers (regno) /* -GLOBAL FUNCTION - - fetch_core_registers -- fetch current registers from core file data - -SYNOPSIS - - 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. -*/ - -void -fetch_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 fails @@ -2238,15 +2347,16 @@ LOCAL FUNCTION SYNOPSIS - static int open_proc_file (pid, struct procinfo *pip) + static int open_proc_file (int pid, struct procinfo *pip, int mode) DESCRIPTION - Given a process id, close the existing open /proc entry (if any) - and open one for the new process id. 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. + 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 @@ -2254,11 +2364,12 @@ DESCRIPTION */ static int -open_proc_file (pid, pip) +open_proc_file (pid, pip, mode) int pid; struct procinfo *pip; + int mode; { - pip -> valid = 0; + pip -> valid = 0; /* FIXME, what is this? ?! */ if (pip -> valid) { close (pip -> fd); @@ -2268,7 +2379,7 @@ open_proc_file (pid, pip) pip -> pathname = xmalloc (32); } sprintf (pip -> pathname, PROC_NAME_FMT, pid); - if ((pip -> fd = open (pip -> pathname, O_RDWR)) >= 0) + if ((pip -> fd = open (pip -> pathname, mode)) >= 0) { pip -> valid = 1; pip -> pid = pid; @@ -2442,7 +2553,8 @@ info_proc_siginfo (pip, summary) } if (sip -> si_code <= 0) { - printf_filtered ("sent by pid %d, uid %d ", sip -> si_pid, + printf_filtered ("sent by %s, uid %d ", + target_pid_to_str (sip -> si_pid), sip -> si_uid); } else @@ -2457,8 +2569,8 @@ info_proc_siginfo (pip, summary) } else if ((sip -> si_signo == SIGCHLD)) { - printf_filtered ("child pid %u, status %u ", - sip -> si_pid, + printf_filtered ("child %s, status %u ", + target_pid_to_str (sip -> si_pid), sip -> si_status); } else if ((sip -> si_signo == SIGPOLL)) @@ -2480,7 +2592,7 @@ info_proc_siginfo (pip, summary) } if (sip -> si_code <= 0) { - printf_filtered ("\t%-16u %s\n", sip -> si_pid, + printf_filtered ("\t%-16u %s\n", sip -> si_pid, /* XXX need target_pid_to_str() */ "PID of process sending signal"); printf_filtered ("\t%-16u %s\n", sip -> si_uid, "UID of process sending signal"); @@ -2503,7 +2615,7 @@ info_proc_siginfo (pip, summary) } else if ((sip -> si_signo == SIGCHLD)) { - printf_filtered ("\t%-16u %s.\n", sip -> si_pid, + printf_filtered ("\t%-16u %s.\n", sip -> si_pid, /* XXX need target_pid_to_str() */ "Child process ID"); printf_filtered ("\t%-16u %s.\n", sip -> si_status, "Child process exit value or signal"); @@ -2748,7 +2860,9 @@ DESCRIPTION info proc mappings (prints address mappings) info proc times (prints process/children times) info proc id (prints pid, ppid, gid, sid, etc) + FIXME: i proc id not implemented. info proc status (prints general process state info) + FIXME: i proc status not implemented. info proc signals (prints info about signal handling) info proc all (prints all info) @@ -2843,7 +2957,7 @@ info_proc (args, from_tty) pid = pii.pid; pip = &pii; memset (&pii, 0, sizeof (pii)); - if (!open_proc_file (pid, pip)) + if (!open_proc_file (pid, pip, O_RDONLY)) { perror_with_name (pip -> pathname); /* NOTREACHED */ @@ -2863,7 +2977,8 @@ info_proc (args, from_tty) if (!pip -> valid) { - error ("No process. Run an inferior or specify an explicit pid."); + error ("\ +No process. Start debugging a program or specify an explicit process ID."); } if (ioctl (pip -> fd, PIOCSTATUS, &(pip -> prstatus)) < 0) { @@ -2911,15 +3026,87 @@ info_proc (args, from_tty) do_cleanups (old_chain); } +/* Fork an inferior process, and start debugging it with /proc. */ + +static void +procfs_create_inferior (exec_file, allargs, env) + char *exec_file; + char *allargs; + char **env; +{ + fork_inferior (exec_file, allargs, env, + proc_set_exec_trap, procfs_init_inferior); + /* We are at the first instruction we care about. */ + /* Pedal to the metal... */ + proceed ((CORE_ADDR) -1, 0, 0); +} + +/* Clean up after the inferior dies. */ + +static void +procfs_mourn_inferior () +{ + unpush_target (&procfs_ops); + generic_mourn_inferior (); +} + +/* Mark our target-struct as eligible for stray "run" and "attach" commands. */ +static int +procfs_can_run () +{ + return(1); +} + +struct target_ops procfs_ops = { + "procfs", /* to_shortname */ + "Unix /proc child process", /* to_longname */ + "Unix /proc child process (started by the \"run\" command).", /* to_doc */ + procfs_open, /* to_open */ + 0, /* to_close */ + procfs_attach, /* to_attach */ + procfs_detach, /* to_detach */ + procfs_resume, /* to_resume */ + procfs_wait, /* to_wait */ + procfs_fetch_registers, /* to_fetch_registers */ + procfs_store_registers, /* to_store_registers */ + procfs_prepare_to_store, /* to_prepare_to_store */ + procfs_xfer_memory, /* to_xfer_memory */ + procfs_files_info, /* to_files_info */ + memory_insert_breakpoint, /* to_insert_breakpoint */ + memory_remove_breakpoint, /* to_remove_breakpoint */ + terminal_init_inferior, /* to_terminal_init */ + terminal_inferior, /* to_terminal_inferior */ + terminal_ours_for_output, /* to_terminal_ours_for_output */ + terminal_ours, /* to_terminal_ours */ + child_terminal_info, /* to_terminal_info */ + procfs_kill_inferior, /* to_kill */ + 0, /* to_load */ + 0, /* to_lookup_symbol */ + procfs_create_inferior, /* to_create_inferior */ + procfs_mourn_inferior, /* to_mourn_inferior */ + procfs_can_run, /* to_can_run */ + procfs_notice_signals, /* to_notice_signals */ + process_stratum, /* to_stratum */ + 0, /* to_next */ + 1, /* to_has_all_memory */ + 1, /* to_has_memory */ + 1, /* to_has_stack */ + 1, /* to_has_registers */ + 1, /* to_has_execution */ + 0, /* sections */ + 0, /* sections_end */ + OPS_MAGIC /* to_magic */ +}; + /* GLOBAL FUNCTION - _initialize_proc_fs -- initialize the process file system stuff + _initialize_procfs -- initialize the process file system stuff SYNOPSIS - void _initialize_proc_fs (void) + void _initialize_procfs (void) DESCRIPTION @@ -2928,19 +3115,18 @@ DESCRIPTION */ -static char *proc_desc = +void +_initialize_procfs () +{ + add_target (&procfs_ops); + + add_info ("proc", info_proc, "Show process status information using /proc entry.\n\ Specify process id or use current inferior by default.\n\ Specify keywords for detailed information; default is summary.\n\ Keywords are: `all', `faults', `flags', `id', `mappings', `signals',\n\ `status', `syscalls', and `times'.\n\ -Unambiguous abbreviations may be used."; +Unambiguous abbreviations may be used."); -void -_initialize_proc_fs () -{ - add_info ("proc", info_proc, proc_desc); init_syscall_table (); } - -#endif /* USE_PROC_FS */