18 changed files with 3419 additions and 87 deletions
@ -0,0 +1,808 @@ |
|||
/* Machine independent support for SVR4 /proc (process file system) for GDB.
|
|||
Copyright 1999 Free Software Foundation, Inc. |
|||
Written by Michael Snyder at Cygnus Solutions. |
|||
Based on work by Fred Fish, Stu Grossman, Geoff Noer, and others. |
|||
|
|||
This file is part of GDB. |
|||
|
|||
This program is free software; you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation; either version 2 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
This program is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
|||
|
|||
/*
|
|||
* Pretty-print trace of api calls to the /proc api |
|||
* (ioctl or read/write calls). |
|||
* |
|||
*/ |
|||
|
|||
#include "defs.h" |
|||
#include "gdbcmd.h" |
|||
|
|||
#if defined (NEW_PROC_API) |
|||
#define _STRUCTURED_PROC 1 |
|||
#endif |
|||
|
|||
#include <stdio.h> |
|||
#include <sys/types.h> |
|||
#include <sys/procfs.h> |
|||
#include <sys/proc.h> /* for struct proc */ |
|||
#include <sys/user.h> /* for struct user */ |
|||
#include <fcntl.h> /* for O_RDWR etc. */ |
|||
#include <sys/wait.h> |
|||
|
|||
#include "proc-utils.h" |
|||
|
|||
/* 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 { |
|||
long value; /* The numeric value */ |
|||
char *name; /* The equivalent symbolic value */ |
|||
char *desc; /* Short description of value */ |
|||
}; |
|||
|
|||
static int procfs_trace = 1; |
|||
/*static int info_verbose = 1;*/ /* kludge */ |
|||
static FILE *procfs_file = NULL; |
|||
static char *procfs_filename = "procfs_trace"; |
|||
|
|||
static void |
|||
set_procfs_trace_cmd (args, from_tty, c) |
|||
char *args; |
|||
int from_tty; |
|||
struct cmd_list_element *c; |
|||
{ |
|||
#if 0 /* not sure what I might actually need to do here, if anything */
|
|||
if (procfs_file) |
|||
fflush (procfs_file); |
|||
#endif |
|||
} |
|||
|
|||
static void |
|||
set_procfs_file_cmd (args, from_tty, c) |
|||
char *args; |
|||
int from_tty; |
|||
struct cmd_list_element *c; |
|||
{ |
|||
/* Just changed the filename for procfs tracing.
|
|||
If a file was already open, close it. */ |
|||
if (procfs_file) |
|||
fclose (procfs_file); |
|||
procfs_file = NULL; |
|||
} |
|||
|
|||
|
|||
#ifndef NEW_PROC_API |
|||
|
|||
static struct trans ioctl_table[] = { |
|||
#ifdef PIOCACINFO /* irix */ |
|||
{ PIOCACINFO, "PIOCACINFO", "get process account info" }, |
|||
#endif |
|||
{ PIOCACTION, "PIOCACTION", "get signal action structs" }, |
|||
#ifdef PIOCARGUMENTS /* osf */ |
|||
{ PIOCARGUMENTS, "PIOCARGUMENTS", "command line args" }, |
|||
#endif |
|||
#ifdef PIOCAUXV /* solaris aux vectors */ |
|||
{ PIOCAUXV, "PIOCAUXV", "get aux vector" }, |
|||
{ PIOCNAUXV, "PIOCNAUXV", "get number of aux vector entries" }, |
|||
#endif /* AUXV */ |
|||
{ PIOCCFAULT, "PIOCCFAULT", "clear current fault" }, |
|||
{ PIOCCRED, "PIOCCRED", "get process credentials" }, |
|||
#ifdef PIOCENEVCTRS /* irix event counters */ |
|||
{ PIOCENEVCTRS, "PIOCENEVCTRS", "acquire and start event counters" }, |
|||
{ PIOCGETEVCTRL, "PIOCGETEVCTRL", "get control info of event counters" }, |
|||
{ PIOCGETEVCTRS, "PIOCGETEVCTRS", "dump event counters" }, |
|||
{ PIOCGETPREVCTRS, "PIOCGETPREVCTRS", "dump event counters & prusage info" }, |
|||
{ PIOCRELEVCTRS, "PIOCRELEVCTRS", "release/stop event counters" }, |
|||
{ PIOCSETEVCTRL, "PIOCSETEVCTRL", "set control info of event counters" }, |
|||
{ PIOCGETPTIMER, "PIOCGETPTIMER", "get process timers" }, |
|||
#endif /* irix event counters */ |
|||
{ PIOCGENTRY, "PIOCGENTRY", "get traced syscall entry set" }, |
|||
{ PIOCGETPR, "PIOCGETPR", "read struct proc" }, |
|||
{ PIOCGETU, "PIOCGETU", "read user area" }, |
|||
#if defined (PIOCGETUTK) && (defined(KERNEL) || defined(SHOW_UTT)) /* osf */ |
|||
{ PIOCGETUTK, "PIOCGETUTK", "get the utask struct" }, |
|||
#endif |
|||
{ PIOCGEXIT, "PIOCGEXIT", "get traced syscall exit set" }, |
|||
{ PIOCGFAULT, "PIOCGFAULT", "get traced fault set" }, |
|||
#ifdef PIOCGFPCR /* osf */ |
|||
{ PIOCGFPCR, "PIOCGFPCR", "get FP control register" }, |
|||
{ PIOCSFPCR, "PIOCSFPCR", "set FP conrtol register" }, |
|||
#endif |
|||
{ PIOCGFPREG, "PIOCGFPREG", "get floating point registers" }, |
|||
{ PIOCGHOLD, "PIOCGHOLD", "get held signal set" }, |
|||
{ PIOCGREG, "PIOCGREG", "get general registers" }, |
|||
{ PIOCGROUPS, "PIOCGROUPS", "get supplementary groups" }, |
|||
#ifdef PIOCGSPCACT /* osf */ |
|||
{ PIOCGSPCACT, "PIOCGSPCACT", "get special action" }, |
|||
{ PIOCSSPCACT, "PIOCSSPCACT", "set special action" }, |
|||
#endif |
|||
{ PIOCGTRACE, "PIOCGTRACE", "get traced signal set" }, |
|||
#ifdef PIOCGWATCH /* irix watchpoints */ |
|||
{ PIOCGWATCH, "PIOCGWATCH", "get watchpoint" }, |
|||
{ PIOCSWATCH, "PIOCSWATCH", "set watchpoint" }, |
|||
{ PIOCNWATCH, "PIOCNWATCH", "get number of watchpoints" }, |
|||
#endif /* irix watchpoints */ |
|||
#ifdef PIOCGWIN /* solaris sparc */ |
|||
{ PIOCGWIN, "PIOCGWIN", "get gwindows_t" }, |
|||
#endif |
|||
#ifdef PIOCGXREG /* solaris sparc extra regs */ |
|||
{ PIOCGXREGSIZE, "PIOCXREGSIZE", "get extra register state size" }, |
|||
{ PIOCGXREG, "PIOCGXREG", "get extra register state" }, |
|||
{ PIOCSXREG, "PIOCSXREG", "set extra register state" }, |
|||
#endif /* XREG */ |
|||
{ PIOCKILL, "PIOCKILL", "send signal" }, |
|||
#ifdef PIOCLDT /* solaris i386 */ |
|||
{ PIOCLDT, "PIOCLDT", "get LDT" }, |
|||
{ PIOCNLDT, "PIOCNLDT", "get number of LDT entries" }, |
|||
#endif |
|||
#ifdef PIOCLSTATUS /* solaris and unixware */ |
|||
{ PIOCLSTATUS, "PIOCLSTATUS", "get status of all lwps" }, |
|||
{ PIOCLUSAGE, "PIOCLUSAGE", "get resource usage of all lwps" }, |
|||
{ PIOCOPENLWP, "PIOCOPENLWP", "get lwp file descriptor" }, |
|||
{ PIOCLWPIDS, "PIOCLWPIDS", "get lwp identifiers" }, |
|||
#endif /* LWP */ |
|||
{ PIOCMAP, "PIOCMAP", "get memory map information" }, |
|||
{ PIOCMAXSIG, "PIOCMAXSIG", "get max signal number" }, |
|||
{ PIOCNICE, "PIOCNICE", "set nice priority" }, |
|||
{ PIOCNMAP, "PIOCNMAP", "get number of memory mappings" }, |
|||
{ PIOCOPENM, "PIOCOPENM", "open mapped object for reading" }, |
|||
#ifdef PIOCOPENMOBS /* osf */ |
|||
{ PIOCOPENMOBS, "PIOCOPENMOBS", "open mapped object" }, |
|||
#endif |
|||
#ifdef PIOCOPENPD /* solaris */ |
|||
{ PIOCOPENPD, "PIOCOPENPD", "get page data file descriptor" }, |
|||
#endif |
|||
{ PIOCPSINFO, "PIOCPSINFO", "get ps(1) information" }, |
|||
{ PIOCRESET, "PIOCRESET", "reset process flags" }, |
|||
{ PIOCRFORK, "PIOCRFORK", "reset inherit-on-fork flag" }, |
|||
{ PIOCRRLC, "PIOCRRLC", "reset run-on-last-close flag" }, |
|||
{ PIOCRUN, "PIOCRUN", "make process runnable" }, |
|||
#ifdef PIOCSAVECCNTRS /* irix */ |
|||
{ PIOCSAVECCNTRS, "PIOCSAVECCNTRS", "parent gets child cntrs" }, |
|||
#endif |
|||
{ PIOCSENTRY, "PIOCSENTRY", "set traced syscall entry set" }, |
|||
{ PIOCSET, "PIOCSET", "set process flags" }, |
|||
{ PIOCSEXIT, "PIOCSEXIT", "set traced syscall exit set" }, |
|||
{ PIOCSFAULT, "PIOCSFAULT", "set traced fault set" }, |
|||
{ PIOCSFORK, "PIOCSFORK", "set inherit-on-fork flag" }, |
|||
{ PIOCSFPREG, "PIOCSFPREG", "set floating point registers" }, |
|||
{ PIOCSHOLD, "PIOCSHOLD", "set held signal set" }, |
|||
{ PIOCSREG, "PIOCSREG", "set general registers" }, |
|||
{ PIOCSRLC, "PIOCSRLC", "set run-on-last-close flag" }, |
|||
{ PIOCSSIG, "PIOCSSIG", "set current signal" }, |
|||
{ PIOCSTATUS, "PIOCSTATUS", "get process status" }, |
|||
{ PIOCSTOP, "PIOCSTOP", "post stop request" }, |
|||
{ PIOCSTRACE, "PIOCSTRACE", "set traced signal set" }, |
|||
{ PIOCUNKILL, "PIOCUNKILL", "delete a signal" }, |
|||
#ifdef PIOCUSAGE /* solaris */ |
|||
{ PIOCUSAGE, "PIOCUSAGE", "get resource usage" }, |
|||
#endif |
|||
{ PIOCWSTOP, "PIOCWSTOP", "wait for process to stop" }, |
|||
|
|||
#ifdef PIOCNTHR /* osf threads */ |
|||
{ PIOCNTHR, "PIOCNTHR", "get thread count" }, |
|||
{ PIOCRTINH, "PIOCRTINH", "reset inherit-on-thread-creation" }, |
|||
{ PIOCSTINH, "PIOCSTINH", "set inherit-on-thread-creation" }, |
|||
{ PIOCTLIST, "PIOCTLIST", "get thread ids" }, |
|||
{ PIOCXPTH, "PIOCXPTH", "translate port to thread handle" }, |
|||
{ PIOCTRUN, "PIOCTRUN", "make thread runnable" }, |
|||
{ PIOCTSTATUS, "PIOCTSTATUS", "get thread status" }, |
|||
{ PIOCTSTOP, "PIOCTSTOP", "stop a thread" }, |
|||
/* ... TGTRACE TSTRACE TSSIG TKILL TUNKILL TCFAULT TGFAULT TSFAULT
|
|||
TGFPREG TSFPREG TGREG TSREG TACTION TTERM TABRUN TGENTRY TSENTRY |
|||
TGEXIT TSEXIT TSHOLD ... thread functions */ |
|||
#endif /* osf threads */ |
|||
{ -1, NULL, NULL } |
|||
}; |
|||
|
|||
int |
|||
ioctl_with_trace (fd, opcode, ptr, file, line) |
|||
int fd; |
|||
long opcode; |
|||
void *ptr; |
|||
char *file; |
|||
int line; |
|||
{ |
|||
int i, ret, arg1; |
|||
|
|||
if (procfs_trace) |
|||
{ |
|||
if (procfs_file == NULL && procfs_filename != NULL) |
|||
procfs_file = fopen (procfs_filename, "a"); |
|||
|
|||
for (i = 0; ioctl_table[i].name != NULL; i++) |
|||
if (ioctl_table[i].value == opcode) |
|||
break; |
|||
|
|||
if (info_verbose) |
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"%s:%d -- ", file, line); |
|||
switch (opcode) { |
|||
case PIOCSET: |
|||
arg1 = ptr ? *(long *) ptr : 0; |
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"ioctl (PIOCSET, %s) %s\n", |
|||
arg1 == PR_FORK ? "PR_FORK" : |
|||
arg1 == PR_RLC ? "PR_RLC" : |
|||
#ifdef PR_ASYNC |
|||
arg1 == PR_ASYNC ? "PR_ASYNC" : |
|||
#endif |
|||
"<unknown flag>", |
|||
info_verbose ? ioctl_table[i].desc : ""); |
|||
break; |
|||
case PIOCRESET: |
|||
arg1 = ptr ? *(long *) ptr : 0; |
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"ioctl (PIOCRESET, %s) %s\n", |
|||
arg1 == PR_FORK ? "PR_FORK" : |
|||
arg1 == PR_RLC ? "PR_RLC" : |
|||
#ifdef PR_ASYNC |
|||
arg1 == PR_ASYNC ? "PR_ASYNC" : |
|||
#endif |
|||
"<unknown flag>", |
|||
info_verbose ? ioctl_table[i].desc : ""); |
|||
break; |
|||
case PIOCSTRACE: |
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"ioctl (PIOCSTRACE) "); |
|||
proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout, |
|||
(sigset_t *) ptr, 0); |
|||
break; |
|||
case PIOCSFAULT: |
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"ioctl (%s) ", |
|||
opcode == PIOCSFAULT ? "PIOCSFAULT" : "PIOCGFAULT"); |
|||
proc_prettyfprint_faultset (procfs_file ? procfs_file : stdout, |
|||
(fltset_t *) ptr, 0); |
|||
break; |
|||
case PIOCSENTRY: |
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"ioctl (%s) ", |
|||
opcode == PIOCSENTRY ? "PIOCSENTRY" : "PIOCGENTRY"); |
|||
proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout, |
|||
(sysset_t *) ptr, 0); |
|||
break; |
|||
case PIOCSEXIT: |
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"ioctl (%s) ", |
|||
opcode == PIOCSEXIT ? "PIOCSEXIT" : "PIOCGEXIT"); |
|||
proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout, |
|||
(sysset_t *) ptr, 0); |
|||
break; |
|||
case PIOCSHOLD: |
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"ioctl (%s) ", |
|||
opcode == PIOCSHOLD ? "PIOCSHOLD" : "PIOCGHOLD"); |
|||
proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout, |
|||
(sigset_t *) ptr, 0); |
|||
break; |
|||
case PIOCSSIG: |
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"ioctl (PIOCSSIG) "); |
|||
proc_prettyfprint_signal (procfs_file ? procfs_file : stdout, |
|||
ptr ? ((siginfo_t *) ptr)->si_signo : 0, |
|||
0); |
|||
fprintf (procfs_file ? procfs_file : stdout, "\n"); |
|||
break; |
|||
case PIOCRUN: |
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"ioctl (PIOCRUN) "); |
|||
|
|||
arg1 = ptr ? *(long *) ptr : 0; |
|||
if (arg1 & PRCSIG) |
|||
fprintf (procfs_file ? procfs_file : stdout, "clearSig "); |
|||
if (arg1 & PRCFAULT) |
|||
fprintf (procfs_file ? procfs_file : stdout, "clearFlt "); |
|||
if (arg1 & PRSTRACE) |
|||
fprintf (procfs_file ? procfs_file : stdout, "setTrace "); |
|||
if (arg1 & PRSHOLD) |
|||
fprintf (procfs_file ? procfs_file : stdout, "setHold "); |
|||
if (arg1 & PRSFAULT) |
|||
fprintf (procfs_file ? procfs_file : stdout, "setFlt "); |
|||
if (arg1 & PRSVADDR) |
|||
fprintf (procfs_file ? procfs_file : stdout, "setVaddr "); |
|||
if (arg1 & PRSTEP) |
|||
fprintf (procfs_file ? procfs_file : stdout, "step "); |
|||
if (arg1 & PRSABORT) |
|||
fprintf (procfs_file ? procfs_file : stdout, "syscallAbort "); |
|||
if (arg1 & PRSTOP) |
|||
fprintf (procfs_file ? procfs_file : stdout, "stopReq "); |
|||
|
|||
fprintf (procfs_file ? procfs_file : stdout, "\n"); |
|||
break; |
|||
case PIOCKILL: |
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"ioctl (PIOCKILL) "); |
|||
proc_prettyfprint_signal (procfs_file ? procfs_file : stdout, |
|||
ptr ? *(long *) ptr : 0, 0); |
|||
fprintf (procfs_file ? procfs_file : stdout, "\n"); |
|||
break; |
|||
#ifdef PIOCSSPCACT |
|||
case PIOCSSPCACT: |
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"ioctl (PIOCSSPCACT) "); |
|||
arg1 = ptr ? *(long *) ptr : 0; |
|||
if (arg1 & PRFS_STOPFORK) |
|||
fprintf (procfs_file ? procfs_file : stdout, "stopFork "); |
|||
if (arg1 & PRFS_STOPEXEC) |
|||
fprintf (procfs_file ? procfs_file : stdout, "stopExec "); |
|||
if (arg1 & PRFS_STOPTERM) |
|||
fprintf (procfs_file ? procfs_file : stdout, "stopTerm "); |
|||
if (arg1 & PRFS_STOPTCR) |
|||
fprintf (procfs_file ? procfs_file : stdout, "stopThreadCreate "); |
|||
if (arg1 & PRFS_STOPTTERM) |
|||
fprintf (procfs_file ? procfs_file : stdout, "stopThreadTerm "); |
|||
if (arg1 & PRFS_KOLC) |
|||
fprintf (procfs_file ? procfs_file : stdout, "killOnLastClose "); |
|||
fprintf (procfs_file ? procfs_file : stdout, "\n"); |
|||
break; |
|||
#endif /* PIOCSSPCACT */ |
|||
default: |
|||
if (ioctl_table[i].name) |
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"ioctl (%s) %s\n", |
|||
ioctl_table[i].name, |
|||
info_verbose ? ioctl_table[i].desc : ""); |
|||
else |
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"ioctl (<unknown %ld (0x%lx)) \n", opcode, opcode); |
|||
break; |
|||
} |
|||
if (procfs_file) |
|||
fflush (procfs_file); |
|||
} |
|||
ret = ioctl (fd, opcode, ptr); |
|||
if (procfs_trace && ret < 0) |
|||
{ |
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"[ioctl (%s) FAILED!]\n", |
|||
ioctl_table[i].name != NULL ? |
|||
ioctl_table[i].name : "<unknown>"); |
|||
if (procfs_file) |
|||
fflush (procfs_file); |
|||
} |
|||
|
|||
return ret; |
|||
} |
|||
|
|||
#else /* NEW_PROC_API */ |
|||
|
|||
static struct trans rw_table[] = { |
|||
#ifdef PCAGENT /* solaris */ |
|||
{ PCAGENT, "PCAGENT", "create agent lwp with regs from argument" }, |
|||
#endif |
|||
{ PCCFAULT, "PCCFAULT", "clear current fault" }, |
|||
#ifdef PCCSIG /* solaris */ |
|||
{ PCCSIG, "PCCSIG", "clear current signal" }, |
|||
#endif |
|||
{ PCDSTOP, "PCDSTOP", "post stop request" }, |
|||
{ PCKILL, "PCKILL", "post a signal" }, |
|||
{ PCNICE, "PCNICE", "set nice priority" }, |
|||
#ifdef PCREAD /* solaris */ |
|||
{ PCREAD, "PCREAD", "read from the address space" }, |
|||
{ PCWRITE, "PCWRITE", "write to the address space" }, |
|||
#endif |
|||
#ifdef PCRESET /* unixware */ |
|||
{ PCRESET, "PCRESET", "unset modes" }, |
|||
#endif |
|||
{ PCRUN, "PCRUN", "make process/lwp runnable" }, |
|||
#ifdef PCSASRS /* solaris 2.7 only */ |
|||
{ PCSASRS, "PCSASRS", "set ancillary state registers" }, |
|||
#endif |
|||
#ifdef PCSCRED /* solaris */ |
|||
{ PCSCRED, "PCSCRED", "set process credentials" }, |
|||
#endif |
|||
{ PCSENTRY, "PCSENTRY", "set traced syscall entry set" }, |
|||
{ PCSET, "PCSET", "set modes" }, |
|||
{ PCSEXIT, "PCSEXIT", "set traced syscall exit set" }, |
|||
{ PCSFAULT, "PCSFAULT", "set traced fault set" }, |
|||
{ PCSFPREG, "PCSFPREG", "set floating point registers" }, |
|||
{ PCSHOLD, "PCSHOLD", "set signal mask" }, |
|||
{ PCSREG, "PCSREG", "set general registers" }, |
|||
{ PCSSIG, "PCSSIG", "set current signal" }, |
|||
{ PCSTOP, "PCSTOP", "post stop request and wait" }, |
|||
{ PCSTRACE, "PCSTRACE", "set traced signal set" }, |
|||
#ifdef PCSVADDR /* solaris */ |
|||
{ PCSVADDR, "PCSVADDR", "set pc virtual address" }, |
|||
#endif |
|||
#ifdef PCSXREG /* solaris sparc only */ |
|||
{ PCSXREG, "PCSXREG", "set extra registers" }, |
|||
#endif |
|||
#ifdef PCTWSTOP /* solaris */ |
|||
{ PCTWSTOP, "PCTWSTOP", "wait for stop, with timeout arg" }, |
|||
#endif |
|||
{ PCUNKILL, "PCUNKILL", "delete a pending signal" }, |
|||
#ifdef PCUNSET /* solaris */ |
|||
{ PCUNSET, "PCUNSET", "unset modes" }, |
|||
#endif |
|||
#ifdef PCWATCH /* solaris */ |
|||
{ PCWATCH, "PCWATCH", "set/unset watched memory area" }, |
|||
#endif |
|||
{ PCWSTOP, "PCWSTOP", "wait for process/lwp to stop, no timeout" }, |
|||
{ 0, NULL, NULL } |
|||
}; |
|||
|
|||
static off_t lseek_offset; |
|||
|
|||
int |
|||
write_with_trace (fd, arg, len, file, line) |
|||
int fd; |
|||
long *arg; |
|||
size_t len; |
|||
char *file; |
|||
int line; |
|||
{ |
|||
int i; |
|||
long opcode = arg[0]; |
|||
int ret; |
|||
|
|||
if (procfs_trace) |
|||
{ |
|||
if (procfs_file == NULL && procfs_filename != NULL) |
|||
procfs_file = fopen (procfs_filename, "a"); |
|||
|
|||
for (i = 0; rw_table[i].name != NULL; i++) |
|||
if (rw_table[i].value == opcode) |
|||
break; |
|||
|
|||
if (info_verbose) |
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"%s:%d -- ", file, line); |
|||
switch (opcode) { |
|||
case PCSET: |
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"write (PCSET, %s) %s\n", |
|||
arg[1] == PR_FORK ? "PR_FORK" : |
|||
arg[1] == PR_RLC ? "PR_RLC" : |
|||
#ifdef PR_ASYNC |
|||
arg[1] == PR_ASYNC ? "PR_ASYNC" : |
|||
#endif |
|||
"<unknown flag>", |
|||
info_verbose ? rw_table[i].desc : ""); |
|||
break; |
|||
#ifdef PCUNSET |
|||
case PCUNSET: |
|||
#endif |
|||
#ifdef PCRESET |
|||
case PCRESET: |
|||
#endif |
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"write (PCRESET, %s) %s\n", |
|||
arg[1] == PR_FORK ? "PR_FORK" : |
|||
arg[1] == PR_RLC ? "PR_RLC" : |
|||
#ifdef PR_ASYNC |
|||
arg[1] == PR_ASYNC ? "PR_ASYNC" : |
|||
#endif |
|||
"<unknown flag>", |
|||
info_verbose ? rw_table[i].desc : ""); |
|||
break; |
|||
case PCSTRACE: |
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"write (PCSTRACE) "); |
|||
proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout, |
|||
(sigset_t *) &arg[1], 0); |
|||
break; |
|||
case PCSFAULT: |
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"write (PCSFAULT) "); |
|||
proc_prettyfprint_faultset (procfs_file ? procfs_file : stdout, |
|||
(fltset_t *) &arg[1], 0); |
|||
break; |
|||
case PCSENTRY: |
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"write (PCSENTRY) "); |
|||
proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout, |
|||
(sysset_t *) &arg[1], 0); |
|||
break; |
|||
case PCSEXIT: |
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"write (PCSEXIT) "); |
|||
proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout, |
|||
(sysset_t *) &arg[1], 0); |
|||
break; |
|||
case PCSHOLD: |
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"write (PCSHOLD) "); |
|||
proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout, |
|||
(sigset_t *) &arg[1], 0); |
|||
break; |
|||
case PCSSIG: |
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"write (PCSSIG) "); |
|||
proc_prettyfprint_signal (procfs_file ? procfs_file : stdout, |
|||
arg[1] ? ((siginfo_t *) &arg[1])->si_signo |
|||
: 0, |
|||
0); |
|||
fprintf (procfs_file ? procfs_file : stdout, "\n"); |
|||
break; |
|||
case PCRUN: |
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"write (PCRUN) "); |
|||
if (arg[1] & PRCSIG) |
|||
fprintf (procfs_file ? procfs_file : stdout, "clearSig "); |
|||
if (arg[1] & PRCFAULT) |
|||
fprintf (procfs_file ? procfs_file : stdout, "clearFlt "); |
|||
if (arg[1] & PRSTEP) |
|||
fprintf (procfs_file ? procfs_file : stdout, "step "); |
|||
if (arg[1] & PRSABORT) |
|||
fprintf (procfs_file ? procfs_file : stdout, "syscallAbort "); |
|||
if (arg[1] & PRSTOP) |
|||
fprintf (procfs_file ? procfs_file : stdout, "stopReq "); |
|||
|
|||
fprintf (procfs_file ? procfs_file : stdout, "\n"); |
|||
break; |
|||
case PCKILL: |
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"write (PCKILL) "); |
|||
proc_prettyfprint_signal (procfs_file ? procfs_file : stdout, |
|||
arg[1], 0); |
|||
fprintf (procfs_file ? procfs_file : stdout, "\n"); |
|||
break; |
|||
default: |
|||
{ |
|||
static unsigned char break_insn[] = BREAKPOINT; |
|||
|
|||
if (len == sizeof (break_insn) && |
|||
memcmp (arg, &break_insn, len) == 0) |
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"write (<breakpoint at 0x%08x>) \n", lseek_offset); |
|||
else if (rw_table[i].name) |
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"write (%s) %s\n", |
|||
rw_table[i].name, |
|||
info_verbose ? rw_table[i].desc : ""); |
|||
else |
|||
{ |
|||
if (lseek_offset != -1) |
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"write (<unknown>, %d bytes at 0x%08x) \n", |
|||
len, lseek_offset); |
|||
else |
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"write (<unknown>, %d bytes) \n", len); |
|||
} |
|||
break; |
|||
} |
|||
} |
|||
if (procfs_file) |
|||
fflush (procfs_file); |
|||
} |
|||
ret = write (fd, arg, len); |
|||
if (procfs_trace && ret != len) |
|||
{ |
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"[write (%s) FAILED!\n", |
|||
rw_table[i].name != NULL ? |
|||
rw_table[i].name : "<unknown>"); |
|||
if (procfs_file) |
|||
fflush (procfs_file); |
|||
} |
|||
|
|||
lseek_offset = -1; |
|||
return ret; |
|||
} |
|||
|
|||
off_t |
|||
lseek_with_trace (fd, offset, whence, file, line) |
|||
int fd; |
|||
off_t offset; |
|||
int whence; |
|||
char *file; |
|||
int line; |
|||
{ |
|||
off_t ret; |
|||
|
|||
#if 0 /* don't need output, just need address */
|
|||
if (procfs_trace) |
|||
{ |
|||
if (procfs_file == NULL && procfs_filename != NULL) |
|||
procfs_file = fopen (procfs_filename, "a"); |
|||
|
|||
if (info_verbose) |
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"%s:%d -- ", file, line); |
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"lseek (0x%08x, %s) \n", offset, |
|||
whence == SEEK_SET ? "SEEK_SET" : |
|||
whence == SEEK_CUR ? "SEEK_CUR" : |
|||
whence == SEEK_END ? "SEEK_END" : |
|||
"<unknown whence>"); |
|||
if (procfs_file) |
|||
fflush (procfs_file); |
|||
} |
|||
#endif |
|||
ret = lseek (fd, offset, whence); |
|||
lseek_offset = ret; |
|||
if (procfs_trace && ret == -1) |
|||
{ |
|||
if (procfs_file == NULL && procfs_filename != NULL) |
|||
procfs_file = fopen (procfs_filename, "a"); |
|||
|
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"[lseek (0x%08x) FAILED!\n", offset); |
|||
if (procfs_file) |
|||
fflush (procfs_file); |
|||
} |
|||
|
|||
return ret; |
|||
} |
|||
|
|||
#endif /* NEW_PROC_API */ |
|||
|
|||
int |
|||
open_with_trace (filename, mode, file, line) |
|||
char *filename; |
|||
int mode; |
|||
char *file; |
|||
int line; |
|||
{ |
|||
int ret = open (filename, mode); |
|||
|
|||
if (procfs_trace) |
|||
{ |
|||
if (procfs_file == NULL && procfs_filename != NULL) |
|||
procfs_file = fopen (procfs_filename, "a"); |
|||
|
|||
if (info_verbose) |
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"%s:%d -- ", file, line); |
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"%d = open (%s, ", ret, filename); |
|||
if (mode == O_RDONLY) |
|||
fprintf (procfs_file ? procfs_file : stdout, "O_RDONLY) %d\n", line); |
|||
else if (mode == O_WRONLY) |
|||
fprintf (procfs_file ? procfs_file : stdout, "O_WRONLY) %d\n", line); |
|||
else if (mode == O_RDWR) |
|||
fprintf (procfs_file ? procfs_file : stdout, "O_RDWR) %d\n", line); |
|||
if (procfs_file) |
|||
fflush (procfs_file); |
|||
} |
|||
|
|||
return ret; |
|||
} |
|||
|
|||
int |
|||
close_with_trace (fd, file, line) |
|||
int fd; |
|||
char *file; |
|||
int line; |
|||
{ |
|||
int ret = close (fd); |
|||
|
|||
if (procfs_trace) |
|||
{ |
|||
if (procfs_file == NULL && procfs_filename != NULL) |
|||
procfs_file = fopen (procfs_filename, "a"); |
|||
|
|||
if (info_verbose) |
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"%s:%d -- ", file, line); |
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"%d = close (%d)\n", ret, fd); |
|||
if (procfs_file) |
|||
fflush (procfs_file); |
|||
} |
|||
|
|||
return ret; |
|||
} |
|||
|
|||
int |
|||
wait_with_trace (wstat, file, line) |
|||
int *wstat; |
|||
char *file; |
|||
int line; |
|||
{ |
|||
int ret, lstat = 0; |
|||
|
|||
if (procfs_trace) |
|||
{ |
|||
if (procfs_file == NULL && procfs_filename != NULL) |
|||
procfs_file = fopen (procfs_filename, "a"); |
|||
|
|||
if (info_verbose) |
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"%s:%d -- ", file, line); |
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"wait (line %d) ", line); |
|||
if (procfs_file) |
|||
fflush (procfs_file); |
|||
} |
|||
ret = wait (&lstat); |
|||
if (procfs_trace) |
|||
{ |
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"returned pid %d, status 0x%x\n", ret, lstat); |
|||
if (procfs_file) |
|||
fflush (procfs_file); |
|||
} |
|||
if (wstat) |
|||
*wstat = lstat; |
|||
|
|||
return ret; |
|||
} |
|||
|
|||
void |
|||
procfs_note (msg, file, line) |
|||
char *msg; |
|||
char *file; |
|||
int line; |
|||
{ |
|||
if (procfs_trace) |
|||
{ |
|||
if (procfs_file == NULL && procfs_filename != NULL) |
|||
procfs_file = fopen (procfs_filename, "a"); |
|||
|
|||
if (info_verbose) |
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"%s:%d -- ", file, line); |
|||
fprintf (procfs_file ? procfs_file : stdout, msg); |
|||
if (procfs_file) |
|||
fflush (procfs_file); |
|||
} |
|||
} |
|||
|
|||
void |
|||
proc_prettyfprint_status (flags, why, what, thread) |
|||
long flags; |
|||
int why; |
|||
int what; |
|||
int thread; |
|||
{ |
|||
if (procfs_trace) |
|||
{ |
|||
if (procfs_file == NULL && procfs_filename != NULL) |
|||
procfs_file = fopen (procfs_filename, "a"); |
|||
|
|||
if (thread) |
|||
fprintf (procfs_file ? procfs_file : stdout, |
|||
"Thread %d: ", thread); |
|||
|
|||
proc_prettyfprint_flags (procfs_file ? procfs_file : stdout, |
|||
flags, 0); |
|||
|
|||
if (flags & (PR_STOPPED | PR_ISTOP)) |
|||
proc_prettyfprint_why (procfs_file ? procfs_file : stdout, |
|||
why, what, 0); |
|||
if (procfs_file) |
|||
fflush (procfs_file); |
|||
} |
|||
} |
|||
|
|||
|
|||
void |
|||
_initialize_proc_api () |
|||
{ |
|||
struct cmd_list_element *c; |
|||
|
|||
c = add_set_cmd ("procfs-trace", no_class, |
|||
var_boolean, (char *) &procfs_trace, |
|||
"Set tracing for /proc ioctl calls.\n", &setlist); |
|||
|
|||
add_show_from_set (c, &showlist); |
|||
c->function.sfunc = set_procfs_trace_cmd; |
|||
|
|||
c = add_set_cmd ("procfs-file", no_class, var_filename, |
|||
(char *) &procfs_filename, |
|||
"Set filename for /proc tracefile.\n", &setlist); |
|||
|
|||
add_show_from_set (c, &showlist); |
|||
c->function.sfunc = set_procfs_file_cmd; |
|||
|
|||
#ifdef TRACE_PROCFS |
|||
if (procfs_file == NULL && procfs_filename != NULL) |
|||
procfs_file = fopen (procfs_filename, "a"); |
|||
#endif |
|||
} |
|||
File diff suppressed because it is too large
@ -0,0 +1,296 @@ |
|||
/* Machine independent support for SVR4 /proc (process file system) for GDB.
|
|||
Copyright 1999 Free Software Foundation, Inc. |
|||
Written by Michael Snyder at Cygnus Solutions. |
|||
Based on work by Fred Fish, Stu Grossman, Geoff Noer, and others. |
|||
|
|||
This file is part of GDB. |
|||
|
|||
This program is free software; you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation; either version 2 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
This program is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
|||
|
|||
/*
|
|||
* Pretty-print the prstatus flags. |
|||
* |
|||
* Arguments: unsigned long flags, int verbose |
|||
* |
|||
*/ |
|||
|
|||
#include "defs.h" |
|||
|
|||
#if defined (NEW_PROC_API) |
|||
#define _STRUCTURED_PROC 1 |
|||
#endif |
|||
|
|||
#include <stdio.h> |
|||
#include <sys/types.h> |
|||
#include <sys/procfs.h> |
|||
|
|||
/* 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) |
|||
/* Sol2.5: lwp is stopped
|
|||
* Sol2.6: lwp is stopped |
|||
* Sol2.7: lwp is stopped |
|||
* IRIX6: process is stopped |
|||
* OSF: task/thread is stopped |
|||
* UW: LWP is stopped |
|||
*/ |
|||
{ PR_STOPPED, "PR_STOPPED", "Process (LWP) is stopped" }, |
|||
#endif |
|||
#if defined (PR_ISTOP) |
|||
/* Sol2.5: lwp is stopped on an event of interest
|
|||
* Sol2.6: lwp is stopped on an event of interest |
|||
* Sol2.7: lwp is stopped on an event of interest |
|||
* IRIX6: process is stopped on event of interest |
|||
* OSF: task/thread stopped on event of interest |
|||
* UW: LWP stopped on an event of interest |
|||
*/ |
|||
{ PR_ISTOP, "PR_ISTOP", "Stopped on an event of interest" }, |
|||
#endif |
|||
#if defined (PR_DSTOP) |
|||
/* Sol2.5: lwp has a stop directive in effect
|
|||
* Sol2.6: lwp has a stop directive in effect |
|||
* Sol2.7: lwp has a stop directive in effect |
|||
* IRIX6: process has stop directive in effect |
|||
* OSF: task/thread has stop directive in effect |
|||
* UW: A stop directive is in effect |
|||
*/ |
|||
{ PR_DSTOP, "PR_DSTOP", "A stop directive is in effect" }, |
|||
#endif |
|||
#if defined (PR_STEP) |
|||
/* Sol2.5: lwp has a single-step directive in effect
|
|||
* Sol2.6: lwp has a single-step directive in effect |
|||
* Sol2.7: lwp has a single-step directive in effect |
|||
* IRIX6: process has single step pending |
|||
*/ |
|||
{ PR_STEP, "PR_STEP", "A single step directive is in effect" }, |
|||
#endif |
|||
#if defined (PR_ASLEEP) |
|||
/* Sol2.5: lwp is sleeping in a system call
|
|||
* Sol2.6: lwp is sleeping in a system call |
|||
* Sol2.7: lwp is sleeping in a system call |
|||
* IRIX6: process is in an interruptible sleep |
|||
* OSF: task/thread is asleep within a system call |
|||
* UW: LWP is sleep()ing in a system call |
|||
*/ |
|||
{ PR_ASLEEP, "PR_ASLEEP", "Sleeping in an (interruptible) system call" }, |
|||
#endif |
|||
#if defined (PR_PCINVAL) |
|||
/* Sol2.5: contents of pr_instr undefined
|
|||
* Sol2.6: contents of pr_instr undefined |
|||
* Sol2.7: contents of pr_instr undefined |
|||
* IRIX6: current pc is invalid |
|||
* OSF: program counter contains invalid address |
|||
* UW: %pc refers to an invalid virtual address |
|||
*/ |
|||
{ PR_PCINVAL, "PR_PCINVAL", "PC (pr_instr) is invalid" }, |
|||
#endif |
|||
#if defined (PR_ASLWP) |
|||
/* Sol2.5: this lwp is the aslwp
|
|||
* Sol2.6: this lwp is the aslwp |
|||
* Sol2.7: this lwp is the aslwp |
|||
*/ |
|||
{ PR_ASLWP, "PR_ASLWP", "This is the asynchronous signal LWP" }, |
|||
#endif |
|||
#if defined (PR_AGENT) |
|||
/* Sol2.6: this lwp is the /proc agent lwp
|
|||
* Sol2.7: this lwp is the /proc agent lwp |
|||
*/ |
|||
{ PR_AGENT, "PR_AGENT", "This is the /proc agent LWP" }, |
|||
#endif |
|||
#if defined (PR_ISSYS) |
|||
/* Sol2.5: system process
|
|||
* Sol2.6: this is a system process |
|||
* Sol2.7: this is a system process |
|||
* IRIX6: process is a system process |
|||
* OSF: task/thread is a system task/thread |
|||
* UW: System process |
|||
*/ |
|||
{ PR_ISSYS, "PR_ISSYS", "Is a system process/thread" }, |
|||
#endif |
|||
#if defined (PR_VFORKP) |
|||
/* Sol2.6: process is the parent of a vfork()d child
|
|||
* Sol2.7: process is the parent of a vfork()d child |
|||
*/ |
|||
{ PR_VFORKP, "PR_VFORKP", "Process is the parent of a vforked child" }, |
|||
#endif |
|||
#ifdef PR_ORPHAN |
|||
/* Sol2.6: process's process group is orphaned
|
|||
* Sol2.7: process's process group is orphaned |
|||
*/ |
|||
{ PR_ORPHAN, "PR_ORPHAN", "Process's process group is orphaned" }, |
|||
#endif |
|||
#if defined (PR_FORK) |
|||
/* Sol2.5: inherit-on-fork is in effect
|
|||
* Sol2.6: inherit-on-fork is in effect |
|||
* Sol2.7: inherit-on-fork is in effect |
|||
* IRIX6: process has inherit-on-fork flag set |
|||
* OSF: task/thread has inherit-on-fork flag set |
|||
* UW: inherit-on-fork is in effect |
|||
*/ |
|||
{ PR_FORK, "PR_FORK", "Inherit-on-fork is in effect" }, |
|||
#endif |
|||
#if defined (PR_RLC) |
|||
/* Sol2.5: run-on-last-close is in effect
|
|||
* Sol2.6: run-on-last-close is in effect |
|||
* Sol2.7: run-on-last-close is in effect |
|||
* IRIX6: process has run-on-last-close flag set |
|||
* OSF: task/thread has run-on-last-close flag set |
|||
* UW: Run-on-last-close is in effect |
|||
*/ |
|||
{ PR_RLC, "PR_RLC", "Run-on-last-close is in effect" }, |
|||
#endif |
|||
#if defined (PR_KLC) |
|||
/* Sol2.5: kill-on-last-close is in effect
|
|||
* Sol2.6: kill-on-last-close is in effect |
|||
* Sol2.7: kill-on-last-close is in effect |
|||
* IRIX6: process has kill-on-last-close flag set |
|||
* OSF: kill-on-last-close, superceeds RLC |
|||
* UW: kill-on-last-close is in effect |
|||
*/ |
|||
{ PR_KLC, "PR_KLC", "Kill-on-last-close is in effect" }, |
|||
#endif |
|||
#if defined (PR_ASYNC) |
|||
/* Sol2.5: asynchronous-stop is in effect
|
|||
* Sol2.6: asynchronous-stop is in effect |
|||
* Sol2.7: asynchronous-stop is in effect |
|||
* OSF: asynchronous stop mode is in effect |
|||
* UW: asynchronous stop mode is in effect |
|||
*/ |
|||
{ PR_ASYNC, "PR_ASYNC", "Asynchronous stop is in effect" }, |
|||
#endif |
|||
#if defined (PR_MSACCT) |
|||
/* Sol2.5: micro-state usage accounting is in effect
|
|||
* Sol2.6: micro-state usage accounting is in effect |
|||
* Sol2.7: micro-state usage accounting is in effect |
|||
*/ |
|||
{ PR_MSACCT, "PR_MSACCT", "Microstate accounting enabled" }, |
|||
#endif |
|||
#if defined (PR_BPTADJ) |
|||
/* Sol2.5: breakpoint trap pc adjustment is in effect
|
|||
* Sol2.6: breakpoint trap pc adjustment is in effect |
|||
* Sol2.7: breakpoint trap pc adjustment is in effect |
|||
*/ |
|||
{ PR_BPTADJ, "PR_BPTADJ", "Breakpoint PC adjustment in effect" }, |
|||
#endif |
|||
#if defined (PR_PTRACE) |
|||
/* Note: different meanings on Solaris and Irix 6
|
|||
* Sol2.5: obsolete, never set in SunOS5.0 |
|||
* Sol2.6: ptrace-compatibility mode is in effect |
|||
* Sol2.7: ptrace-compatibility mode is in effect |
|||
* IRIX6: process is traced with ptrace() too |
|||
* OSF: task/thread is being traced by ptrace |
|||
* UW: Process is being controlled by ptrace(2) |
|||
*/ |
|||
{ PR_PTRACE, "PR_PTRACE", "Process is being controlled by ptrace" }, |
|||
#endif |
|||
#if defined (PR_PCOMPAT) |
|||
/* Note: PCOMPAT on Sol2.5 means same thing as PTRACE on Sol2.6
|
|||
* Sol2.5 (only): ptrace-compatibility mode is in effect |
|||
*/ |
|||
{ PR_PCOMPAT, "PR_PCOMPAT", "Ptrace compatibility mode in effect" }, |
|||
#endif |
|||
#ifdef PR_MSFORK |
|||
/* Sol2.6: micro-state accounting inherited on fork
|
|||
* Sol2.7: micro-state accounting inherited on fork |
|||
*/ |
|||
{ PR_MSFORK, "PR_PCOMPAT", "Micro-state accounting inherited on fork" }, |
|||
#endif |
|||
|
|||
#ifdef PR_ISKTHREAD |
|||
/* Irix6: process is a kernel thread */ |
|||
{ PR_ISKTHREAD, "PR_KTHREAD", "Process is a kernel thread" }, |
|||
#endif |
|||
|
|||
#ifdef PR_ABORT |
|||
/* OSF (only): abort the current stop condition */ |
|||
{ PR_ABORT, "PR_ABORT", "Abort the current stop condition" }, |
|||
#endif |
|||
|
|||
#ifdef PR_TRACING |
|||
/* OSF: task is traced */ |
|||
{ PR_TRACING, "PR_TRACING", "Task is traced" }, |
|||
#endif |
|||
|
|||
#ifdef PR_STOPFORK |
|||
/* OSF: stop child on fork */ |
|||
{ PR_STOPFORK, "PR_STOPFORK", "Stop child on fork" }, |
|||
#endif |
|||
|
|||
#ifdef PR_STOPEXEC |
|||
/* OSF: stop on exec */ |
|||
{ PR_STOPEXEC, "PR_STOPEXEC", "Stop on exec" }, |
|||
#endif |
|||
|
|||
#ifdef PR_STOPTERM |
|||
/* OSF: stop on task exit */ |
|||
{ PR_STOPTERM, "PR_STOPTERM", "Stop on task exit" }, |
|||
#endif |
|||
|
|||
#ifdef PR_STOPTCR |
|||
/* OSF: stop on thread creation */ |
|||
{ PR_STOPTCR, "PR_STOPTCR", "Stop on thread creation" }, |
|||
#endif |
|||
|
|||
#ifdef PR_STOPTTERM |
|||
/* OSF: stop on thread exit */ |
|||
{ PR_STOPTTERM, "PR_STOPTTERM", "Stop on thread exit" }, |
|||
#endif |
|||
|
|||
#ifdef PR_USCHED |
|||
/* OSF: user level scheduling is in effect */ |
|||
{ PR_USCHED, "PR_USCHED", "User level scheduling is in effect" }, |
|||
#endif |
|||
}; |
|||
|
|||
void |
|||
proc_prettyfprint_flags (file, flags, verbose) |
|||
FILE *file; |
|||
unsigned long flags; |
|||
int verbose; |
|||
{ |
|||
int i; |
|||
|
|||
for (i = 0; i < sizeof (pr_flag_table) / sizeof (pr_flag_table[0]); i++) |
|||
if (flags & pr_flag_table[i].value) |
|||
{ |
|||
fprintf (file, "%s ", pr_flag_table[i].name); |
|||
if (verbose) |
|||
fprintf (file, "%s\n", pr_flag_table[i].desc); |
|||
} |
|||
if (!verbose) |
|||
fprintf (file, "\n"); |
|||
} |
|||
|
|||
void |
|||
proc_prettyprint_flags (flags, verbose) |
|||
unsigned long flags; |
|||
int verbose; |
|||
{ |
|||
proc_prettyfprint_flags (stdout, flags, verbose); |
|||
} |
|||
@ -0,0 +1,52 @@ |
|||
/* Machine independent support for SVR4 /proc (process file system) for GDB.
|
|||
Copyright 1999 Free Software Foundation, Inc. |
|||
|
|||
This file is part of GDB. |
|||
|
|||
This program is free software; you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation; either version 2 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
This program is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
|||
|
|||
|
|||
extern void |
|||
proc_prettyprint_why (unsigned long why, unsigned long what, int verbose); |
|||
|
|||
extern void proc_prettyprint_syscalls (sysset_t *sysset, int verbose); |
|||
|
|||
extern void proc_prettyprint_syscall (int num, int verbose); |
|||
|
|||
extern void proc_prettyprint_flags (unsigned long flags, int verbose); |
|||
|
|||
extern void |
|||
proc_prettyfprint_signalset (FILE *file, sigset_t *sigset, int verbose); |
|||
|
|||
extern void |
|||
proc_prettyfprint_faultset (FILE *file, fltset_t *fltset, int verbose); |
|||
|
|||
extern void |
|||
proc_prettyfprint_syscall (FILE *file, int num, int verbose); |
|||
|
|||
extern void |
|||
proc_prettyfprint_signal (FILE *file, int signo, int verbose); |
|||
|
|||
extern void |
|||
proc_prettyfprint_flags (FILE *file, unsigned long flags, int verbose); |
|||
|
|||
extern void |
|||
proc_prettyfprint_why (FILE *file, unsigned long why, unsigned long what, int verbose); |
|||
|
|||
extern void |
|||
proc_prettyfprint_fault (FILE *file, int faultno, int verbose); |
|||
|
|||
extern void |
|||
proc_prettyfprint_syscalls (FILE *file, sysset_t *sysset, int verbose); |
|||
@ -0,0 +1,181 @@ |
|||
/* Machine independent support for SVR4 /proc (process file system) for GDB.
|
|||
Copyright 1999 Free Software Foundation, Inc. |
|||
Written by Michael Snyder at Cygnus Solutions. |
|||
Based on work by Fred Fish, Stu Grossman, Geoff Noer, and others. |
|||
|
|||
This file is part of GDB. |
|||
|
|||
This program is free software; you can redistribute it and/or modify |
|||
it under the terms of the GNU General Public License as published by |
|||
the Free Software Foundation; either version 2 of the License, or |
|||
(at your option) any later version. |
|||
|
|||
This program is distributed in the hope that it will be useful, |
|||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
|||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|||
GNU General Public License for more details. |
|||
|
|||
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ |
|||
|
|||
/*
|
|||
* Pretty-print the pr_why value. |
|||
* |
|||
* Arguments: unsigned long flags, int verbose |
|||
* |
|||
*/ |
|||
|
|||
#include "defs.h" |
|||
|
|||
#if defined(NEW_PROC_API) |
|||
#define _STRUCTURED_PROC 1 |
|||
#endif |
|||
|
|||
#include <stdio.h> |
|||
#include <sys/types.h> |
|||
#include <sys/procfs.h> |
|||
|
|||
#include "proc-utils.h" |
|||
|
|||
/* 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 values in the pr_why field of the prstatus struct. */ |
|||
|
|||
static struct trans pr_why_table[] = |
|||
{ |
|||
#if defined (PR_REQUESTED) |
|||
/* All platforms */ |
|||
{ PR_REQUESTED, "PR_REQUESTED", |
|||
"Directed to stop by debugger via P(IO)CSTOP or P(IO)CWSTOP" }, |
|||
#endif |
|||
#if defined (PR_SIGNALLED) |
|||
/* All platforms */ |
|||
{ PR_SIGNALLED, "PR_SIGNALLED", "Receipt of a traced signal" }, |
|||
#endif |
|||
#if defined (PR_SYSENTRY) |
|||
/* All platforms */ |
|||
{ PR_SYSENTRY, "PR_SYSENTRY", "Entry to a traced system call" }, |
|||
#endif |
|||
#if defined (PR_SYSEXIT) |
|||
/* All platforms */ |
|||
{ PR_SYSEXIT, "PR_SYSEXIT", "Exit from a traced system call" }, |
|||
#endif |
|||
#if defined (PR_JOBCONTROL) |
|||
/* All platforms */ |
|||
{ PR_JOBCONTROL, "PR_JOBCONTROL", "Default job control stop signal action" }, |
|||
#endif |
|||
#if defined (PR_FAULTED) |
|||
/* All platforms */ |
|||
{ PR_FAULTED, "PR_FAULTED", "Incurred a traced hardware fault" }, |
|||
#endif |
|||
#if defined (PR_SUSPENDED) |
|||
/* Solaris and UnixWare */ |
|||
{ PR_SUSPENDED, "PR_SUSPENDED", "Process suspended" }, |
|||
#endif |
|||
#if defined (PR_CHECKPOINT) |
|||
/* Solaris only */ |
|||
{ PR_CHECKPOINT, "PR_CHECKPOINT", "Process stopped at checkpoint" }, |
|||
#endif |
|||
#if defined (PR_FORKSTOP) |
|||
/* OSF only */ |
|||
{ PR_FORKSTOP, "PR_FORKSTOP", "Process stopped at end of fork call" }, |
|||
#endif |
|||
#if defined (PR_TCRSTOP) |
|||
/* OSF only */ |
|||
{ PR_TCRSTOP, "PR_TCRSTOP", "Process stopped on thread creation" }, |
|||
#endif |
|||
#if defined (PR_TTSTOP) |
|||
/* OSF only */ |
|||
{ PR_TTSTOP, "PR_TTSTOP", "Process stopped on thread termination" }, |
|||
#endif |
|||
#if defined (PR_DEAD) |
|||
/* OSF only */ |
|||
{ PR_DEAD, "PR_DEAD", "Process stopped in exit system call" }, |
|||
#endif |
|||
}; |
|||
|
|||
void |
|||
proc_prettyfprint_why (file, why, what, verbose) |
|||
FILE *file; |
|||
unsigned long why; |
|||
unsigned long what; |
|||
int verbose; |
|||
{ |
|||
int i; |
|||
|
|||
if (why == 0) |
|||
return; |
|||
|
|||
for (i = 0; i < sizeof (pr_why_table) / sizeof (pr_why_table[0]); i++) |
|||
if (why == pr_why_table[i].value) |
|||
{ |
|||
fprintf (file, "%s ", pr_why_table[i].name); |
|||
if (verbose) |
|||
fprintf (file, ": %s ", pr_why_table[i].desc); |
|||
|
|||
switch (why) { |
|||
#ifdef PR_REQUESTED |
|||
case PR_REQUESTED: |
|||
break; /* Nothing more to print. */ |
|||
#endif |
|||
#ifdef PR_SIGNALLED |
|||
case PR_SIGNALLED: |
|||
proc_prettyfprint_signal (file, what, verbose); |
|||
break; |
|||
#endif |
|||
#ifdef PR_FAULTED |
|||
case PR_FAULTED: |
|||
proc_prettyfprint_fault (file, what, verbose); |
|||
break; |
|||
#endif |
|||
#ifdef PR_SYSENTRY |
|||
case PR_SYSENTRY: |
|||
fprintf (file, "Entry to "); |
|||
proc_prettyfprint_syscall (file, what, verbose); |
|||
break; |
|||
#endif |
|||
#ifdef PR_SYSEXIT |
|||
case PR_SYSEXIT: |
|||
fprintf (file, "Exit from "); |
|||
proc_prettyfprint_syscall (file, what, verbose); |
|||
break; |
|||
#endif |
|||
#ifdef PR_JOBCONTROL |
|||
case PR_JOBCONTROL: |
|||
proc_prettyfprint_signal (file, what, verbose); |
|||
break; |
|||
#endif |
|||
#ifdef PR_DEAD |
|||
case PR_DEAD: |
|||
fprintf (file, "Exit status: %d\n", what); |
|||
break; |
|||
#endif |
|||
default: |
|||
fprintf (file, "Unknown why %ld, what %ld\n", why, what); |
|||
break; |
|||
} |
|||
fprintf (file, "\n"); |
|||
|
|||
return; |
|||
} |
|||
fprintf (file, "Unknown pr_why.\n"); |
|||
} |
|||
|
|||
void |
|||
proc_prettyprint_why (why, what, verbose) |
|||
unsigned long why; |
|||
unsigned long what; |
|||
int verbose; |
|||
{ |
|||
proc_prettyfprint_why (stdout, why, what, verbose); |
|||
} |
|||
Loading…
Reference in new issue