From: Fred Fish Date: Wed, 1 Apr 1992 19:46:14 +0000 (+0000) Subject: Many changes to procfs.c, mostly to expand the "info proc" command and to X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=cc221e76d677199b674aa81b9b69597ed3b4da83;p=binutils-gdb.git Many changes to procfs.c, mostly to expand the "info proc" command and to fix a couple of small bugs. Changes to other files mostly to fix minor things pointed out by the SGI compiler. See ChangeLog for complete details. --- diff --git a/gdb/ChangeLog b/gdb/ChangeLog index e9420813f77..a25d9d3800a 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,70 @@ +Wed Apr 1 11:39:52 1992 Fred Fish (fnf@cygnus.com) + + * breakpoint.h (bpdisp, bptype): Remove trailing comma. + * symtab.h (current_source_symtab): Make extern + * symtab.h (current_source_line): Make extern + * inferior.h: Move all procfs.c prototypes to one place, add + prototype for proc_signal_handling_change. Add prototypes for + signal_stop_state, signal_print_state, and signal_pass_state. + * inferior.h (stop_soon_quietly): Make extern + * inferior.h (attach_flag): Make extern + * infrun.c (NOTICE_SIGNAL_HANDLING_CHANGE): Default is null. + * infrun.c (signal_stop_state, signal_print_state, + signal_pass_state): New functions to query specific signal + handling flags. + * infrun.c (handle_command): Minor error message change, add + NOTICE_SIGNAL_HANDLING_CHANGE. + * procfs.c (open_proc_file): Remove iris specific reset of + inherit-on-fork flag, moved to proc_set_exec_trap(). + * procfs.c (proc_set_exec_trap): Add SVR4 and iris code + to reset inherit-on-fork flag, bash comment to GNU form. + * procfs.c (proc_base_address, set_proc_siginfo, + fetch_core_registers): Conform to code style. + * procfs.c (signame.h): Include. + * procfs.c (MAX_SYSCALLS, syscall_table[], init_syscalltable(), + syscallname(), info_proc_syscalls()): New macros, tables, and + functions to organize and report system call information. + * procfs.c (saved_fltset, saved_trace, saved_sighold, + saved_exitset, saved_entryset): Add to procinfo struct. + * procfs.c (struct trans): Add. + * procfs.c (pr_flag_table, pr_why_table, faults_table, + siginfo_table, errno_table): Tables to translate numeric values + to symbolic names and short descriptions. + * procfs.c (signalname, info_proc_signals): Add function and + prototype. + * procfs.c (proc_info): Now info_proc. + * procfs.c (proc_info_address_map): Now info_proc_mappings. + * procfs.c (info_proc_flags, info_proc_stop, info_proc_siginfo, + info_proc_faults, lookupname, lookupdesc, sigcodename, + sigcodedesc): New functions. + * procfs.c (proc_signal_handling_change): New function to set + the trace flags based on the state of gdb's signal handling flags. + * procfs.c (inferior_proc_init): Call proc_signal_handling_change + and remove code to do PIOCSTRACE ioctl. + * procfs.c (attach, detach): Preserve and restore process flags + using saved_* fields in procinfo struct. + * procfs.c (attach): Call proc_signal_handling_change. + * procfs.c (info_proc): Major rework to expand "info proc" cmd. + * procfs.c (proc_desc): Update for latest changes. + * xm-irix4.h (CREATE_INFERIOR_HOOK): Protect by USE_PROC_FS. + * xm-irix4.h (NOTICE_SIGNAL_HANDLING_CHANGE): Add definition. + * xm-sysv4.h (NOTICE_SIGNAL_HANDLING_CHANGE): Add definition. + +Tue Mar 31 18:38:28 1992 Fred Fish (fnf@cygnus.com) + + * procfs.c (set_proc_siginfo): Add prototype and new function. + * procfs.c (detach, child_resume): Call set_proc_siginfo to set + up inferior siginfo struct. + * elfread.c (elf_symfile_read): Compute the relocation amount + by subtracting off the address of the ".text" section. + * solib.c: Add pointer to ".text" section to so_list struct. + * solib.c (solib_map_sections): Initialize pointer to ".text" + section in so_list struct. + * solib.c (symbol_add_stub): Pass base address of ".text" + section to symbol_file_add, rather than the load address of + the shared library. On SunOS they are the same. On SVR4 they + are not. + Tue Mar 31 17:48:15 1992 Stu Grossman (grossman at cygnus.com) * mipsread.c (parse_procedure): PDR.isym should get pointer to diff --git a/gdb/inferior.h b/gdb/inferior.h index eed848ceffa..ce92228096e 100644 --- a/gdb/inferior.h +++ b/gdb/inferior.h @@ -1,6 +1,6 @@ /* Variables that describe the inferior process running under GDB: Where it is, why it stopped, and how to step it. - Copyright (C) 1986, 1989 Free Software Foundation, Inc. + Copyright 1986, 1989, 1992 Free Software Foundation, Inc. This file is part of GDB. @@ -18,6 +18,12 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +#if !defined (INFERIOR_H) +#define INFERIOR_H 1 + +/* For symtab_and_line */ +#include "symtab.h" + /* For bpstat. */ #include "breakpoint.h" @@ -57,7 +63,11 @@ struct inferior_status { int proceed_to_finish; }; -void save_inferior_status (), restore_inferior_status (); +extern void +save_inferior_status PARAMS ((struct inferior_status *, int)); + +extern void +restore_inferior_status PARAMS ((struct inferior_status *)); /* File name for default use for standard in/out in the inferior. */ @@ -71,29 +81,142 @@ extern int inferior_pid; extern char registers[]; -extern void clear_proceed_status (); -extern void start_inferior (); -extern void proceed (); -extern void kill_inferior (); -extern void kill_inferior_fast (); -extern void generic_mourn_inferior (); -extern void terminal_ours (); -extern void detach (); -extern void run_stack_dummy (); -extern CORE_ADDR read_pc (); -extern void write_pc (); -extern void wait_for_inferior (); -extern void init_wait_for_inferior (); -extern void close_exec_file (); -extern void reopen_exec_file (); +extern void +clear_proceed_status PARAMS ((void)); + +extern void +proceed PARAMS ((CORE_ADDR, int, int)); + +extern void +kill_inferior PARAMS ((void)); + +extern void +kill_inferior_fast PARAMS ((void)); + +extern void +generic_mourn_inferior PARAMS ((void)); + +extern void +terminal_ours PARAMS ((void)); + +extern void +run_stack_dummy PARAMS ((CORE_ADDR, char [REGISTER_BYTES])); + +extern CORE_ADDR +read_pc PARAMS ((void)); + +extern void +write_pc PARAMS ((CORE_ADDR)); + +extern void +wait_for_inferior PARAMS ((void)); + +extern void +init_wait_for_inferior PARAMS ((void)); + +extern void +close_exec_file PARAMS ((void)); + +extern void +reopen_exec_file PARAMS ((void)); + +/* From misc files */ + +extern void +store_inferior_registers PARAMS ((int)); + +extern void +fetch_inferior_registers PARAMS ((int)); + +extern void +solib_create_inferior_hook PARAMS ((void)); + +extern void +child_mourn_inferior PARAMS ((void)); + +extern void +child_terminal_info PARAMS ((char *, int)); + +extern void +term_info PARAMS ((char *, int)); + +extern void +terminal_ours_for_output PARAMS ((void)); + +extern void +terminal_inferior PARAMS ((void)); + +extern void +terminal_init_inferior PARAMS ((void)); + +/* From infptrace.c or procfs.c */ + +extern int +attach PARAMS ((int)); + +void +detach PARAMS ((int)); + +extern void +child_resume PARAMS ((int, int)); + +/* From procfs.c */ + +#ifdef USE_PROC_FS + +extern int +proc_iterate_over_mappings PARAMS ((int (*) (int, CORE_ADDR))); + +extern int +proc_wait PARAMS ((int *)); + +extern void +inferior_proc_init PARAMS ((int)); + +extern void +proc_signal_handling_change PARAMS ((void)); + +extern void +proc_set_exec_trap PARAMS ((void)); -/* From infcmd.c */ -void attach_command ( -#ifdef __STDC__ - char *arg, int from_tty #endif - ); - + +/* From inflow.c */ + +extern void +new_tty_prefork PARAMS ((char *)); + +/* From infrun.c */ + +extern void +start_remote PARAMS ((void)); + +extern void +child_create_inferior PARAMS ((char *, char *, char **)); + +extern void +child_attach PARAMS ((char *, int)); + +extern void +normal_stop PARAMS ((void)); + +extern int +signal_stop_state PARAMS ((int)); + +extern int +signal_print_state PARAMS ((int)); + +extern int +signal_pass_state PARAMS ((int)); + +/* From infcmd.c */ + +extern void +tty_command PARAMS ((char *, int)); + +extern void +attach_command PARAMS ((char *, int)); + /* Last signal that the inferior received (why it stopped). */ extern int stop_signal; @@ -157,7 +280,7 @@ extern int step_multi; when running in the shell before the child program has been exec'd; and when running some kinds of remote stuff (FIXME?). */ -int stop_soon_quietly; +extern int stop_soon_quietly; /* Nonzero if proceed is being used for a "finish" command or a similar situation when stop_registers should be saved. */ @@ -179,7 +302,7 @@ extern int pc_changed; /* Nonzero if the child process in inferior_pid was attached rather than forked. */ -int attach_flag; +extern int attach_flag; /* Possible values for CALL_DUMMY_LOCATION. */ #define ON_STACK 1 @@ -195,11 +318,13 @@ int attach_flag; subtracted out. */ #if !defined (PC_IN_CALL_DUMMY) #if CALL_DUMMY_LOCATION == BEFORE_TEXT_END +extern CORE_ADDR text_end; #define PC_IN_CALL_DUMMY(pc, sp, frame_address) \ ((pc) >= text_end - CALL_DUMMY_LENGTH \ && (pc) < text_end + DECR_PC_AFTER_BREAK) #else /* Not before text_end. */ #if CALL_DUMMY_LOCATION == AFTER_TEXT_END +extern CORE_ADDR text_end; #define PC_IN_CALL_DUMMY(pc, sp, frame_address) \ ((pc) >= text_end \ && (pc) < text_end + CALL_DUMMY_LENGTH + DECR_PC_AFTER_BREAK) @@ -209,3 +334,5 @@ int attach_flag; #endif /* On stack. */ #endif /* Not before text_end. */ #endif /* No PC_IN_CALL_DUMMY. */ + +#endif /* !defined (INFERIOR_H) */ diff --git a/gdb/infrun.c b/gdb/infrun.c index 9bd4d3e327f..98e7227e580 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -158,6 +158,9 @@ resume_cleanups PARAMS ((int)); extern char **environ; +extern int sys_nerr; +extern char *sys_errlist[]; + extern struct target_ops child_ops; /* In inftarg.c */ /* Sigtramp is a routine that the kernel calls (which then calls the @@ -198,6 +201,12 @@ extern struct target_ops child_ops; /* In inftarg.c */ #define IN_SOLIB_TRAMPOLINE(pc,name) 0 #endif +/* Notify other parts of gdb that might care that signal handling may + have changed for one or more signals. */ +#ifndef NOTICE_SIGNAL_HANDLING_CHANGE +#define NOTICE_SIGNAL_HANDLING_CHANGE /* No actions */ +#endif + #ifdef TDESC #include "tdesc.h" int safe_to_init_tdesc_context = 0; @@ -466,8 +475,6 @@ child_create_inferior (exec_file, allargs, env) { int pid; char *shell_command; - extern int sys_nerr; - extern char *sys_errlist[]; char *shell_file; static char default_shell_file[] = SHELL_FILE; int len; @@ -1128,7 +1135,7 @@ wait_for_inferior () #if 0 if (* step_frame_address == 0 || (step_frame_address == stop_frame_address)) -#endif 0 +#endif { remove_step_breakpoint (); step_resume_break_address = 0; @@ -1579,6 +1586,24 @@ remove_step_breakpoint () step_resume_break_shadow); } +int signal_stop_state (signo) + int signo; +{ + return ((signo >= 0 && signo < NSIG) ? signal_stop[signo] : 0); +} + +int signal_print_state (signo) + int signo; +{ + return ((signo >= 0 && signo < NSIG) ? signal_print[signo] : 0); +} + +int signal_pass_state (signo) + int signo; +{ + return ((signo >= 0 && signo < NSIG) ? signal_program[signo] : 0); +} + static void sig_print_header () { @@ -1688,7 +1713,7 @@ handle_command (args, from_tty) /* Not a number and not a recognized flag word => complain. */ else { - error ("Unrecognized flag word: \"%s\".", p); + error ("Unrecognized or ambiguous flag word: \"%s\".", p); } /* Find start of next word. */ @@ -1696,6 +1721,8 @@ handle_command (args, from_tty) while (*p == ' ' || *p == '\t') p++; } + NOTICE_SIGNAL_HANDLING_CHANGE; + if (from_tty) { /* Show the results. */ diff --git a/gdb/procfs.c b/gdb/procfs.c index dc5ae10d1d4..407c65fe90a 100644 --- a/gdb/procfs.c +++ b/gdb/procfs.c @@ -43,6 +43,9 @@ regardless of whether or not the actual target has floating point hardware. #include "inferior.h" #include "target.h" +#include "signame.h" + +#define MAX_SYSCALLS 256 /* Maximum number of syscalls for table */ #ifndef PROC_NAME_FMT #define PROC_NAME_FMT "/proc/%d" @@ -52,6 +55,13 @@ regardless of whether or not the actual target has floating point hardware. CORE_ADDR kernel_u_addr; #endif +#ifdef BROKEN_SIGINFO_H /* Workaround broken SGS */ +#undef si_pid +#define si_pid _data._proc.pid +#undef si_uid +#define si_uid _data._proc._pdata._kill.uid +#endif /* BROKEN_SIGINFO_H */ + /* All access to the inferior, either one started by gdb or one that has been attached to, is controlled by an instance of a procinfo structure, defined below. Since gdb currently only handles one inferior at a time, @@ -75,15 +85,633 @@ struct procinfo { sigset_t trace; /* Current traced signal set */ sysset_t exitset; /* Current traced system call exit set */ sysset_t entryset; /* Current traced system call entry set */ + fltset_t saved_fltset; /* Saved traced hardware fault set */ + sigset_t saved_trace; /* Saved traced signal set */ + sigset_t saved_sighold; /* Saved held signal set */ + sysset_t saved_exitset; /* Saved traced system call exit set */ + sysset_t saved_entryset; /* Saved traced system call entry set */ }; static struct procinfo pi; /* Inferior's process information */ +/* Much of the information used in the /proc interface, particularly for + printing status information, is kept as tables of structures of the + following form. These tables can be used to map numeric values to + their symbolic names and to a string that describes their specific use. */ + +struct trans { + int value; /* The numeric value */ + char *name; /* The equivalent symbolic value */ + char *desc; /* Short description of value */ +}; + +/* Translate bits in the pr_flags member of the prstatus structure, into the + names and desc information. */ + +static struct trans pr_flag_table[] = +{ +#if defined (PR_STOPPED) + PR_STOPPED, "PR_STOPPED", "Process is stopped", +#endif +#if defined (PR_ISTOP) + PR_ISTOP, "PR_ISTOP", "Stopped on an event of interest", +#endif +#if defined (PR_DSTOP) + PR_DSTOP, "PR_DSTOP", "A stop directive is in effect", +#endif +#if defined (PR_ASLEEP) + PR_ASLEEP, "PR_ASLEEP", "Sleeping in an interruptible system call", +#endif +#if defined (PR_FORK) + PR_FORK, "PR_FORK", "Inherit-on-fork is in effect", +#endif +#if defined (PR_RLC) + PR_RLC, "PR_RLC", "Run-on-last-close is in effect", +#endif +#if defined (PR_PTRACE) + PR_PTRACE, "PR_PTRACE", "Process is being controlled by ptrace", +#endif +#if defined (PR_PCINVAL) + PR_PCINVAL, "PR_PCINVAL", "PC refers to an invalid virtual address", +#endif +#if defined (PR_ISSYS) + PR_ISSYS, "PR_ISSYS", "Is a system process", +#endif + 0, NULL, NULL +}; + +/* Translate values in the pr_why field of the prstatus struct. */ + +static struct trans pr_why_table[] = +{ +#if defined (PR_REQUESTED) + PR_REQUESTED, "PR_REQUESTED", "Directed to stop via PIOCSTOP/PIOCWSTOP", +#endif +#if defined (PR_SIGNALLED) + PR_SIGNALLED, "PR_SIGNALLED", "Receipt of a traced signal", +#endif +#if defined (PR_FAULTED) + PR_FAULTED, "PR_FAULTED", "Incurred a traced hardware fault", +#endif +#if defined (PR_SYSENTRY) + PR_SYSENTRY, "PR_SYSENTRY", "Entry to a traced system call", +#endif +#if defined (PR_SYSEXIT) + PR_SYSEXIT, "PR_SYSEXIT", "Exit from a traced system call", +#endif +#if defined (PR_JOBCONTROL) + PR_JOBCONTROL, "PR_JOBCONTROL", "Default job control stop signal action", +#endif + 0, NULL, NULL +}; + +/* Hardware fault translation table. */ + +static struct trans faults_table[] = +{ +#if defined (FLTILL) + FLTILL, "FLTILL", "Illegal instruction", +#endif +#if defined (FLTPRIV) + FLTPRIV, "FLTPRIV", "Privileged instruction", +#endif +#if defined (FLTBPT) + FLTBPT, "FLTBPT", "Breakpoint trap", +#endif +#if defined (FLTTRACE) + FLTTRACE, "FLTTRACE", "Trace trap", +#endif +#if defined (FLTACCESS) + FLTACCESS, "FLTACCESS", "Memory access fault", +#endif +#if defined (FLTBOUNDS) + FLTBOUNDS, "FLTBOUNDS", "Memory bounds violation", +#endif +#if defined (FLTIOVF) + FLTIOVF, "FLTIOVF", "Integer overflow", +#endif +#if defined (FLTIZDIV) + FLTIZDIV, "FLTIZDIV", "Integer zero divide", +#endif +#if defined (FLTFPE) + FLTFPE, "FLTFPE", "Floating-point exception", +#endif +#if defined (FLTSTACK) + FLTSTACK, "FLTSTACK", "Unrecoverable stack fault", +#endif +#if defined (FLTPAGE) + FLTPAGE, "FLTPAGE", "Recoverable page fault", +#endif + 0, NULL, NULL +}; + +/* Translation table for signal generation information. See UNIX System + V Release 4 Programmer's Reference Manual, siginfo(5). */ + +static struct sigcode { + int signo; + int code; + char *codename; + char *desc; +} siginfo_table[] = { +#if defined (SIGILL) && defined (ILL_ILLOPC) + SIGILL, ILL_ILLOPC, "ILL_ILLOPC", "Illegal opcode", +#endif +#if defined (SIGILL) && defined (ILL_ILLOPN) + SIGILL, ILL_ILLOPN, "ILL_ILLOPN", "Illegal operand", +#endif +#if defined (SIGILL) && defined (ILL_ILLADR) + SIGILL, ILL_ILLADR, "ILL_ILLADR", "Illegal addressing mode", +#endif +#if defined (SIGILL) && defined (ILL_ILLTRP) + SIGILL, ILL_ILLTRP, "ILL_ILLTRP", "Illegal trap", +#endif +#if defined (SIGILL) && defined (ILL_PRVOPC) + SIGILL, ILL_PRVOPC, "ILL_PRVOPC", "Privileged opcode", +#endif +#if defined (SIGILL) && defined (ILL_PRVREG) + SIGILL, ILL_PRVREG, "ILL_PRVREG", "Privileged register", +#endif +#if defined (SIGILL) && defined (ILL_COPROC) + SIGILL, ILL_COPROC, "ILL_COPROC", "Coprocessor error", +#endif +#if defined (SIGILL) && defined (ILL_BADSTK) + SIGILL, ILL_BADSTK, "ILL_BADSTK", "Internal stack error", +#endif +#if defined (SIGFPE) && defined (FPE_INTDIV) + SIGFPE, FPE_INTDIV, "FPE_INTDIV", "Integer divide by zero", +#endif +#if defined (SIGFPE) && defined (FPE_INTOVF) + SIGFPE, FPE_INTOVF, "FPE_INTOVF", "Integer overflow", +#endif +#if defined (SIGFPE) && defined (FPE_FLTDIV) + SIGFPE, FPE_FLTDIV, "FPE_FLTDIV", "Floating point divide by zero", +#endif +#if defined (SIGFPE) && defined (FPE_FLTOVF) + SIGFPE, FPE_FLTOVF, "FPE_FLTOVF", "Floating point overflow", +#endif +#if defined (SIGFPE) && defined (FPE_FLTUND) + SIGFPE, FPE_FLTUND, "FPE_FLTUND", "Floating point underflow", +#endif +#if defined (SIGFPE) && defined (FPE_FLTRES) + SIGFPE, FPE_FLTRES, "FPE_FLTRES", "Floating point inexact result", +#endif +#if defined (SIGFPE) && defined (FPE_FLTINV) + SIGFPE, FPE_FLTINV, "FPE_FLTINV", "Invalid floating point operation", +#endif +#if defined (SIGFPE) && defined (FPE_FLTSUB) + SIGFPE, FPE_FLTSUB, "FPE_FLTSUB", "Subscript out of range", +#endif +#if defined (SIGSEGV) && defined (SEGV_MAPERR) + SIGSEGV, SEGV_MAPERR, "SEGV_MAPERR", "Address not mapped to object", +#endif +#if defined (SIGSEGV) && defined (SEGV_ACCERR) + SIGSEGV, SEGV_ACCERR, "SEGV_ACCERR", "Invalid permissions for object", +#endif +#if defined (SIGBUS) && defined (BUS_ADRALN) + SIGBUS, BUS_ADRALN, "BUS_ADRALN", "Invalid address alignment", +#endif +#if defined (SIGBUS) && defined (BUS_ADRERR) + SIGBUS, BUS_ADRERR, "BUS_ADRERR", "Non-existent physical address", +#endif +#if defined (SIGBUS) && defined (BUS_OBJERR) + SIGBUS, BUS_OBJERR, "BUS_OBJERR", "Object specific hardware error", +#endif +#if defined (SIGTRAP) && defined (TRAP_BRKPT) + SIGTRAP, TRAP_BRKPT, "TRAP_BRKPT", "Process breakpoint", +#endif +#if defined (SIGTRAP) && defined (TRAP_TRACE) + SIGTRAP, TRAP_TRACE, "TRAP_TRACE", "Process trace trap", +#endif +#if defined (SIGCLD) && defined (CLD_EXITED) + SIGCLD, CLD_EXITED, "CLD_EXITED", "Child has exited", +#endif +#if defined (SIGCLD) && defined (CLD_KILLED) + SIGCLD, CLD_KILLED, "CLD_KILLED", "Child was killed", +#endif +#if defined (SIGCLD) && defined (CLD_DUMPED) + SIGCLD, CLD_DUMPED, "CLD_DUMPED", "Child has terminated abnormally", +#endif +#if defined (SIGCLD) && defined (CLD_TRAPPED) + SIGCLD, CLD_TRAPPED, "CLD_TRAPPED", "Traced child has trapped", +#endif +#if defined (SIGCLD) && defined (CLD_STOPPED) + SIGCLD, CLD_STOPPED, "CLD_STOPPED", "Child has stopped", +#endif +#if defined (SIGCLD) && defined (CLD_CONTINUED) + SIGCLD, CLD_CONTINUED, "CLD_CONTINUED", "Stopped child had continued", +#endif +#if defined (SIGPOLL) && defined (POLL_IN) + SIGPOLL, POLL_IN, "POLL_IN", "Input input available", +#endif +#if defined (SIGPOLL) && defined (POLL_OUT) + SIGPOLL, POLL_OUT, "POLL_OUT", "Output buffers available", +#endif +#if defined (SIGPOLL) && defined (POLL_MSG) + SIGPOLL, POLL_MSG, "POLL_MSG", "Input message available", +#endif +#if defined (SIGPOLL) && defined (POLL_ERR) + SIGPOLL, POLL_ERR, "POLL_ERR", "I/O error", +#endif +#if defined (SIGPOLL) && defined (POLL_PRI) + SIGPOLL, POLL_PRI, "POLL_PRI", "High priority input available", +#endif +#if defined (SIGPOLL) && defined (POLL_HUP) + SIGPOLL, POLL_HUP, "POLL_HUP", "Device disconnected", +#endif + 0, 0, NULL, NULL +}; + +/* Translation table for errno values. See intro(2) in most UNIX systems + Programmers Reference Manuals. + + Note that some systems provide a function (strerror) that returns the + error message string, or a global variable that is the base address of the + array of character pointers. Perhaps we should try to make use of these + provided strings if they are present, but at least this is more portable. + (FIXME?) */ + +static struct trans errno_table[] = +{ +#if defined (EPERM) + EPERM, "EPERM", "Not super-user", +#endif +#if defined (ENOENT) + ENOENT, "ENOENT", "No such file or directory", +#endif +#if defined (ESRCH) + ESRCH, "ESRCH", "No such process", +#endif +#if defined (EINTR) + EINTR, "EINTR", "Interrupted system call", +#endif +#if defined (EIO) + EIO, "EIO", "I/O error", +#endif +#if defined (ENXIO) + ENXIO, "ENXIO", "No such device or address", +#endif +#if defined (E2BIG) + E2BIG, "E2BIG", "Arg list too long", +#endif +#if defined (ENOEXEC) + ENOEXEC, "ENOEXEC", "Exec format error", +#endif +#if defined (EBADF) + EBADF, "EBADF", "Bad file number", +#endif +#if defined (ECHILD) + ECHILD, "ECHILD", "No child process", +#endif +#if defined (EAGAIN) + EAGAIN, "EAGAIN", "No more processes", +#endif +#if defined (ENOMEM) + ENOMEM, "ENOMEM", "Not enough space", +#endif +#if defined (EACCES) + EACCES, "EACCES", "Permission denied", +#endif +#if defined (EFAULT) + EFAULT, "EFAULT", "Bad address", +#endif +#if defined (ENOTBLK) + ENOTBLK, "ENOTBLK", "Block device required", +#endif +#if defined (EBUSY) + EBUSY, "EBUSY", "Device busy", +#endif +#if defined (EEXIST) + EEXIST, "EEXIST", "File exists", +#endif +#if defined (EXDEV) + EXDEV, "EXDEV", "Cross-device link", +#endif +#if defined (ENODEV) + ENODEV, "ENODEV", "No such device", +#endif +#if defined (ENOTDIR) + ENOTDIR, "ENOTDIR", "Not a directory", +#endif +#if defined (EISDIR) + EISDIR, "EISDIR", "Is a directory", +#endif +#if defined (EINVAL) + EINVAL, "EINVAL", "Invalid argument", +#endif +#if defined (ENFILE) + ENFILE, "ENFILE", "File table overflow", +#endif +#if defined (EMFILE) + EMFILE, "EMFILE", "Too many open files", +#endif +#if defined (ENOTTY) + ENOTTY, "ENOTTY", "Not a typewriter", +#endif +#if defined (ETXTBSY) + ETXTBSY, "ETXTBSY", "Text file busy", +#endif +#if defined (EFBIG) + EFBIG, "EFBIG", "File too large", +#endif +#if defined (ENOSPC) + ENOSPC, "ENOSPC", "No space left on device", +#endif +#if defined (ESPIPE) + ESPIPE, "ESPIPE", "Illegal seek", +#endif +#if defined (EROFS) + EROFS, "EROFS", "Read only file system", +#endif +#if defined (EMLINK) + EMLINK, "EMLINK", "Too many links", +#endif +#if defined (EPIPE) + EPIPE, "EPIPE", "Broken pipe", +#endif +#if defined (EDOM) + EDOM, "EDOM", "Math argument out of domain of func", +#endif +#if defined (ERANGE) + ERANGE, "ERANGE", "Math result not representable", +#endif +#if defined (ENOMSG) + ENOMSG, "ENOMSG", "No message of desired type", +#endif +#if defined (EIDRM) + EIDRM, "EIDRM", "Identifier removed", +#endif +#if defined (ECHRNG) + ECHRNG, "ECHRNG", "Channel number out of range", +#endif +#if defined (EL2NSYNC) + EL2NSYNC, "EL2NSYNC", "Level 2 not synchronized", +#endif +#if defined (EL3HLT) + EL3HLT, "EL3HLT", "Level 3 halted", +#endif +#if defined (EL3RST) + EL3RST, "EL3RST", "Level 3 reset", +#endif +#if defined (ELNRNG) + ELNRNG, "ELNRNG", "Link number out of range", +#endif +#if defined (EUNATCH) + EUNATCH, "EUNATCH", "Protocol driver not attached", +#endif +#if defined (ENOCSI) + ENOCSI, "ENOCSI", "No CSI structure available", +#endif +#if defined (EL2HLT) + EL2HLT, "EL2HLT", "Level 2 halted", +#endif +#if defined (EDEADLK) + EDEADLK, "EDEADLK", "Deadlock condition", +#endif +#if defined (ENOLCK) + ENOLCK, "ENOLCK", "No record locks available", +#endif +#if defined (EBADE) + EBADE, "EBADE", "Invalid exchange", +#endif +#if defined (EBADR) + EBADR, "EBADR", "Invalid request descriptor", +#endif +#if defined (EXFULL) + EXFULL, "EXFULL", "Exchange full", +#endif +#if defined (ENOANO) + ENOANO, "ENOANO", "No anode", +#endif +#if defined (EBADRQC) + EBADRQC, "EBADRQC", "Invalid request code", +#endif +#if defined (EBADSLT) + EBADSLT, "EBADSLT", "Invalid slot", +#endif +#if defined (EDEADLOCK) + EDEADLOCK, "EDEADLOCK", "File locking deadlock error", +#endif +#if defined (EBFONT) + EBFONT, "EBFONT", "Bad font file fmt", +#endif +#if defined (ENOSTR) + ENOSTR, "ENOSTR", "Device not a stream", +#endif +#if defined (ENODATA) + ENODATA, "ENODATA", "No data available", +#endif +#if defined (ETIME) + ETIME, "ETIME", "Timer expired", +#endif +#if defined (ENOSR) + ENOSR, "ENOSR", "Out of streams resources", +#endif +#if defined (ENONET) + ENONET, "ENONET", "Machine is not on the network", +#endif +#if defined (ENOPKG) + ENOPKG, "ENOPKG", "Package not installed", +#endif +#if defined (EREMOTE) + EREMOTE, "EREMOTE", "Object is remote", +#endif +#if defined (ENOLINK) + ENOLINK, "ENOLINK", "Link has been severed", +#endif +#if defined (EADV) + EADV, "EADV", "Advertise error", +#endif +#if defined (ESRMNT) + ESRMNT, "ESRMNT", "Srmount error", +#endif +#if defined (ECOMM) + ECOMM, "ECOMM", "Communication error on send", +#endif +#if defined (EPROTO) + EPROTO, "EPROTO", "Protocol error", +#endif +#if defined (EMULTIHOP) + EMULTIHOP, "EMULTIHOP", "Multihop attempted", +#endif +#if defined (EDOTDOT) + EDOTDOT, "EDOTDOT", "RFS specific error", +#endif +#if defined (EBADMSG) + EBADMSG, "EBADMSG", "Not a data message", +#endif +#if defined (ENAMETOOLONG) + ENAMETOOLONG, "ENAMETOOLONG", "File name too long", +#endif +#if defined (EOVERFLOW) + EOVERFLOW, "EOVERFLOW", "Value too large for defined data type", +#endif +#if defined (ENOTUNIQ) + ENOTUNIQ, "ENOTUNIQ", "Name not unique on network", +#endif +#if defined (EBADFD) + EBADFD, "EBADFD", "File descriptor in bad state", +#endif +#if defined (EREMCHG) + EREMCHG, "EREMCHG", "Remote address changed", +#endif +#if defined (ELIBACC) + ELIBACC, "ELIBACC", "Cannot access a needed shared library", +#endif +#if defined (ELIBBAD) + ELIBBAD, "ELIBBAD", "Accessing a corrupted shared library", +#endif +#if defined (ELIBSCN) + ELIBSCN, "ELIBSCN", ".lib section in a.out corrupted", +#endif +#if defined (ELIBMAX) + ELIBMAX, "ELIBMAX", "Attempting to link in too many shared libraries", +#endif +#if defined (ELIBEXEC) + ELIBEXEC, "ELIBEXEC", "Cannot exec a shared library directly", +#endif +#if defined (EILSEQ) + EILSEQ, "EILSEQ", "Illegal byte sequence", +#endif +#if defined (ENOSYS) + ENOSYS, "ENOSYS", "Operation not applicable", +#endif +#if defined (ELOOP) + ELOOP, "ELOOP", "Too many symbolic links encountered", +#endif +#if defined (ERESTART) + ERESTART, "ERESTART", "Interrupted system call should be restarted", +#endif +#if defined (ESTRPIPE) + ESTRPIPE, "ESTRPIPE", "Streams pipe error", +#endif +#if defined (ENOTEMPTY) + ENOTEMPTY, "ENOTEMPTY", "Directory not empty", +#endif +#if defined (EUSERS) + EUSERS, "EUSERS", "Too many users", +#endif +#if defined (ENOTSOCK) + ENOTSOCK, "ENOTSOCK", "Socket operation on non-socket", +#endif +#if defined (EDESTADDRREQ) + EDESTADDRREQ, "EDESTADDRREQ", "Destination address required", +#endif +#if defined (EMSGSIZE) + EMSGSIZE, "EMSGSIZE", "Message too long", +#endif +#if defined (EPROTOTYPE) + EPROTOTYPE, "EPROTOTYPE", "Protocol wrong type for socket", +#endif +#if defined (ENOPROTOOPT) + ENOPROTOOPT, "ENOPROTOOPT", "Protocol not available", +#endif +#if defined (EPROTONOSUPPORT) + EPROTONOSUPPORT, "EPROTONOSUPPORT", "Protocol not supported", +#endif +#if defined (ESOCKTNOSUPPORT) + ESOCKTNOSUPPORT, "ESOCKTNOSUPPORT", "Socket type not supported", +#endif +#if defined (EOPNOTSUPP) + EOPNOTSUPP, "EOPNOTSUPP", "Operation not supported on transport endpoint ", +#endif +#if defined (EPFNOSUPPORT) + EPFNOSUPPORT, "EPFNOSUPPORT", "Protocol family not supported", +#endif +#if defined (EAFNOSUPPORT) + EAFNOSUPPORT, "EAFNOSUPPORT", "Address family not supported by protocol", +#endif +#if defined (EADDRINUSE) + EADDRINUSE, "EADDRINUSE", "Address already in use", +#endif +#if defined (EADDRNOTAVAIL) + EADDRNOTAVAIL, "EADDRNOTAVAIL","Cannot assign requested address", +#endif +#if defined (ENETDOWN) + ENETDOWN, "ENETDOWN", "Network is down", +#endif +#if defined (ENETUNREACH) + ENETUNREACH, "ENETUNREACH", "Network is unreachable", +#endif +#if defined (ENETRESET) + ENETRESET, "ENETRESET", "Network dropped connection because of reset", +#endif +#if defined (ECONNABORTED) + ECONNABORTED, "ECONNABORTED", "Software caused connection abort", +#endif +#if defined (ECONNRESET) + ECONNRESET, "ECONNRESET", "Connection reset by peer", +#endif +#if defined (ENOBUFS) + ENOBUFS, "ENOBUFS", "No buffer space available", +#endif +#if defined (EISCONN) + EISCONN, "EISCONN", "Transport endpoint is already connected", +#endif +#if defined (ENOTCONN) + ENOTCONN, "ENOTCONN", "Transport endpoint is not connected", +#endif +#if defined (ESHUTDOWN) + ESHUTDOWN, "ESHUTDOWN", "Cannot send after transport endpoint shutdown", +#endif +#if defined (ETOOMANYREFS) + ETOOMANYREFS, "ETOOMANYREFS", "Too many references: cannot splice", +#endif +#if defined (ETIMEDOUT) + ETIMEDOUT, "ETIMEDOUT", "Connection timed out", +#endif +#if defined (ECONNREFUSED) + ECONNREFUSED, "ECONNREFUSED", "Connection refused", +#endif +#if defined (EHOSTDOWN) + EHOSTDOWN, "EHOSTDOWN", "Host is down", +#endif +#if defined (EHOSTUNREACH) + EHOSTUNREACH, "EHOSTUNREACH", "No route to host", +#endif +#if defined (EWOULDBLOCK) + EWOULDBLOCK, "EWOULDBLOCK", "Operation already in progress", +#endif +#if defined (EINPROGRESS) + EINPROGRESS, "EINPROGRESS", "Operation now in progress", +#endif +#if defined (ESTALE) + ESTALE, "ESTALE", "Stale NFS file handle", +#endif +#if defined (EUCLEAN) + EUCLEAN, "EUCLEAN", "Structure needs cleaning", +#endif +#if defined (ENOTNAM) + ENOTNAM, "ENOTNAM", "Not a XENIX named type file", +#endif +#if defined (ENAVAIL) + ENAVAIL, "ENAVAIL", "No XENIX semaphores available", +#endif +#if defined (EISNAM) + EISNAM, "EISNAM", "Is a named type file", +#endif +#if defined (EREMOTEIO) + EREMOTEIO, "EREMOTEIO", "Remote I/O error", +#endif + 0, NULL, NULL +}; + +static char *syscall_table[MAX_SYSCALLS]; + /* Prototypes for local functions */ static void set_proc_siginfo PARAMS ((struct procinfo *, int)); +static void +init_syscall_table PARAMS ((void)); + +static char * +syscallname PARAMS ((int)); + +static char * +signalname PARAMS ((int)); + static int proc_address_to_fd PARAMS ((CORE_ADDR, int)); @@ -100,14 +728,38 @@ static void proc_init_failed PARAMS ((char *)); static void -proc_info PARAMS ((char *, int)); +info_proc PARAMS ((char *, int)); + +static void +info_proc_flags PARAMS ((struct procinfo *, int)); + +static void +info_proc_stop PARAMS ((struct procinfo *, int)); static void -proc_info_address_map PARAMS ((struct procinfo *, int)); +info_proc_siginfo PARAMS ((struct procinfo *, int)); + +static void +info_proc_syscalls PARAMS ((struct procinfo *, int)); + +static void +info_proc_mappings PARAMS ((struct procinfo *, int)); + +static void +info_proc_signals PARAMS ((struct procinfo *, int)); + +static void +info_proc_faults PARAMS ((struct procinfo *, int)); static char * mappingflags PARAMS ((long)); +static char * +lookupname PARAMS ((struct trans *, unsigned int, char *)); + +static char * +lookupdesc PARAMS ((struct trans *, unsigned int)); + /* External function prototypes that can't be easily included in any header file because the args are typedefs in system include files. */ @@ -123,6 +775,585 @@ supply_fpregset PARAMS ((fpregset_t *)); extern void fill_fpregset PARAMS ((fpregset_t *, int)); +/* + +LOCAL FUNCTION + + lookupdesc -- translate a value to a summary desc string + +SYNOPSIS + + static char *lookupdesc (struct trans *transp, unsigned int val); + +DESCRIPTION + + Given a pointer to a translation table and a value to be translated, + lookup the desc string and return it. + */ + +static char * +lookupdesc (transp, val) + struct trans *transp; + unsigned int val; +{ + char *desc; + + for (desc = NULL; transp -> name != NULL; transp++) + { + if (transp -> value == val) + { + desc = transp -> desc; + break; + } + } + + /* Didn't find a translation for the specified value, set a default one. */ + + if (desc == NULL) + { + desc = "Unknown"; + } + return (desc); +} + +/* + +LOCAL FUNCTION + + lookupname -- translate a value to symbolic name + +SYNOPSIS + + static char *lookupname (struct trans *transp, unsigned int val, + char *prefix); + +DESCRIPTION + + Given a pointer to a translation table, a value to be translated, + and a default prefix to return if the value can't be translated, + match the value with one of the translation table entries and + return a pointer to the symbolic name. + + If no match is found it just returns the value as a printable string, + with the given prefix. The previous such value, if any, is freed + at this time. + */ + +static char * +lookupname (transp, val, prefix) + struct trans *transp; + unsigned int val; + char *prefix; +{ + static char *locbuf; + char *name; + + for (name = NULL; transp -> name != NULL; transp++) + { + if (transp -> value == val) + { + name = transp -> name; + break; + } + } + + /* Didn't find a translation for the specified value, build a default + one using the specified prefix and return it. The lifetime of + the value is only until the next one is needed. */ + + if (name == NULL) + { + if (locbuf != NULL) + { + free (locbuf); + } + locbuf = xmalloc (strlen (prefix) + 16); + (void) sprintf (locbuf, "%s %u", prefix, val); + name = locbuf; + } + return (name); +} + +static char * +sigcodename (sip) + siginfo_t *sip; +{ + struct sigcode *scp; + char *name = NULL; + static char locbuf[32]; + + for (scp = siginfo_table; scp -> codename != NULL; scp++) + { + if ((scp -> signo == sip -> si_signo) && + (scp -> code == sip -> si_code)) + { + name = scp -> codename; + break; + } + } + if (name == NULL) + { + (void) sprintf (locbuf, "sigcode %u", sip -> si_signo); + name = locbuf; + } + return (name); +} + +static char *sigcodedesc (sip) + siginfo_t *sip; +{ + struct sigcode *scp; + char *desc = NULL; + + for (scp = siginfo_table; scp -> codename != NULL; scp++) + { + if ((scp -> signo == sip -> si_signo) && + (scp -> code == sip -> si_code)) + { + desc = scp -> desc; + break; + } + } + if (desc == NULL) + { + desc = "Unrecognized signal or trap use"; + } + return (desc); +} + +/* + +LOCAL FUNCTION + + syscallname - translate a system call number into a system call name + +SYNOPSIS + + char *syscallname (int syscallnum) + +DESCRIPTION + + Given a system call number, translate it into the printable name + of a system call, or into "syscall " if it is an unknown + number. + */ + +static char * +syscallname (syscallnum) + int syscallnum; +{ + static char locbuf[32]; + char *rtnval; + + if (syscallnum >= 0 && syscallnum < MAX_SYSCALLS) + { + rtnval = syscall_table[syscallnum]; + } + else + { + (void) sprintf (locbuf, "syscall %u", syscallnum); + rtnval = locbuf; + } + return (rtnval); +} + +/* + +LOCAL FUNCTION + + init_syscall_table - initialize syscall translation table + +SYNOPSIS + + void init_syscall_table (void) + +DESCRIPTION + + Dynamically initialize the translation table to convert system + call numbers into printable system call names. Done once per + gdb run, on initialization. + +NOTES + + This is awfully ugly, but preprocessor tricks to make it prettier + tend to be nonportable. + */ + +static void +init_syscall_table () +{ + int syscallnum; + +#if defined (SYS_exit) + syscall_table[SYS_exit] = "exit"; +#endif +#if defined (SYS_fork) + syscall_table[SYS_fork] = "fork"; +#endif +#if defined (SYS_read) + syscall_table[SYS_read] = "read"; +#endif +#if defined (SYS_write) + syscall_table[SYS_write] = "write"; +#endif +#if defined (SYS_open) + syscall_table[SYS_open] = "open"; +#endif +#if defined (SYS_close) + syscall_table[SYS_close] = "close"; +#endif +#if defined (SYS_wait) + syscall_table[SYS_wait] = "wait"; +#endif +#if defined (SYS_creat) + syscall_table[SYS_creat] = "creat"; +#endif +#if defined (SYS_link) + syscall_table[SYS_link] = "link"; +#endif +#if defined (SYS_unlink) + syscall_table[SYS_unlink] = "unlink"; +#endif +#if defined (SYS_exec) + syscall_table[SYS_exec] = "exec"; +#endif +#if defined (SYS_execv) + syscall_table[SYS_execv] = "execv"; +#endif +#if defined (SYS_execve) + syscall_table[SYS_execve] = "execve"; +#endif +#if defined (SYS_chdir) + syscall_table[SYS_chdir] = "chdir"; +#endif +#if defined (SYS_time) + syscall_table[SYS_time] = "time"; +#endif +#if defined (SYS_mknod) + syscall_table[SYS_mknod] = "mknod"; +#endif +#if defined (SYS_chmod) + syscall_table[SYS_chmod] = "chmod"; +#endif +#if defined (SYS_chown) + syscall_table[SYS_chown] = "chown"; +#endif +#if defined (SYS_brk) + syscall_table[SYS_brk] = "brk"; +#endif +#if defined (SYS_stat) + syscall_table[SYS_stat] = "stat"; +#endif +#if defined (SYS_lseek) + syscall_table[SYS_lseek] = "lseek"; +#endif +#if defined (SYS_getpid) + syscall_table[SYS_getpid] = "getpid"; +#endif +#if defined (SYS_mount) + syscall_table[SYS_mount] = "mount"; +#endif +#if defined (SYS_umount) + syscall_table[SYS_umount] = "umount"; +#endif +#if defined (SYS_setuid) + syscall_table[SYS_setuid] = "setuid"; +#endif +#if defined (SYS_getuid) + syscall_table[SYS_getuid] = "getuid"; +#endif +#if defined (SYS_stime) + syscall_table[SYS_stime] = "stime"; +#endif +#if defined (SYS_ptrace) + syscall_table[SYS_ptrace] = "ptrace"; +#endif +#if defined (SYS_alarm) + syscall_table[SYS_alarm] = "alarm"; +#endif +#if defined (SYS_fstat) + syscall_table[SYS_fstat] = "fstat"; +#endif +#if defined (SYS_pause) + syscall_table[SYS_pause] = "pause"; +#endif +#if defined (SYS_utime) + syscall_table[SYS_utime] = "utime"; +#endif +#if defined (SYS_stty) + syscall_table[SYS_stty] = "stty"; +#endif +#if defined (SYS_gtty) + syscall_table[SYS_gtty] = "gtty"; +#endif +#if defined (SYS_access) + syscall_table[SYS_access] = "access"; +#endif +#if defined (SYS_nice) + syscall_table[SYS_nice] = "nice"; +#endif +#if defined (SYS_statfs) + syscall_table[SYS_statfs] = "statfs"; +#endif +#if defined (SYS_sync) + syscall_table[SYS_sync] = "sync"; +#endif +#if defined (SYS_kill) + syscall_table[SYS_kill] = "kill"; +#endif +#if defined (SYS_fstatfs) + syscall_table[SYS_fstatfs] = "fstatfs"; +#endif +#if defined (SYS_pgrpsys) + syscall_table[SYS_pgrpsys] = "pgrpsys"; +#endif +#if defined (SYS_xenix) + syscall_table[SYS_xenix] = "xenix"; +#endif +#if defined (SYS_dup) + syscall_table[SYS_dup] = "dup"; +#endif +#if defined (SYS_pipe) + syscall_table[SYS_pipe] = "pipe"; +#endif +#if defined (SYS_times) + syscall_table[SYS_times] = "times"; +#endif +#if defined (SYS_profil) + syscall_table[SYS_profil] = "profil"; +#endif +#if defined (SYS_plock) + syscall_table[SYS_plock] = "plock"; +#endif +#if defined (SYS_setgid) + syscall_table[SYS_setgid] = "setgid"; +#endif +#if defined (SYS_getgid) + syscall_table[SYS_getgid] = "getgid"; +#endif +#if defined (SYS_signal) + syscall_table[SYS_signal] = "signal"; +#endif +#if defined (SYS_msgsys) + syscall_table[SYS_msgsys] = "msgsys"; +#endif +#if defined (SYS_sys3b) + syscall_table[SYS_sys3b] = "sys3b"; +#endif +#if defined (SYS_acct) + syscall_table[SYS_acct] = "acct"; +#endif +#if defined (SYS_shmsys) + syscall_table[SYS_shmsys] = "shmsys"; +#endif +#if defined (SYS_semsys) + syscall_table[SYS_semsys] = "semsys"; +#endif +#if defined (SYS_ioctl) + syscall_table[SYS_ioctl] = "ioctl"; +#endif +#if defined (SYS_uadmin) + syscall_table[SYS_uadmin] = "uadmin"; +#endif +#if defined (SYS_utssys) + syscall_table[SYS_utssys] = "utssys"; +#endif +#if defined (SYS_fsync) + syscall_table[SYS_fsync] = "fsync"; +#endif +#if defined (SYS_umask) + syscall_table[SYS_umask] = "umask"; +#endif +#if defined (SYS_chroot) + syscall_table[SYS_chroot] = "chroot"; +#endif +#if defined (SYS_fcntl) + syscall_table[SYS_fcntl] = "fcntl"; +#endif +#if defined (SYS_ulimit) + syscall_table[SYS_ulimit] = "ulimit"; +#endif +#if defined (SYS_rfsys) + syscall_table[SYS_rfsys] = "rfsys"; +#endif +#if defined (SYS_rmdir) + syscall_table[SYS_rmdir] = "rmdir"; +#endif +#if defined (SYS_mkdir) + syscall_table[SYS_mkdir] = "mkdir"; +#endif +#if defined (SYS_getdents) + syscall_table[SYS_getdents] = "getdents"; +#endif +#if defined (SYS_sysfs) + syscall_table[SYS_sysfs] = "sysfs"; +#endif +#if defined (SYS_getmsg) + syscall_table[SYS_getmsg] = "getmsg"; +#endif +#if defined (SYS_putmsg) + syscall_table[SYS_putmsg] = "putmsg"; +#endif +#if defined (SYS_poll) + syscall_table[SYS_poll] = "poll"; +#endif +#if defined (SYS_lstat) + syscall_table[SYS_lstat] = "lstat"; +#endif +#if defined (SYS_symlink) + syscall_table[SYS_symlink] = "symlink"; +#endif +#if defined (SYS_readlink) + syscall_table[SYS_readlink] = "readlink"; +#endif +#if defined (SYS_setgroups) + syscall_table[SYS_setgroups] = "setgroups"; +#endif +#if defined (SYS_getgroups) + syscall_table[SYS_getgroups] = "getgroups"; +#endif +#if defined (SYS_fchmod) + syscall_table[SYS_fchmod] = "fchmod"; +#endif +#if defined (SYS_fchown) + syscall_table[SYS_fchown] = "fchown"; +#endif +#if defined (SYS_sigprocmask) + syscall_table[SYS_sigprocmask] = "sigprocmask"; +#endif +#if defined (SYS_sigsuspend) + syscall_table[SYS_sigsuspend] = "sigsuspend"; +#endif +#if defined (SYS_sigaltstack) + syscall_table[SYS_sigaltstack] = "sigaltstack"; +#endif +#if defined (SYS_sigaction) + syscall_table[SYS_sigaction] = "sigaction"; +#endif +#if defined (SYS_sigpending) + syscall_table[SYS_sigpending] = "sigpending"; +#endif +#if defined (SYS_context) + syscall_table[SYS_context] = "context"; +#endif +#if defined (SYS_evsys) + syscall_table[SYS_evsys] = "evsys"; +#endif +#if defined (SYS_evtrapret) + syscall_table[SYS_evtrapret] = "evtrapret"; +#endif +#if defined (SYS_statvfs) + syscall_table[SYS_statvfs] = "statvfs"; +#endif +#if defined (SYS_fstatvfs) + syscall_table[SYS_fstatvfs] = "fstatvfs"; +#endif +#if defined (SYS_nfssys) + syscall_table[SYS_nfssys] = "nfssys"; +#endif +#if defined (SYS_waitsys) + syscall_table[SYS_waitsys] = "waitsys"; +#endif +#if defined (SYS_sigsendsys) + syscall_table[SYS_sigsendsys] = "sigsendsys"; +#endif +#if defined (SYS_hrtsys) + syscall_table[SYS_hrtsys] = "hrtsys"; +#endif +#if defined (SYS_acancel) + syscall_table[SYS_acancel] = "acancel"; +#endif +#if defined (SYS_async) + syscall_table[SYS_async] = "async"; +#endif +#if defined (SYS_priocntlsys) + syscall_table[SYS_priocntlsys] = "priocntlsys"; +#endif +#if defined (SYS_pathconf) + syscall_table[SYS_pathconf] = "pathconf"; +#endif +#if defined (SYS_mincore) + syscall_table[SYS_mincore] = "mincore"; +#endif +#if defined (SYS_mmap) + syscall_table[SYS_mmap] = "mmap"; +#endif +#if defined (SYS_mprotect) + syscall_table[SYS_mprotect] = "mprotect"; +#endif +#if defined (SYS_munmap) + syscall_table[SYS_munmap] = "munmap"; +#endif +#if defined (SYS_fpathconf) + syscall_table[SYS_fpathconf] = "fpathconf"; +#endif +#if defined (SYS_vfork) + syscall_table[SYS_vfork] = "vfork"; +#endif +#if defined (SYS_fchdir) + syscall_table[SYS_fchdir] = "fchdir"; +#endif +#if defined (SYS_readv) + syscall_table[SYS_readv] = "readv"; +#endif +#if defined (SYS_writev) + syscall_table[SYS_writev] = "writev"; +#endif +#if defined (SYS_xstat) + syscall_table[SYS_xstat] = "xstat"; +#endif +#if defined (SYS_lxstat) + syscall_table[SYS_lxstat] = "lxstat"; +#endif +#if defined (SYS_fxstat) + syscall_table[SYS_fxstat] = "fxstat"; +#endif +#if defined (SYS_xmknod) + syscall_table[SYS_xmknod] = "xmknod"; +#endif +#if defined (SYS_clocal) + syscall_table[SYS_clocal] = "clocal"; +#endif +#if defined (SYS_setrlimit) + syscall_table[SYS_setrlimit] = "setrlimit"; +#endif +#if defined (SYS_getrlimit) + syscall_table[SYS_getrlimit] = "getrlimit"; +#endif +#if defined (SYS_lchown) + syscall_table[SYS_lchown] = "lchown"; +#endif +#if defined (SYS_memcntl) + syscall_table[SYS_memcntl] = "memcntl"; +#endif +#if defined (SYS_getpmsg) + syscall_table[SYS_getpmsg] = "getpmsg"; +#endif +#if defined (SYS_putpmsg) + syscall_table[SYS_putpmsg] = "putpmsg"; +#endif +#if defined (SYS_rename) + syscall_table[SYS_rename] = "rename"; +#endif +#if defined (SYS_uname) + syscall_table[SYS_uname] = "uname"; +#endif +#if defined (SYS_setegid) + syscall_table[SYS_setegid] = "setegid"; +#endif +#if defined (SYS_sysconfig) + syscall_table[SYS_sysconfig] = "sysconfig"; +#endif +#if defined (SYS_adjtime) + syscall_table[SYS_adjtime] = "adjtime"; +#endif +#if defined (SYS_systeminfo) + syscall_table[SYS_systeminfo] = "systeminfo"; +#endif +#if defined (SYS_seteuid) + syscall_table[SYS_seteuid] = "seteuid"; +#endif +} /* @@ -397,6 +1628,7 @@ NOTES If proc_init_failed ever gets called, control returns to the command processing loop via the standard error handling code. + */ void @@ -409,18 +1641,15 @@ inferior_proc_init (pid) } else { - (void) memset (&pi.prrun, 0, sizeof (pi.prrun)); + (void) memset ((char *) &pi.prrun, 0, sizeof (pi.prrun)); prfillset (&pi.prrun.pr_trace); + proc_signal_handling_change (); 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, PIOCSTRACE, &pi.prrun.pr_trace) < 0) - { - proc_init_failed ("PIOCSTRACE failed"); - } else if (ioctl (pi.fd, PIOCSFAULT, &pi.prrun.pr_fault) < 0) { proc_init_failed ("PIOCSFAULT failed"); @@ -430,6 +1659,58 @@ inferior_proc_init (pid) /* +GLOBAL FUNCTION + + proc_signal_handling_change + +SYNOPSIS + + void proc_signal_handling_change (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. + */ + +void +proc_signal_handling_change () +{ + 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); + } + } +} + +/* + GLOBAL FUNCTION proc_set_exec_trap -- arrange for exec'd child to halt at startup @@ -453,6 +1734,10 @@ 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. */ void @@ -471,12 +1756,11 @@ proc_set_exec_trap () } 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. - */ + /* 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 @@ -493,6 +1777,21 @@ proc_set_exec_trap () fflush (stderr); _exit (127); } + + /* Turn off inherit-on-fork flag so that all grand-children of gdb + start with tracing flags cleared. */ + +#ifdef PIOCRFORK /* Standard SVR4 */ + (void) ioctl (fd, PIOCRFORK, NULL); +#else +#ifdef PIOCRESET /* iris (for example) */ + { + long pr_flags; + pr_flags = PR_FORK; + (void) ioctl (fd, PIOCRESET, &pr_flags); + } +#endif +#endif } /* @@ -567,7 +1866,7 @@ DESCRIPTION CORE_ADDR proc_base_address (addr) -CORE_ADDR addr; + CORE_ADDR addr; { int nmap; struct prmap *prmaps; @@ -597,7 +1896,7 @@ CORE_ADDR addr; /* -GLOBAL_FUNCTION +LOCAL FUNCTION proc_address_to_fd -- return open fd for file mapped to address @@ -704,15 +2003,17 @@ attach (pid) /* Remember some things about the inferior that we will, or might, change so that we can restore them when we detach. */ - (void) ioctl (pi.fd, PIOCGTRACE, &pi.trace); - (void) ioctl (pi.fd, PIOCGFAULT, &pi.fltset); - (void) ioctl (pi.fd, PIOCGENTRY, &pi.entryset); - (void) ioctl (pi.fd, PIOCGEXIT, &pi.exitset); + (void) ioctl (pi.fd, PIOCGTRACE, &pi.saved_trace); + (void) ioctl (pi.fd, PIOCGHOLD, &pi.saved_sighold); + (void) ioctl (pi.fd, PIOCGFAULT, &pi.saved_fltset); + (void) ioctl (pi.fd, PIOCGENTRY, &pi.saved_entryset); + (void) ioctl (pi.fd, PIOCGEXIT, &pi.saved_exitset); /* Set up trace and fault sets, as gdb expects them. */ (void) memset (&pi.prrun, 0, sizeof (pi.prrun)); prfillset (&pi.prrun.pr_trace); + proc_signal_handling_change (); prfillset (&pi.prrun.pr_fault); prdelset (&pi.prrun.pr_fault, FLTPAGE); if (ioctl (pi.fd, PIOCSFAULT, &pi.prrun.pr_fault)) @@ -764,22 +2065,27 @@ detach (signal) { set_proc_siginfo (&pi, signal); } - if (ioctl (pi.fd, PIOCSEXIT, &pi.exitset) < 0) + 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.entryset) < 0) + 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.trace) < 0) + if (ioctl (pi.fd, PIOCSTRACE, &pi.saved_trace) < 0) { print_sys_errmsg (pi.pathname, errno); printf ("PIOCSTRACE failed.\n"); } - if (ioctl (pi.fd, PIOCSFAULT, &pi.fltset) < 0) + 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"); @@ -1012,8 +2318,8 @@ DESCRIPTION static void set_proc_siginfo (pip, signo) - struct procinfo *pip; - int signo; + struct procinfo *pip; + int signo; { struct siginfo newsiginfo; struct siginfo *sip; @@ -1050,7 +2356,7 @@ GLOBAL FUNCTION SYNOPSIS - void child_resume (int step, int signal) + void child_resume (int step, int signo) DESCRIPTION @@ -1068,16 +2374,16 @@ NOTE */ void -child_resume (step, signal) +child_resume (step, signo) int step; - int signal; + int signo; { errno = 0; pi.prrun.pr_flags = PRSVADDR | PRSTRACE | PRSFAULT | PRCFAULT; pi.prrun.pr_vaddr = (caddr_t) *(int *) ®isters[REGISTER_BYTE (PC_REGNUM)]; - if (signal) + if (signo) { - set_proc_siginfo (&pi, signal); + set_proc_siginfo (&pi, signo); } else { @@ -1154,10 +2460,10 @@ NOTES 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 */ + char *core_reg_sect; + unsigned core_reg_size; + int which; + unsigned int reg_addr; /* Unused in this version */ { if (which == 0) @@ -1296,12 +2602,8 @@ open_proc_file (pid, pip) sprintf (pip -> pathname, PROC_NAME_FMT, pid); if ((pip -> fd = open (pip -> pathname, O_RDWR)) >= 0) { - long pr_flags; - pip -> valid = 1; pip -> pid = pid; - pr_flags = PR_FORK; - (void) ioctl (pip -> fd, PIOCRESET, &pr_flags); } return (pip -> valid); } @@ -1323,49 +2625,428 @@ mappingflags (flags) } static void -proc_info_address_map (pip, verbose) +info_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 void +info_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), + sys_siglist[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 void +info_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 ", lookupname (errno_table, + sip -> si_errno, "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), + sys_siglist[sip -> si_signo]); + if (sip -> si_errno > 0) + { + printf_filtered ("\t%-16s %s.\n", + lookupname (errno_table, + sip -> si_errno, "errno"), + lookupdesc (errno_table, 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 void +info_proc_syscalls (pip, summary) + struct procinfo *pip; + int summary; +{ + int syscallnum; + + if (!summary) + { + +#if 0 /* FIXME: Needs to use gdb-wide configured info about system calls. */ + if (pip -> prstatus.pr_flags & PR_ASLEEP) + { + int syscallnum = pip -> prstatus.pr_reg[R_D0]; + if (summary) + { + printf_filtered ("%-32s", "Sleeping in system call:"); + printf_filtered ("%s", syscallname (syscallnum)); + } + else + { + printf_filtered ("Sleeping in system call '%s'.\n", + syscallname (syscallnum)); + } + } +#endif + + if (ioctl (pip -> fd, PIOCGENTRY, &pip -> entryset) < 0) + { + print_sys_errmsg (pip -> pathname, errno); + error ("PIOCGENTRY failed"); + } + + if (ioctl (pip -> fd, PIOCGEXIT, &pip -> exitset) < 0) + { + print_sys_errmsg (pip -> pathname, errno); + error ("PIOCGEXIT failed"); + } + + printf_filtered ("System call tracing information:\n\n"); + + printf_filtered ("\t%-12s %-8s %-8s\n", + "System call", + "Entry", + "Exit"); + for (syscallnum = 0; syscallnum < MAX_SYSCALLS; syscallnum++) + { + QUIT; + if (syscall_table[syscallnum] != NULL) + { + printf_filtered ("\t%-12s ", syscall_table[syscallnum]); + printf_filtered ("%-8s ", + prismember (&pip -> entryset, syscallnum) + ? "on" : "off"); + printf_filtered ("%-8s ", + prismember (&pip -> exitset, syscallnum) + ? "on" : "off"); + printf_filtered ("\n"); + } + } + printf_filtered ("\n"); + } +} + +static char * +signalname (signo) + int signo; +{ + char *abbrev; + static char locbuf[32]; + + abbrev = sig_abbrev (signo); + if (abbrev == NULL) + { + sprintf (locbuf, "signal %d", signo); + } + else + { + sprintf (locbuf, "SIG%s (%d)", abbrev, signo); + } + return (locbuf); +} + +static void +info_proc_signals (pip, summary) + struct procinfo *pip; + int summary; +{ + int signo; + + if (!summary) + { + if (ioctl (pip -> fd, PIOCGTRACE, &pip -> trace) < 0) + { + print_sys_errmsg (pip -> pathname, errno); + error ("PIOCGTRACE failed"); + } + + printf_filtered ("Disposition of signals:\n\n"); + printf_filtered ("\t%-15s %-8s %-8s %-8s %s\n\n", + "Signal", "Trace", "Hold", "Pending", "Description"); + for (signo = 0; signo < NSIG; signo++) + { + QUIT; + printf_filtered ("\t%-15s ", signalname (signo)); + printf_filtered ("%-8s ", + prismember (&pip -> trace, signo) + ? "on" : "off"); + printf_filtered ("%-8s ", + prismember (&pip -> prstatus.pr_sighold, signo) + ? "on" : "off"); + printf_filtered ("%-8s ", + prismember (&pip -> prstatus.pr_sigpend, signo) + ? "yes" : "no"); + printf_filtered (" %s\n", sys_siglist[signo]); + } + printf_filtered ("\n"); + } +} + +static void +info_proc_faults (pip, summary) + struct procinfo *pip; + int summary; +{ + struct trans *transp; + + if (!summary) + { + if (ioctl (pip -> fd, PIOCGFAULT, &pip -> fltset) < 0) + { + print_sys_errmsg (pip -> pathname, errno); + error ("PIOCGFAULT failed"); + } + + printf_filtered ("Current traced hardware fault set:\n\n"); + printf_filtered ("\t%-12s %-8s\n", "Fault", "Trace"); + + for (transp = faults_table; transp -> name != NULL; transp++) + { + QUIT; + printf_filtered ("\t%-12s ", transp -> name); + printf_filtered ("%-8s", prismember (&pip -> fltset, transp -> value) + ? "on" : "off"); + printf_filtered ("\n"); + } + printf_filtered ("\n"); + } +} + +static void +info_proc_mappings (pip, summary) struct procinfo *pip; - int verbose; + int summary; { int nmap; struct prmap *prmaps; struct prmap *prmap; - printf_filtered ("Mapped address spaces:\n\n"); - printf_filtered ("\t%10s %10s %10s %10s %6s\n", - "Start Addr", - " End Addr", - " Size", - " Offset", - "Flags"); - if (ioctl (pip -> fd, PIOCNMAP, &nmap) == 0) + if (!summary) { - prmaps = (struct prmap *) alloca ((nmap + 1) * sizeof (*prmaps)); - if (ioctl (pip -> fd, PIOCMAP, prmaps) == 0) + printf_filtered ("Mapped address spaces:\n\n"); + printf_filtered ("\t%10s %10s %10s %10s %6s\n", + "Start Addr", + " End Addr", + " Size", + " Offset", + "Flags"); + if (ioctl (pip -> fd, PIOCNMAP, &nmap) == 0) { - for (prmap = prmaps; prmap -> pr_size; ++prmap) + prmaps = (struct prmap *) alloca ((nmap + 1) * sizeof (*prmaps)); + if (ioctl (pip -> fd, PIOCMAP, prmaps) == 0) { - printf_filtered ("\t%#10x %#10x %#10x %#10x %6s\n", - prmap -> pr_vaddr, - prmap -> pr_vaddr + prmap -> pr_size - 1, - prmap -> pr_size, - prmap -> pr_off, - mappingflags (prmap -> pr_mflags)); + for (prmap = prmaps; prmap -> pr_size; ++prmap) + { + printf_filtered ("\t%#10x %#10x %#10x %#10x %6s\n", + prmap -> pr_vaddr, + prmap -> pr_vaddr + prmap -> pr_size - 1, + prmap -> pr_size, + prmap -> pr_off, + mappingflags (prmap -> pr_mflags)); + } } } + printf_filtered ("\n"); } - printf_filtered ("\n\n"); } /* LOCAL FUNCTION - proc_info -- implement the "info proc" command + info_proc -- implement the "info proc" command SYNOPSIS - void proc_info (char *args, int from_tty) + void info_proc (char *args, int from_tty) DESCRIPTION @@ -1374,24 +3055,39 @@ DESCRIPTION Examples of the use of "info proc" are: - info proc Print short info about current inferior. - info proc verbose Print verbose info about current inferior. - info proc 123 Print short info about process pid 123. - info proc 123 verbose Print verbose info about process pid 123. + info proc (prints summary info for current inferior) + info proc 123 (prints summary info for process with pid 123) + info proc mappings (prints address mappings) + info proc times (prints process/children times) + info proc id (prints pid, ppid, gid, sid, etc) + info proc status (prints general process state info) + info proc signals (prints info about signal handling) + info proc all (prints all info) */ static void -proc_info (args, from_tty) +info_proc (args, from_tty) char *args; int from_tty; { - int verbose = 0; int pid; struct procinfo pii; struct procinfo *pip; struct cleanup *old_chain; char *nexttok; + char **argv; + int argsize; + int summary = 1; + int flags = 0; + int syscalls = 0; + int signals = 0; + int faults = 0; + int mappings = 0; + int times = 0; + int id = 0; + int status = 0; + int all = 0; old_chain = make_cleanup (null_cleanup, 0); @@ -1399,20 +3095,63 @@ proc_info (args, from_tty) pip = π - /* Parse the args string, looking for "verbose" (or any abbrev) and - for a specific pid. If a specific pid is found, the process - file is opened. */ - if (args != NULL) { - while ((nexttok = strtok (args, " \t")) != NULL) + if ((argv = buildargv (args)) == NULL) { - args = NULL; - if (strncmp (nexttok, "verbose", strlen (nexttok)) == 0) + nomem (0); + } + make_cleanup (freeargv, (char *) argv); + + while (*argv != NULL) + { + argsize = strlen (*argv); + if (argsize >= 1 && strncmp (*argv, "all", argsize) == 0) + { + summary = 0; + all = 1; + } + else if (argsize >= 2 && strncmp (*argv, "faults", argsize) == 0) + { + summary = 0; + faults = 1; + } + else if (argsize >= 2 && strncmp (*argv, "flags", argsize) == 0) + { + summary = 0; + flags = 1; + } + else if (argsize >= 1 && strncmp (*argv, "id", argsize) == 0) + { + summary = 0; + id = 1; + } + else if (argsize >= 1 && strncmp (*argv, "mappings", argsize) == 0) + { + summary = 0; + mappings = 1; + } + else if (argsize >= 2 && strncmp (*argv, "signals", argsize) == 0) + { + summary = 0; + signals = 1; + } + else if (argsize >= 2 && strncmp (*argv, "status", argsize) == 0) + { + summary = 0; + status = 1; + } + else if (argsize >= 2 && strncmp (*argv, "syscalls", argsize) == 0) + { + summary = 0; + syscalls = 1; + } + else if (argsize >= 1 && strncmp (*argv, "times", argsize) == 0) { - verbose++; + summary = 0; + times = 1; } - else if ((pii.pid = atoi (nexttok)) > 0) + else if ((pii.pid = atoi (*argv)) > 0) { pid = pii.pid; pip = &pii; @@ -1424,6 +3163,11 @@ proc_info (args, from_tty) } make_cleanup (close_proc_file, pip); } + else if (**argv != '\000') + { + error ("Unrecognized or ambiguous keyword `%s'.", *argv); + } + argv++; } } @@ -1440,24 +3184,39 @@ proc_info (args, from_tty) error ("PIOCSTATUS failed"); } - printf_filtered ("\nStatus information for %s:\n\n", pip -> pathname); - proc_info_address_map (pip, verbose); -#if 0 - proc_info_flags (pip, verbose); - proc_info_why (pip, verbose); - proc_info_what (pip, verbose); - proc_info_info (pip, verbose); - proc_info_cursig (pip, verbose); - proc_info_sigpend (pip, verbose); - proc_info_sighold (pip, verbose); - proc_info_altstack (pip, verbose); - proc_info_action (pip, verbose); - proc_info_id (pip, verbose); - proc_info_times (pip, verbose); - proc_info_clname (pip,verbose); - proc_info_instr (pip, verbose); - proc_info_reg (pip, verbose); -#endif + /* Print verbose information of the requested type(s), or just a summary + of the information for all types. */ + + printf_filtered ("\nInformation for %s:\n\n", pip -> pathname); + if (summary || all || flags) + { + info_proc_flags (pip, summary); + } + if (summary || all) + { + info_proc_stop (pip, summary); + } + if (summary || all || signals || faults) + { + info_proc_siginfo (pip, summary); + } + if (summary || all || syscalls) + { + info_proc_syscalls (pip, summary); + } + if (summary || all || mappings) + { + info_proc_mappings (pip, summary); + } + if (summary || all || signals) + { + info_proc_signals (pip, summary); + } + if (summary || all || faults) + { + info_proc_faults (pip, summary); + } + printf_filtered ("\n"); /* All done, deal with closing any temporary process info structure, freeing temporary memory , etc. */ @@ -1483,13 +3242,18 @@ DESCRIPTION */ static char *proc_desc = -"Show current process status information using /proc entry.\n\ -With no arguments, prints short form. With 'verbose' prints long form."; +"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."; void _initialize_proc_fs () { - add_info ("proc", proc_info, proc_desc); + add_info ("proc", info_proc, proc_desc); + init_syscall_table (); } #endif /* USE_PROC_FS */ diff --git a/gdb/xm-irix4.h b/gdb/xm-irix4.h index e25a144a79f..e25b6be7381 100644 --- a/gdb/xm-irix4.h +++ b/gdb/xm-irix4.h @@ -42,9 +42,27 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ */ #define USE_PROC_FS #define PROC_NAME_FMT "/debug/%d" + +/* If we are using SVR4 /proc instead of ptrace, use CREATE_INFERIOR_HOOK + to do internal /proc initialization. */ +#ifdef USE_PROC_FS #define CREATE_INFERIOR_HOOK(pid) inferior_proc_init(pid) +#endif /* Irix defines psignal() in signal.h, which gets gcc rather angry at us * because their definition is markedly different. */ #define PSIGNAL_IN_SIGNAL_H + +/* If gdb's signal handling changes (due to a "handle" command), then + this macro expands to an action to perform to notify other parts of + gdb that might care, that signal handling has changed. For hosts using + the /proc interface, gdb has more control over which signals cause the + inferior to stop and which do not. In some cases, it is desirable to + have signals delivered directly to the inferior without involving the + debugger at all. */ +#ifdef USE_PROC_FS +#define NOTICE_SIGNAL_HANDLING_CHANGE proc_signal_handling_change() +#endif + +#define BROKEN_SIGINFO_H /* si_pid & si_uid are bogus */ diff --git a/gdb/xm-sysv4.h b/gdb/xm-sysv4.h index 35c831da320..c51c58dba5e 100644 --- a/gdb/xm-sysv4.h +++ b/gdb/xm-sysv4.h @@ -65,3 +65,15 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ /* Use setpgid(0,0) to run inferior in a separate process group */ #define NEED_POSIX_SETPGID + +/* If gdb's signal handling changes (due to a "handle" command), then + this macro expands to an action to perform to notify other parts of + gdb that might care, that signal handling has changed. For hosts using + the /proc interface, gdb has more control over which signals cause the + inferior to stop and which do not. In some cases, it is desirable to + have signals delivered directly to the inferior without involving the + debugger at all. */ + +#ifdef USE_PROC_FS +#define NOTICE_SIGNAL_HANDLING_CHANGE proc_signal_handling_change() +#endif