GDB (API)
/home/stan/gdb/src/gdb/proc-api.c
Go to the documentation of this file.
00001 /* Machine independent support for SVR4 /proc (process file system) for GDB.
00002 
00003    Copyright (C) 1999-2013 Free Software Foundation, Inc.
00004 
00005    Written by Michael Snyder at Cygnus Solutions.
00006    Based on work by Fred Fish, Stu Grossman, Geoff Noer, and others.
00007 
00008    This file is part of GDB.
00009 
00010    This program is free software; you can redistribute it and/or modify
00011    it under the terms of the GNU General Public License as published by
00012    the Free Software Foundation; either version 3 of the License, or
00013    (at your option) any later version.
00014 
00015    This program is distributed in the hope that it will be useful,
00016    but WITHOUT ANY WARRANTY; without even the implied warranty of
00017    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018    GNU General Public License for more details.
00019 
00020    You should have received a copy of the GNU General Public License
00021    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00022 
00023 /*
00024  * Pretty-print trace of api calls to the /proc api
00025  * (ioctl or read/write calls).
00026  * 
00027  */
00028 
00029 #include "defs.h"
00030 #include "gdbcmd.h"
00031 #include "completer.h"
00032 
00033 #if defined (NEW_PROC_API)
00034 #define _STRUCTURED_PROC 1
00035 #endif
00036 
00037 #include <stdio.h>
00038 #include <sys/types.h>
00039 #include <sys/procfs.h>
00040 #ifdef HAVE_SYS_PROC_H
00041 #include <sys/proc.h>   /* for struct proc */
00042 #endif
00043 #ifdef HAVE_SYS_USER_H
00044 #include <sys/user.h>   /* for struct user */
00045 #endif
00046 #include <fcntl.h>      /* for O_RDWR etc.  */
00047 #include "gdb_wait.h"
00048 
00049 #include "proc-utils.h"
00050 
00051 /*  Much of the information used in the /proc interface, particularly for
00052     printing status information, is kept as tables of structures of the
00053     following form.  These tables can be used to map numeric values to
00054     their symbolic names and to a string that describes their specific use.  */
00055 
00056 struct trans {
00057   long value;                   /* The numeric value */
00058   char *name;                   /* The equivalent symbolic value */
00059   char *desc;                   /* Short description of value */
00060 };
00061 
00062 static int   procfs_trace    = 0;
00063 static FILE *procfs_file     = NULL;
00064 static char *procfs_filename = "procfs_trace";
00065 
00066 static void
00067 prepare_to_trace (void)
00068 {
00069   if (procfs_trace)                     /* if procfs tracing turned on */
00070     if (procfs_file == NULL)            /* if output file not yet open */
00071       if (procfs_filename != NULL)      /* if output filename known */
00072         procfs_file = fopen (procfs_filename, "a");     /* open output file */
00073 }
00074 
00075 static void
00076 set_procfs_trace_cmd (char *args, int from_tty, struct cmd_list_element *c)
00077 {
00078 #if 0   /* not sure what I might actually need to do here, if anything */
00079   if (procfs_file)
00080     fflush (procfs_file);
00081 #endif
00082 }
00083 
00084 static void
00085 set_procfs_file_cmd (char *args, int from_tty, struct cmd_list_element *c)
00086 {
00087   /* Just changed the filename for procfs tracing.
00088      If a file was already open, close it.  */
00089   if (procfs_file)
00090     fclose (procfs_file);
00091   procfs_file = NULL;
00092 }
00093 
00094 
00095 #ifndef NEW_PROC_API
00096 
00097 static struct trans ioctl_table[] = {
00098 #ifdef PIOCACINFO                       /* irix */
00099   { PIOCACINFO,    "PIOCACINFO",   "get process account info" },
00100 #endif
00101   { PIOCACTION,    "PIOCACTION",   "get signal action structs" },
00102 #ifdef PIOCARGUMENTS                    /* osf */
00103   { PIOCARGUMENTS, "PIOCARGUMENTS", "command line args" },
00104 #endif
00105 #ifdef PIOCAUXV                         /* solaris aux vectors */
00106   { PIOCAUXV,      "PIOCAUXV",     "get aux vector" },
00107   { PIOCNAUXV,     "PIOCNAUXV",    "get number of aux vector entries" },
00108 #endif /* AUXV */
00109   { PIOCCFAULT,    "PIOCCFAULT",   "clear current fault" },
00110   { PIOCCRED,      "PIOCCRED",     "get process credentials" },
00111 #ifdef PIOCENEVCTRS                     /* irix event counters */
00112   { PIOCENEVCTRS,    "PIOCENEVCTRS",    "acquire and start event counters" },
00113   { PIOCGETEVCTRL,   "PIOCGETEVCTRL",   "get control info of event counters" },
00114   { PIOCGETEVCTRS,   "PIOCGETEVCTRS",   "dump event counters" },
00115   { PIOCGETPREVCTRS, "PIOCGETPREVCTRS", "dump event counters & prusage info" },
00116   { PIOCRELEVCTRS,   "PIOCRELEVCTRS",   "release/stop event counters" },
00117   { PIOCSETEVCTRL,   "PIOCSETEVCTRL",   "set control info of event counters" },
00118   { PIOCGETPTIMER,   "PIOCGETPTIMER",   "get process timers" },
00119 #endif  /* irix event counters */
00120   { PIOCGENTRY,    "PIOCGENTRY",   "get traced syscall entry set" },
00121 #if defined (PIOCGETPR)
00122   { PIOCGETPR,     "PIOCGETPR",    "read struct proc" },
00123 #endif
00124 #if defined (PIOCGETU)
00125   { PIOCGETU,      "PIOCGETU",     "read user area" },
00126 #endif
00127 #if defined (PIOCGETUTK) && (defined(KERNEL) || defined(SHOW_UTT)) /* osf */
00128   { PIOCGETUTK,  "PIOCGETUTK", "get the utask struct" },
00129 #endif
00130   { PIOCGEXIT,     "PIOCGEXIT",    "get traced syscall exit  set" },
00131   { PIOCGFAULT,    "PIOCGFAULT",   "get traced fault set" },
00132 #ifdef PIOCGFPCR                        /* osf */
00133   { PIOCGFPCR,     "PIOCGFPCR",    "get FP control register" },
00134   { PIOCSFPCR,     "PIOCSFPCR",    "set FP conrtol register" },
00135 #endif
00136   { PIOCGFPREG,    "PIOCGFPREG",   "get floating point registers" },
00137   { PIOCGHOLD,     "PIOCGHOLD",    "get held signal set" },
00138   { PIOCGREG,      "PIOCGREG",     "get general registers" },
00139   { PIOCGROUPS,    "PIOCGROUPS",   "get supplementary groups" },
00140 #ifdef PIOCGSPCACT                      /* osf */
00141   { PIOCGSPCACT,   "PIOCGSPCACT",  "get special action" },
00142   { PIOCSSPCACT,   "PIOCSSPCACT",  "set special action" },
00143 #endif
00144   { PIOCGTRACE,    "PIOCGTRACE",   "get traced signal set" },
00145 #ifdef PIOCGWATCH                       /* irix watchpoints */
00146   { PIOCGWATCH,    "PIOCGWATCH",   "get watchpoint" },
00147   { PIOCSWATCH,    "PIOCSWATCH",   "set watchpoint" },
00148   { PIOCNWATCH,    "PIOCNWATCH",   "get number of watchpoints" },
00149 #endif  /* irix watchpoints */
00150 #ifdef PIOCGWIN                         /* solaris sparc */
00151   { PIOCGWIN,      "PIOCGWIN",     "get gwindows_t" },
00152 #endif
00153 #ifdef PIOCGXREG                        /* solaris sparc extra regs */
00154   { PIOCGXREGSIZE, "PIOCXREGSIZE", "get extra register state size" },
00155   { PIOCGXREG,     "PIOCGXREG",    "get extra register state" },
00156   { PIOCSXREG,     "PIOCSXREG",    "set extra register state" },
00157 #endif /* XREG */
00158   { PIOCKILL,      "PIOCKILL",     "send signal" },
00159 #ifdef PIOCLDT                          /* solaris i386 */
00160   { PIOCLDT,       "PIOCLDT",      "get LDT" },
00161   { PIOCNLDT,      "PIOCNLDT",     "get number of LDT entries" },
00162 #endif
00163 #ifdef PIOCLSTATUS                      /* solaris */
00164   { PIOCLSTATUS,   "PIOCLSTATUS",  "get status of all lwps" },
00165   { PIOCLUSAGE,    "PIOCLUSAGE",   "get resource usage of all lwps" },
00166   { PIOCOPENLWP,   "PIOCOPENLWP",  "get lwp file descriptor" },
00167   { PIOCLWPIDS,    "PIOCLWPIDS",   "get lwp identifiers" },
00168 #endif /* LWP */
00169   { PIOCMAP,       "PIOCMAP",      "get memory map information" },
00170   { PIOCMAXSIG,    "PIOCMAXSIG",   "get max signal number" },
00171   { PIOCNICE,      "PIOCNICE",     "set nice priority" },
00172   { PIOCNMAP,      "PIOCNMAP",     "get number of memory mappings" },
00173   { PIOCOPENM,     "PIOCOPENM",    "open mapped object for reading" },
00174 #ifdef PIOCOPENMOBS                     /* osf */
00175   { PIOCOPENMOBS,  "PIOCOPENMOBS", "open mapped object" },
00176 #endif
00177 #ifdef PIOCOPENPD       /* solaris */
00178   { PIOCOPENPD,    "PIOCOPENPD",   "get page data file descriptor" },
00179 #endif
00180   { PIOCPSINFO,    "PIOCPSINFO",   "get ps(1) information" },
00181   { PIOCRESET,     "PIOCRESET",    "reset process flags" },
00182   { PIOCRFORK,     "PIOCRFORK",    "reset inherit-on-fork flag" },
00183   { PIOCRRLC,      "PIOCRRLC",     "reset run-on-last-close flag" },
00184   { PIOCRUN,       "PIOCRUN",      "make process runnable" },
00185 #ifdef PIOCSAVECCNTRS                   /* irix */
00186   { PIOCSAVECCNTRS, "PIOCSAVECCNTRS", "parent gets child cntrs" },
00187 #endif
00188   { PIOCSENTRY,    "PIOCSENTRY",   "set traced syscall entry set" },
00189   { PIOCSET,       "PIOCSET",      "set process flags" },
00190   { PIOCSEXIT,     "PIOCSEXIT",    "set traced syscall exit  set" },
00191   { PIOCSFAULT,    "PIOCSFAULT",   "set traced fault set" },
00192   { PIOCSFORK,     "PIOCSFORK",    "set inherit-on-fork flag" },
00193   { PIOCSFPREG,    "PIOCSFPREG",   "set floating point registers" },
00194   { PIOCSHOLD,     "PIOCSHOLD",    "set held signal set" },
00195   { PIOCSREG,      "PIOCSREG",     "set general registers" },
00196   { PIOCSRLC,      "PIOCSRLC",     "set run-on-last-close flag" },
00197   { PIOCSSIG,      "PIOCSSIG",     "set current signal" },
00198   { PIOCSTATUS,    "PIOCSTATUS",   "get process status" },
00199   { PIOCSTOP,      "PIOCSTOP",     "post stop request" },
00200   { PIOCSTRACE,    "PIOCSTRACE",   "set traced signal set" },
00201   { PIOCUNKILL,    "PIOCUNKILL",   "delete a signal" },
00202 #ifdef PIOCUSAGE        /* solaris */
00203   { PIOCUSAGE,     "PIOCUSAGE",    "get resource usage" },
00204 #endif
00205   { PIOCWSTOP,     "PIOCWSTOP",    "wait for process to stop" },
00206 
00207 #ifdef PIOCNTHR                         /* osf threads */
00208   { PIOCNTHR,      "PIOCNTHR",     "get thread count" },
00209   { PIOCRTINH,     "PIOCRTINH",    "reset inherit-on-thread-creation" },
00210   { PIOCSTINH,     "PIOCSTINH",    "set   inherit-on-thread-creation" },
00211   { PIOCTLIST,     "PIOCTLIST",    "get thread ids" },
00212   { PIOCXPTH,      "PIOCXPTH",     "translate port to thread handle" },
00213   { PIOCTRUN,      "PIOCTRUN",     "make thread runnable" },
00214   { PIOCTSTATUS,   "PIOCTSTATUS",  "get thread status" },
00215   { PIOCTSTOP,     "PIOCTSTOP",    "stop a thread" },
00216   /* ... TGTRACE TSTRACE TSSIG TKILL TUNKILL TCFAULT TGFAULT TSFAULT
00217      TGFPREG TSFPREG TGREG TSREG TACTION TTERM TABRUN TGENTRY TSENTRY
00218      TGEXIT TSEXIT TSHOLD ... thread functions */
00219 #endif /* osf threads */
00220   { -1,            NULL,           NULL }
00221 };
00222 
00223 int
00224 ioctl_with_trace (int fd, long opcode, void *ptr, char *file, int line)
00225 {
00226   int i = 0;
00227   int ret;
00228   int arg1;
00229 
00230   prepare_to_trace ();
00231 
00232   if (procfs_trace)
00233     {
00234       for (i = 0; ioctl_table[i].name != NULL; i++)
00235         if (ioctl_table[i].value == opcode)
00236           break;
00237 
00238       if (info_verbose)
00239         fprintf (procfs_file ? procfs_file : stdout, 
00240                  "%s:%d -- ", file, line);
00241       switch (opcode) {
00242       case PIOCSET:
00243         arg1 = ptr ? *(long *) ptr : 0;
00244         fprintf (procfs_file ? procfs_file : stdout, 
00245                  "ioctl (PIOCSET,   %s) %s\n", 
00246                  arg1 == PR_FORK  ? "PR_FORK"  :
00247                  arg1 == PR_RLC   ? "PR_RLC"   :
00248 #ifdef PR_ASYNC
00249                  arg1 == PR_ASYNC ? "PR_ASYNC" :
00250 #endif
00251                  "<unknown flag>",
00252                  info_verbose ? ioctl_table[i].desc : "");
00253         break;
00254       case PIOCRESET:
00255         arg1 = ptr ? *(long *) ptr : 0;
00256         fprintf (procfs_file ? procfs_file : stdout, 
00257                  "ioctl (PIOCRESET, %s) %s\n", 
00258                  arg1 == PR_FORK  ? "PR_FORK"  :
00259                  arg1 == PR_RLC   ? "PR_RLC"   :
00260 #ifdef PR_ASYNC
00261                  arg1 == PR_ASYNC ? "PR_ASYNC" :
00262 #endif
00263                  "<unknown flag>",
00264                  info_verbose ? ioctl_table[i].desc : "");
00265         break;
00266       case PIOCSTRACE:
00267         fprintf (procfs_file ? procfs_file : stdout, 
00268                  "ioctl (PIOCSTRACE) ");
00269         proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout,
00270                                      (sigset_t *) ptr, 0);
00271         break;
00272       case PIOCSFAULT:
00273         fprintf (procfs_file ? procfs_file : stdout, 
00274                  "ioctl (%s) ", 
00275                  opcode == PIOCSFAULT ? "PIOCSFAULT" : "PIOCGFAULT");
00276         proc_prettyfprint_faultset (procfs_file ? procfs_file : stdout,
00277                                     (fltset_t *) ptr, 0);
00278         break;
00279       case PIOCSENTRY:
00280         fprintf (procfs_file ? procfs_file : stdout, 
00281                  "ioctl (%s) ", 
00282                  opcode == PIOCSENTRY ? "PIOCSENTRY" : "PIOCGENTRY");
00283         proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout,
00284                                     (sysset_t *) ptr, 0);
00285         break;
00286       case PIOCSEXIT:
00287         fprintf (procfs_file ? procfs_file : stdout, 
00288                  "ioctl (%s) ", 
00289                  opcode == PIOCSEXIT ? "PIOCSEXIT" : "PIOCGEXIT");
00290         proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout,
00291                                     (sysset_t *) ptr, 0);
00292         break;
00293       case PIOCSHOLD:
00294         fprintf (procfs_file ? procfs_file : stdout, 
00295                  "ioctl (%s) ", 
00296                  opcode == PIOCSHOLD ? "PIOCSHOLD" : "PIOCGHOLD");
00297         proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout,
00298                                      (sigset_t *) ptr, 0);
00299         break;
00300       case PIOCSSIG:
00301         fprintf (procfs_file ? procfs_file : stdout, 
00302                  "ioctl (PIOCSSIG) ");
00303         proc_prettyfprint_signal (procfs_file ? procfs_file : stdout,
00304                                   ptr ? ((siginfo_t *) ptr)->si_signo : 0, 
00305                                   0);
00306         fprintf (procfs_file ? procfs_file : stdout, "\n");
00307         break;
00308       case PIOCRUN:
00309         fprintf (procfs_file ? procfs_file : stdout, 
00310                  "ioctl (PIOCRUN) ");
00311         
00312         arg1 = ptr ? *(long *) ptr : 0;
00313         if (arg1 & PRCSIG)
00314           fprintf (procfs_file ? procfs_file : stdout, "clearSig ");
00315         if (arg1 & PRCFAULT)
00316           fprintf (procfs_file ? procfs_file : stdout, "clearFlt ");
00317         if (arg1 & PRSTRACE)
00318           fprintf (procfs_file ? procfs_file : stdout, "setTrace ");
00319         if (arg1 & PRSHOLD)
00320           fprintf (procfs_file ? procfs_file : stdout, "setHold ");
00321         if (arg1 & PRSFAULT)
00322           fprintf (procfs_file ? procfs_file : stdout, "setFlt ");
00323         if (arg1 & PRSVADDR)
00324           fprintf (procfs_file ? procfs_file : stdout, "setVaddr ");
00325         if (arg1 & PRSTEP)
00326           fprintf (procfs_file ? procfs_file : stdout, "step ");
00327         if (arg1 & PRSABORT)
00328           fprintf (procfs_file ? procfs_file : stdout, "syscallAbort ");
00329         if (arg1 & PRSTOP)
00330           fprintf (procfs_file ? procfs_file : stdout, "stopReq ");
00331           
00332         fprintf (procfs_file ? procfs_file : stdout, "\n");
00333         break;
00334       case PIOCKILL:
00335         fprintf (procfs_file ? procfs_file : stdout, 
00336                  "ioctl (PIOCKILL) ");
00337         proc_prettyfprint_signal (procfs_file ? procfs_file : stdout,
00338                                   ptr ? *(long *) ptr : 0, 0);
00339         fprintf (procfs_file ? procfs_file : stdout, "\n");
00340         break;
00341 #ifdef PIOCSSPCACT
00342       case PIOCSSPCACT:
00343         fprintf (procfs_file ? procfs_file : stdout, 
00344                  "ioctl (PIOCSSPCACT) ");
00345         arg1 = ptr ? *(long *) ptr : 0;
00346         if (arg1 & PRFS_STOPFORK)
00347           fprintf (procfs_file ? procfs_file : stdout, "stopFork ");
00348         if (arg1 & PRFS_STOPEXEC)
00349           fprintf (procfs_file ? procfs_file : stdout, "stopExec ");
00350         if (arg1 & PRFS_STOPTERM)
00351           fprintf (procfs_file ? procfs_file : stdout, "stopTerm ");
00352         if (arg1 & PRFS_STOPTCR)
00353           fprintf (procfs_file ? procfs_file : stdout, "stopThreadCreate ");
00354         if (arg1 & PRFS_STOPTTERM)
00355           fprintf (procfs_file ? procfs_file : stdout, "stopThreadTerm ");
00356         if (arg1 & PRFS_KOLC)
00357           fprintf (procfs_file ? procfs_file : stdout, "killOnLastClose ");
00358         fprintf (procfs_file ? procfs_file : stdout, "\n");
00359         break;
00360 #endif /* PIOCSSPCACT */
00361       default:
00362         if (ioctl_table[i].name)
00363           fprintf (procfs_file ? procfs_file : stdout, 
00364                    "ioctl (%s) %s\n", 
00365                    ioctl_table[i].name,
00366                    info_verbose ? ioctl_table[i].desc : "");
00367         else
00368           fprintf (procfs_file ? procfs_file : stdout, 
00369                    "ioctl (<unknown %ld (0x%lx)) \n", opcode, opcode);
00370         break;
00371       }
00372       if (procfs_file)
00373         fflush (procfs_file);
00374     }
00375   errno = 0;
00376   ret = ioctl (fd, opcode, ptr);
00377   if (procfs_trace && ret < 0)
00378     {
00379       fprintf (procfs_file ? procfs_file : stdout, 
00380                "[ioctl (%s) FAILED! (%s)]\n",
00381                ioctl_table[i].name != NULL ? 
00382                ioctl_table[i].name : "<unknown>",
00383                safe_strerror (errno));
00384       if (procfs_file)
00385         fflush (procfs_file);
00386     }
00387 
00388   return ret;
00389 }
00390 
00391 #else   /* NEW_PROC_API */
00392 
00393 static struct trans rw_table[] = {
00394 #ifdef PCAGENT                  /* solaris */
00395   { PCAGENT,  "PCAGENT",  "create agent lwp with regs from argument" },
00396 #endif
00397   { PCCFAULT, "PCCFAULT", "clear current fault" },
00398 #ifdef PCCSIG                   /* solaris */
00399   { PCCSIG,   "PCCSIG",   "clear current signal" },
00400 #endif
00401 #ifdef PCDSTOP                  /* solaris */
00402   { PCDSTOP,  "PCDSTOP",  "post stop request" },
00403 #endif
00404   { PCKILL,   "PCKILL",   "post a signal" },
00405 #ifdef PCNICE                   /* solaris */
00406   { PCNICE,   "PCNICE",   "set nice priority" },
00407 #endif
00408 #ifdef PCREAD                   /* solaris */
00409   { PCREAD,   "PCREAD",   "read from the address space" },
00410   { PCWRITE,  "PCWRITE",  "write to the address space" },
00411 #endif
00412   { PCRUN,    "PCRUN",    "make process/lwp runnable" },
00413 #ifdef PCSASRS                  /* solaris 2.7 only */
00414   { PCSASRS,  "PCSASRS",  "set ancillary state registers" },
00415 #endif
00416 #ifdef PCSCRED                  /* solaris */
00417   { PCSCRED,  "PCSCRED",  "set process credentials" },
00418 #endif
00419   { PCSENTRY, "PCSENTRY", "set traced syscall entry set" },
00420   { PCSET,    "PCSET",    "set modes" },
00421   { PCSEXIT,  "PCSEXIT",  "set traced syscall exit  set" },
00422   { PCSFAULT, "PCSFAULT", "set traced fault set" },
00423   { PCSFPREG, "PCSFPREG", "set floating point registers" },
00424 #ifdef PCSHOLD                  /* solaris */
00425   { PCSHOLD,  "PCSHOLD",  "set signal mask" },
00426 #endif
00427   { PCSREG,   "PCSREG",   "set general registers" },
00428   { PCSSIG,   "PCSSIG",   "set current signal" },
00429   { PCSTOP,   "PCSTOP",   "post stop request and wait" },
00430   { PCSTRACE, "PCSTRACE", "set traced signal set" },
00431 #ifdef PCSVADDR                 /* solaris */
00432   { PCSVADDR, "PCSVADDR", "set pc virtual address" },
00433 #endif
00434 #ifdef PCSXREG                  /* solaris sparc only */
00435   { PCSXREG,  "PCSXREG",  "set extra registers" },
00436 #endif
00437 #ifdef PCTWSTOP                 /* solaris */
00438   { PCTWSTOP, "PCTWSTOP", "wait for stop, with timeout arg" },
00439 #endif
00440 #ifdef PCUNKILL                 /* solaris */
00441   { PCUNKILL, "PCUNKILL", "delete a pending signal" },
00442 #endif
00443 #ifdef PCUNSET                  /* solaris */
00444   { PCUNSET,  "PCUNSET",  "unset modes" },
00445 #endif
00446 #ifdef PCWATCH                  /* solaris */
00447   { PCWATCH,  "PCWATCH",  "set/unset watched memory area" },
00448 #endif
00449   { PCWSTOP,  "PCWSTOP",  "wait for process/lwp to stop, no timeout" },
00450   { 0,        NULL,      NULL }
00451 };
00452 
00453 static off_t lseek_offset;
00454 
00455 int
00456 write_with_trace (int fd, void *varg, size_t len, char *file, int line)
00457 {
00458   int i = ARRAY_SIZE (rw_table) - 1;
00459   int ret;
00460   procfs_ctl_t *arg = (procfs_ctl_t *) varg;
00461 
00462   prepare_to_trace ();
00463   if (procfs_trace)
00464     {
00465       procfs_ctl_t opcode = arg[0];
00466       for (i = 0; rw_table[i].name != NULL; i++)
00467         if (rw_table[i].value == opcode)
00468           break;
00469 
00470       if (info_verbose)
00471         fprintf (procfs_file ? procfs_file : stdout, 
00472                  "%s:%d -- ", file, line);
00473       switch (opcode) {
00474       case PCSET:
00475         fprintf (procfs_file ? procfs_file : stdout, 
00476                  "write (PCSET,   %s) %s\n", 
00477                  arg[1] == PR_FORK  ? "PR_FORK"  :
00478                  arg[1] == PR_RLC   ? "PR_RLC"   :
00479 #ifdef PR_ASYNC
00480                  arg[1] == PR_ASYNC ? "PR_ASYNC" :
00481 #endif
00482                  "<unknown flag>",
00483                  info_verbose ? rw_table[i].desc : "");
00484         break;
00485 #ifdef PCUNSET
00486       case PCUNSET:
00487 #endif
00488 #ifdef PCRESET
00489 #if PCRESET != PCUNSET
00490       case PCRESET:
00491 #endif
00492 #endif
00493         fprintf (procfs_file ? procfs_file : stdout, 
00494                  "write (PCRESET, %s) %s\n", 
00495                  arg[1] == PR_FORK  ? "PR_FORK"  :
00496                  arg[1] == PR_RLC   ? "PR_RLC"   :
00497 #ifdef PR_ASYNC
00498                  arg[1] == PR_ASYNC ? "PR_ASYNC" :
00499 #endif
00500                  "<unknown flag>",
00501                  info_verbose ? rw_table[i].desc : "");
00502         break;
00503       case PCSTRACE:
00504         fprintf (procfs_file ? procfs_file : stdout, 
00505                  "write (PCSTRACE) ");
00506         proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout,
00507                                      (sigset_t *) &arg[1], 0);
00508         break;
00509       case PCSFAULT:
00510         fprintf (procfs_file ? procfs_file : stdout, 
00511                  "write (PCSFAULT) ");
00512         proc_prettyfprint_faultset (procfs_file ? procfs_file : stdout,
00513                                     (fltset_t *) &arg[1], 0);
00514         break;
00515       case PCSENTRY:
00516         fprintf (procfs_file ? procfs_file : stdout, 
00517                  "write (PCSENTRY) ");
00518         proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout,
00519                                     (sysset_t *) &arg[1], 0);
00520         break;
00521       case PCSEXIT:
00522         fprintf (procfs_file ? procfs_file : stdout, 
00523                  "write (PCSEXIT) ");
00524         proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout,
00525                                     (sysset_t *) &arg[1], 0);
00526         break;
00527 #ifdef PCSHOLD
00528       case PCSHOLD:
00529         fprintf (procfs_file ? procfs_file : stdout, 
00530                  "write (PCSHOLD) ");
00531         proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout,
00532                                      (sigset_t *) &arg[1], 0);
00533         break;
00534 #endif
00535       case PCSSIG:
00536         fprintf (procfs_file ? procfs_file : stdout, 
00537                  "write (PCSSIG) ");
00538         proc_prettyfprint_signal (procfs_file ? procfs_file : stdout,
00539                                   arg[1] ? ((siginfo_t *) &arg[1])->si_signo 
00540                                          : 0, 
00541                                   0);
00542         fprintf (procfs_file ? procfs_file : stdout, "\n");
00543         break;
00544       case PCRUN:
00545         fprintf (procfs_file ? procfs_file : stdout, 
00546                  "write (PCRUN) ");
00547         if (arg[1] & PRCSIG)
00548           fprintf (procfs_file ? procfs_file : stdout, "clearSig ");
00549         if (arg[1] & PRCFAULT)
00550           fprintf (procfs_file ? procfs_file : stdout, "clearFlt ");
00551         if (arg[1] & PRSTEP)
00552           fprintf (procfs_file ? procfs_file : stdout, "step ");
00553 #ifdef PRSABORT
00554         if (arg[1] & PRSABORT)
00555           fprintf (procfs_file ? procfs_file : stdout, "syscallAbort ");
00556 #endif
00557 #ifdef PRSTOP
00558         if (arg[1] & PRSTOP)
00559           fprintf (procfs_file ? procfs_file : stdout, "stopReq ");
00560 #endif
00561           
00562         fprintf (procfs_file ? procfs_file : stdout, "\n");
00563         break;
00564       case PCKILL:
00565         fprintf (procfs_file ? procfs_file : stdout, 
00566                  "write (PCKILL) ");
00567         proc_prettyfprint_signal (procfs_file ? procfs_file : stdout,
00568                                   arg[1], 0);
00569         fprintf (procfs_file ? procfs_file : stdout, "\n");
00570         break;
00571       default:
00572         {
00573           if (rw_table[i].name)
00574             fprintf (procfs_file ? procfs_file : stdout, 
00575                      "write (%s) %s\n", 
00576                      rw_table[i].name, 
00577                      info_verbose ? rw_table[i].desc : "");
00578           else
00579             {
00580               if (lseek_offset != -1)
00581                 fprintf (procfs_file ? procfs_file : stdout, 
00582                          "write (<unknown>, %lud bytes at 0x%08lx) \n", 
00583                          (unsigned long) len, (unsigned long) lseek_offset);
00584               else
00585                 fprintf (procfs_file ? procfs_file : stdout, 
00586                          "write (<unknown>, %lud bytes) \n", 
00587                          (unsigned long) len);
00588             }
00589           break;
00590         }
00591       }
00592       if (procfs_file)
00593         fflush (procfs_file);
00594     }
00595   errno = 0;
00596   ret = write (fd, (void *) arg, len);
00597   if (procfs_trace && ret != len)
00598     {
00599       fprintf (procfs_file ? procfs_file : stdout, 
00600                "[write (%s) FAILED! (%s)]\n",
00601                rw_table[i].name != NULL ? 
00602                rw_table[i].name : "<unknown>", 
00603                safe_strerror (errno));
00604       if (procfs_file)
00605         fflush (procfs_file);
00606     }
00607 
00608   lseek_offset = -1;
00609   return ret;
00610 }
00611 
00612 off_t
00613 lseek_with_trace (int fd, off_t offset, int whence, char *file, int line)
00614 {
00615   off_t ret;
00616 
00617   prepare_to_trace ();
00618   errno = 0;
00619   ret = lseek (fd, offset, whence);
00620   lseek_offset = ret;
00621   if (procfs_trace && (ret == -1 || errno != 0))
00622     {
00623       fprintf (procfs_file ? procfs_file : stdout, 
00624                "[lseek (0x%08lx) FAILED! (%s)]\n", 
00625                (unsigned long) offset, safe_strerror (errno));
00626       if (procfs_file)
00627         fflush (procfs_file);
00628     }
00629 
00630   return ret;
00631 }
00632 
00633 #endif /* NEW_PROC_API */
00634 
00635 int
00636 open_with_trace (char *filename, int mode, char *file, int line)
00637 {
00638   int ret;
00639 
00640   prepare_to_trace ();
00641   errno = 0;
00642   ret = open (filename, mode);
00643   if (procfs_trace)
00644     {
00645       if (info_verbose)
00646         fprintf (procfs_file ? procfs_file : stdout, 
00647                  "%s:%d -- ", file, line);
00648 
00649       if (errno)
00650         {
00651           fprintf (procfs_file ? procfs_file : stdout, 
00652                    "[open FAILED! (%s) line %d]\\n", 
00653                    safe_strerror (errno), line);
00654         }
00655       else
00656         {
00657           fprintf (procfs_file ? procfs_file : stdout, 
00658                    "%d = open (%s, ", ret, filename);
00659           if (mode == O_RDONLY)
00660             fprintf (procfs_file ? procfs_file : stdout, "O_RDONLY) %d\n",
00661                      line);
00662           else if (mode == O_WRONLY)
00663             fprintf (procfs_file ? procfs_file : stdout, "O_WRONLY) %d\n",
00664                      line);
00665           else if (mode == O_RDWR)
00666             fprintf (procfs_file ? procfs_file : stdout, "O_RDWR)   %d\n",
00667                      line);
00668         }
00669       if (procfs_file)
00670         fflush (procfs_file);
00671     }
00672 
00673   return ret;
00674 }
00675 
00676 int
00677 close_with_trace (int fd, char *file, int line)
00678 {
00679   int ret;
00680 
00681   prepare_to_trace ();
00682   errno = 0;
00683   ret = close (fd);
00684   if (procfs_trace)
00685     {
00686       if (info_verbose)
00687         fprintf (procfs_file ? procfs_file : stdout, 
00688                  "%s:%d -- ", file, line);
00689       if (errno)
00690         fprintf (procfs_file ? procfs_file : stdout, 
00691                  "[close FAILED! (%s)]\n", safe_strerror (errno));
00692       else
00693         fprintf (procfs_file ? procfs_file : stdout, 
00694                  "%d = close (%d)\n", ret, fd);
00695       if (procfs_file)
00696         fflush (procfs_file);
00697     }
00698 
00699   return ret;
00700 }
00701 
00702 pid_t
00703 wait_with_trace (int *wstat, char *file, int line)
00704 {
00705   int ret, lstat = 0;
00706 
00707   prepare_to_trace ();
00708   if (procfs_trace)
00709     {
00710       if (info_verbose)
00711         fprintf (procfs_file ? procfs_file : stdout, 
00712                  "%s:%d -- ", file, line);
00713       fprintf (procfs_file ? procfs_file : stdout, 
00714                "wait (line %d) ", line);
00715       if (procfs_file)
00716         fflush (procfs_file);
00717     }
00718   errno = 0;
00719   ret = wait (&lstat);
00720   if (procfs_trace)
00721     {
00722       if (errno)
00723         fprintf (procfs_file ? procfs_file : stdout, 
00724                  "[wait FAILED! (%s)]\n", safe_strerror (errno));
00725       else
00726         fprintf (procfs_file ? procfs_file : stdout, 
00727                  "returned pid %d, status 0x%x\n", ret, lstat);
00728       if (procfs_file)
00729         fflush (procfs_file);
00730     }
00731   if (wstat)
00732     *wstat = lstat;
00733 
00734   return ret;
00735 }
00736 
00737 void
00738 procfs_note (char *msg, char *file, int line)
00739 {
00740   prepare_to_trace ();
00741   if (procfs_trace)
00742     {
00743       if (info_verbose)
00744         fprintf (procfs_file ? procfs_file : stdout, 
00745                  "%s:%d -- ", file, line);
00746       fprintf (procfs_file ? procfs_file : stdout, "%s", msg);
00747       if (procfs_file)
00748         fflush (procfs_file);
00749     }
00750 }
00751 
00752 void
00753 proc_prettyfprint_status (long flags, int why, int what, int thread)
00754 {
00755   prepare_to_trace ();
00756   if (procfs_trace)
00757     {
00758       if (thread)
00759         fprintf (procfs_file ? procfs_file : stdout,
00760                  "Thread %d: ", thread);
00761 
00762       proc_prettyfprint_flags (procfs_file ? procfs_file : stdout, 
00763                                flags, 0);
00764 
00765       if (flags & (PR_STOPPED | PR_ISTOP))
00766         proc_prettyfprint_why (procfs_file ? procfs_file : stdout, 
00767                                why, what, 0);
00768       if (procfs_file)
00769         fflush (procfs_file);
00770     }
00771 }
00772 
00773 
00774 /* Provide a prototype to silence -Wmissing-prototypes.  */
00775 extern void _initialize_proc_api (void);
00776 
00777 void
00778 _initialize_proc_api (void)
00779 {
00780   struct cmd_list_element *c;
00781 
00782   add_setshow_boolean_cmd ("procfs-trace", no_class, &procfs_trace, _("\
00783 Set tracing for /proc api calls."), _("\
00784 Show tracing for /proc api calls."), NULL,
00785                            set_procfs_trace_cmd,
00786                            NULL, /* FIXME: i18n: */
00787                            &setlist, &showlist);
00788 
00789   add_setshow_filename_cmd ("procfs-file", no_class, &procfs_filename, _("\
00790 Set filename for /proc tracefile."), _("\
00791 Show filename for /proc tracefile."), NULL,
00792                             set_procfs_file_cmd,
00793                             NULL, /* FIXME: i18n: */
00794                             &setlist, &showlist);
00795 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines