gdb/proc-api.c - gdb

Global variables defined

Data types defined

Functions defined

Macros defined

Source code

  1. /* Machine independent support for SVR4 /proc (process file system) for GDB.

  2.    Copyright (C) 1999-2015 Free Software Foundation, Inc.

  3.    Written by Michael Snyder at Cygnus Solutions.
  4.    Based on work by Fred Fish, Stu Grossman, Geoff Noer, and others.

  5.    This file is part of GDB.

  6.    This program is free software; you can redistribute it and/or modify
  7.    it under the terms of the GNU General Public License as published by
  8.    the Free Software Foundation; either version 3 of the License, or
  9.    (at your option) any later version.

  10.    This program is distributed in the hope that it will be useful,
  11.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.    GNU General Public License for more details.

  14.    You should have received a copy of the GNU General Public License
  15.    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

  16. /*
  17. * Pretty-print trace of api calls to the /proc api
  18. * (ioctl or read/write calls).
  19. *
  20. */

  21. #include "defs.h"
  22. #include "gdbcmd.h"
  23. #include "completer.h"

  24. #if defined (NEW_PROC_API)
  25. #define _STRUCTURED_PROC 1
  26. #endif

  27. #include <sys/types.h>
  28. #include <sys/procfs.h>
  29. #ifdef HAVE_SYS_PROC_H
  30. #include <sys/proc.h>        /* for struct proc */
  31. #endif
  32. #ifdef HAVE_SYS_USER_H
  33. #include <sys/user.h>        /* for struct user */
  34. #endif
  35. #include <fcntl.h>        /* for O_RDWR etc.  */
  36. #include "gdb_wait.h"

  37. #include "proc-utils.h"

  38. /*  Much of the information used in the /proc interface, particularly for
  39.     printing status information, is kept as tables of structures of the
  40.     following form.  These tables can be used to map numeric values to
  41.     their symbolic names and to a string that describes their specific use.  */

  42. struct trans {
  43.   long value;                   /* The numeric value */
  44.   char *name;                   /* The equivalent symbolic value */
  45.   char *desc;                   /* Short description of value */
  46. };

  47. static int   procfs_trace    = 0;
  48. static FILE *procfs_file     = NULL;
  49. static char *procfs_filename = "procfs_trace";

  50. static void
  51. prepare_to_trace (void)
  52. {
  53.   if (procfs_trace)                        /* if procfs tracing turned on */
  54.     if (procfs_file == NULL)                /* if output file not yet open */
  55.       if (procfs_filename != NULL)        /* if output filename known */
  56.         procfs_file = fopen (procfs_filename, "a");        /* open output file */
  57. }

  58. static void
  59. set_procfs_trace_cmd (char *args, int from_tty, struct cmd_list_element *c)
  60. {
  61. #if 0        /* not sure what I might actually need to do here, if anything */
  62.   if (procfs_file)
  63.     fflush (procfs_file);
  64. #endif
  65. }

  66. static void
  67. set_procfs_file_cmd (char *args, int from_tty, struct cmd_list_element *c)
  68. {
  69.   /* Just changed the filename for procfs tracing.
  70.      If a file was already open, close it.  */
  71.   if (procfs_file)
  72.     fclose (procfs_file);
  73.   procfs_file = NULL;
  74. }


  75. #ifndef NEW_PROC_API

  76. static struct trans ioctl_table[] = {
  77. #ifdef PIOCACINFO                        /* irix */
  78.   { PIOCACINFO,    "PIOCACINFO",   "get process account info" },
  79. #endif
  80.   { PIOCACTION,    "PIOCACTION",   "get signal action structs" },
  81. #ifdef PIOCARGUMENTS                        /* osf */
  82.   { PIOCARGUMENTS, "PIOCARGUMENTS", "command line args" },
  83. #endif
  84. #ifdef PIOCAUXV                                /* solaris aux vectors */
  85.   { PIOCAUXV,      "PIOCAUXV",     "get aux vector" },
  86.   { PIOCNAUXV,     "PIOCNAUXV",    "get number of aux vector entries" },
  87. #endif /* AUXV */
  88.   { PIOCCFAULT,    "PIOCCFAULT",   "clear current fault" },
  89.   { PIOCCRED,      "PIOCCRED",     "get process credentials" },
  90. #ifdef PIOCENEVCTRS                        /* irix event counters */
  91.   { PIOCENEVCTRS,    "PIOCENEVCTRS",    "acquire and start event counters" },
  92.   { PIOCGETEVCTRL,   "PIOCGETEVCTRL",   "get control info of event counters" },
  93.   { PIOCGETEVCTRS,   "PIOCGETEVCTRS",   "dump event counters" },
  94.   { PIOCGETPREVCTRS, "PIOCGETPREVCTRS", "dump event counters & prusage info" },
  95.   { PIOCRELEVCTRS,   "PIOCRELEVCTRS",   "release/stop event counters" },
  96.   { PIOCSETEVCTRL,   "PIOCSETEVCTRL",   "set control info of event counters" },
  97.   { PIOCGETPTIMER,   "PIOCGETPTIMER",   "get process timers" },
  98. #endif        /* irix event counters */
  99.   { PIOCGENTRY,    "PIOCGENTRY",   "get traced syscall entry set" },
  100. #if defined (PIOCGETPR)
  101.   { PIOCGETPR,     "PIOCGETPR",    "read struct proc" },
  102. #endif
  103. #if defined (PIOCGETU)
  104.   { PIOCGETU,      "PIOCGETU",     "read user area" },
  105. #endif
  106. #if defined (PIOCGETUTK) && (defined(KERNEL) || defined(SHOW_UTT)) /* osf */
  107.   { PIOCGETUTK,  "PIOCGETUTK", "get the utask struct" },
  108. #endif
  109.   { PIOCGEXIT,     "PIOCGEXIT",    "get traced syscall exit  set" },
  110.   { PIOCGFAULT,    "PIOCGFAULT",   "get traced fault set" },
  111. #ifdef PIOCGFPCR                        /* osf */
  112.   { PIOCGFPCR,     "PIOCGFPCR",    "get FP control register" },
  113.   { PIOCSFPCR,     "PIOCSFPCR",    "set FP conrtol register" },
  114. #endif
  115.   { PIOCGFPREG,    "PIOCGFPREG",   "get floating point registers" },
  116.   { PIOCGHOLD,     "PIOCGHOLD",    "get held signal set" },
  117.   { PIOCGREG,      "PIOCGREG",     "get general registers" },
  118.   { PIOCGROUPS,    "PIOCGROUPS",   "get supplementary groups" },
  119. #ifdef PIOCGSPCACT                        /* osf */
  120.   { PIOCGSPCACT,   "PIOCGSPCACT""get special action" },
  121.   { PIOCSSPCACT,   "PIOCSSPCACT""set special action" },
  122. #endif
  123.   { PIOCGTRACE,    "PIOCGTRACE",   "get traced signal set" },
  124. #ifdef PIOCGWATCH                        /* irix watchpoints */
  125.   { PIOCGWATCH,    "PIOCGWATCH",   "get watchpoint" },
  126.   { PIOCSWATCH,    "PIOCSWATCH",   "set watchpoint" },
  127.   { PIOCNWATCH,    "PIOCNWATCH",   "get number of watchpoints" },
  128. #endif        /* irix watchpoints */
  129. #ifdef PIOCGWIN                                /* solaris sparc */
  130.   { PIOCGWIN,      "PIOCGWIN",     "get gwindows_t" },
  131. #endif
  132. #ifdef PIOCGXREG                        /* solaris sparc extra regs */
  133.   { PIOCGXREGSIZE, "PIOCXREGSIZE", "get extra register state size" },
  134.   { PIOCGXREG,     "PIOCGXREG",    "get extra register state" },
  135.   { PIOCSXREG,     "PIOCSXREG",    "set extra register state" },
  136. #endif /* XREG */
  137.   { PIOCKILL,      "PIOCKILL",     "send signal" },
  138. #ifdef PIOCLDT                                /* solaris i386 */
  139.   { PIOCLDT,       "PIOCLDT",      "get LDT" },
  140.   { PIOCNLDT,      "PIOCNLDT",     "get number of LDT entries" },
  141. #endif
  142. #ifdef PIOCLSTATUS                        /* solaris */
  143.   { PIOCLSTATUS,   "PIOCLSTATUS""get status of all lwps" },
  144.   { PIOCLUSAGE,    "PIOCLUSAGE",   "get resource usage of all lwps" },
  145.   { PIOCOPENLWP,   "PIOCOPENLWP""get lwp file descriptor" },
  146.   { PIOCLWPIDS,    "PIOCLWPIDS",   "get lwp identifiers" },
  147. #endif /* LWP */
  148.   { PIOCMAP,       "PIOCMAP",      "get memory map information" },
  149.   { PIOCMAXSIG,    "PIOCMAXSIG",   "get max signal number" },
  150.   { PIOCNICE,      "PIOCNICE",     "set nice priority" },
  151.   { PIOCNMAP,      "PIOCNMAP",     "get number of memory mappings" },
  152.   { PIOCOPENM,     "PIOCOPENM",    "open mapped object for reading" },
  153. #ifdef PIOCOPENMOBS                        /* osf */
  154.   { PIOCOPENMOBS,  "PIOCOPENMOBS", "open mapped object" },
  155. #endif
  156. #ifdef PIOCOPENPD        /* solaris */
  157.   { PIOCOPENPD,    "PIOCOPENPD",   "get page data file descriptor" },
  158. #endif
  159.   { PIOCPSINFO,    "PIOCPSINFO",   "get ps(1) information" },
  160.   { PIOCRESET,     "PIOCRESET",    "reset process flags" },
  161.   { PIOCRFORK,     "PIOCRFORK",    "reset inherit-on-fork flag" },
  162.   { PIOCRRLC,      "PIOCRRLC",     "reset run-on-last-close flag" },
  163.   { PIOCRUN,       "PIOCRUN",      "make process runnable" },
  164. #ifdef PIOCSAVECCNTRS                        /* irix */
  165.   { PIOCSAVECCNTRS, "PIOCSAVECCNTRS", "parent gets child cntrs" },
  166. #endif
  167.   { PIOCSENTRY,    "PIOCSENTRY",   "set traced syscall entry set" },
  168.   { PIOCSET,       "PIOCSET",      "set process flags" },
  169.   { PIOCSEXIT,     "PIOCSEXIT",    "set traced syscall exit  set" },
  170.   { PIOCSFAULT,    "PIOCSFAULT",   "set traced fault set" },
  171.   { PIOCSFORK,     "PIOCSFORK",    "set inherit-on-fork flag" },
  172.   { PIOCSFPREG,    "PIOCSFPREG",   "set floating point registers" },
  173.   { PIOCSHOLD,     "PIOCSHOLD",    "set held signal set" },
  174.   { PIOCSREG,      "PIOCSREG",     "set general registers" },
  175.   { PIOCSRLC,      "PIOCSRLC",     "set run-on-last-close flag" },
  176.   { PIOCSSIG,      "PIOCSSIG",     "set current signal" },
  177.   { PIOCSTATUS,    "PIOCSTATUS",   "get process status" },
  178.   { PIOCSTOP,      "PIOCSTOP",     "post stop request" },
  179.   { PIOCSTRACE,    "PIOCSTRACE",   "set traced signal set" },
  180.   { PIOCUNKILL,    "PIOCUNKILL",   "delete a signal" },
  181. #ifdef PIOCUSAGE        /* solaris */
  182.   { PIOCUSAGE,     "PIOCUSAGE",    "get resource usage" },
  183. #endif
  184.   { PIOCWSTOP,     "PIOCWSTOP",    "wait for process to stop" },

  185. #ifdef PIOCNTHR                                /* osf threads */
  186.   { PIOCNTHR,      "PIOCNTHR",     "get thread count" },
  187.   { PIOCRTINH,     "PIOCRTINH",    "reset inherit-on-thread-creation" },
  188.   { PIOCSTINH,     "PIOCSTINH",    "set   inherit-on-thread-creation" },
  189.   { PIOCTLIST,     "PIOCTLIST",    "get thread ids" },
  190.   { PIOCXPTH,      "PIOCXPTH",     "translate port to thread handle" },
  191.   { PIOCTRUN,      "PIOCTRUN",     "make thread runnable" },
  192.   { PIOCTSTATUS,   "PIOCTSTATUS""get thread status" },
  193.   { PIOCTSTOP,     "PIOCTSTOP",    "stop a thread" },
  194.   /* ... TGTRACE TSTRACE TSSIG TKILL TUNKILL TCFAULT TGFAULT TSFAULT
  195.      TGFPREG TSFPREG TGREG TSREG TACTION TTERM TABRUN TGENTRY TSENTRY
  196.      TGEXIT TSEXIT TSHOLD ... thread functions */
  197. #endif /* osf threads */
  198.   { -1,            NULL,           NULL }
  199. };

  200. int
  201. ioctl_with_trace (int fd, long opcode, void *ptr, char *file, int line)
  202. {
  203.   int i = 0;
  204.   int ret;
  205.   int arg1;

  206.   prepare_to_trace ();

  207.   if (procfs_trace)
  208.     {
  209.       for (i = 0; ioctl_table[i].name != NULL; i++)
  210.         if (ioctl_table[i].value == opcode)
  211.           break;

  212.       if (info_verbose)
  213.         fprintf (procfs_file ? procfs_file : stdout,
  214.                  "%s:%d -- ", file, line);
  215.       switch (opcode) {
  216.       case PIOCSET:
  217.         arg1 = ptr ? *(long *) ptr : 0;
  218.         fprintf (procfs_file ? procfs_file : stdout,
  219.                  "ioctl (PIOCSET,   %s) %s\n",
  220.                  arg1 == PR_FORK  ? "PR_FORK"  :
  221.                  arg1 == PR_RLC   ? "PR_RLC"   :
  222. #ifdef PR_ASYNC
  223.                  arg1 == PR_ASYNC ? "PR_ASYNC" :
  224. #endif
  225.                  "<unknown flag>",
  226.                  info_verbose ? ioctl_table[i].desc : "");
  227.         break;
  228.       case PIOCRESET:
  229.         arg1 = ptr ? *(long *) ptr : 0;
  230.         fprintf (procfs_file ? procfs_file : stdout,
  231.                  "ioctl (PIOCRESET, %s) %s\n",
  232.                  arg1 == PR_FORK  ? "PR_FORK"  :
  233.                  arg1 == PR_RLC   ? "PR_RLC"   :
  234. #ifdef PR_ASYNC
  235.                  arg1 == PR_ASYNC ? "PR_ASYNC" :
  236. #endif
  237.                  "<unknown flag>",
  238.                  info_verbose ? ioctl_table[i].desc : "");
  239.         break;
  240.       case PIOCSTRACE:
  241.         fprintf (procfs_file ? procfs_file : stdout,
  242.                  "ioctl (PIOCSTRACE) ");
  243.         proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout,
  244.                                      (sigset_t *) ptr, 0);
  245.         break;
  246.       case PIOCSFAULT:
  247.         fprintf (procfs_file ? procfs_file : stdout,
  248.                  "ioctl (%s) ",
  249.                  opcode == PIOCSFAULT ? "PIOCSFAULT" : "PIOCGFAULT");
  250.         proc_prettyfprint_faultset (procfs_file ? procfs_file : stdout,
  251.                                     (fltset_t *) ptr, 0);
  252.         break;
  253.       case PIOCSENTRY:
  254.         fprintf (procfs_file ? procfs_file : stdout,
  255.                  "ioctl (%s) ",
  256.                  opcode == PIOCSENTRY ? "PIOCSENTRY" : "PIOCGENTRY");
  257.         proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout,
  258.                                     (sysset_t *) ptr, 0);
  259.         break;
  260.       case PIOCSEXIT:
  261.         fprintf (procfs_file ? procfs_file : stdout,
  262.                  "ioctl (%s) ",
  263.                  opcode == PIOCSEXIT ? "PIOCSEXIT" : "PIOCGEXIT");
  264.         proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout,
  265.                                     (sysset_t *) ptr, 0);
  266.         break;
  267.       case PIOCSHOLD:
  268.         fprintf (procfs_file ? procfs_file : stdout,
  269.                  "ioctl (%s) ",
  270.                  opcode == PIOCSHOLD ? "PIOCSHOLD" : "PIOCGHOLD");
  271.         proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout,
  272.                                      (sigset_t *) ptr, 0);
  273.         break;
  274.       case PIOCSSIG:
  275.         fprintf (procfs_file ? procfs_file : stdout,
  276.                  "ioctl (PIOCSSIG) ");
  277.         proc_prettyfprint_signal (procfs_file ? procfs_file : stdout,
  278.                                   ptr ? ((siginfo_t *) ptr)->si_signo : 0,
  279.                                   0);
  280.         fprintf (procfs_file ? procfs_file : stdout, "\n");
  281.         break;
  282.       case PIOCRUN:
  283.         fprintf (procfs_file ? procfs_file : stdout,
  284.                  "ioctl (PIOCRUN) ");

  285.         arg1 = ptr ? *(long *) ptr : 0;
  286.         if (arg1 & PRCSIG)
  287.           fprintf (procfs_file ? procfs_file : stdout, "clearSig ");
  288.         if (arg1 & PRCFAULT)
  289.           fprintf (procfs_file ? procfs_file : stdout, "clearFlt ");
  290.         if (arg1 & PRSTRACE)
  291.           fprintf (procfs_file ? procfs_file : stdout, "setTrace ");
  292.         if (arg1 & PRSHOLD)
  293.           fprintf (procfs_file ? procfs_file : stdout, "setHold ");
  294.         if (arg1 & PRSFAULT)
  295.           fprintf (procfs_file ? procfs_file : stdout, "setFlt ");
  296.         if (arg1 & PRSVADDR)
  297.           fprintf (procfs_file ? procfs_file : stdout, "setVaddr ");
  298.         if (arg1 & PRSTEP)
  299.           fprintf (procfs_file ? procfs_file : stdout, "step ");
  300.         if (arg1 & PRSABORT)
  301.           fprintf (procfs_file ? procfs_file : stdout, "syscallAbort ");
  302.         if (arg1 & PRSTOP)
  303.           fprintf (procfs_file ? procfs_file : stdout, "stopReq ");

  304.         fprintf (procfs_file ? procfs_file : stdout, "\n");
  305.         break;
  306.       case PIOCKILL:
  307.         fprintf (procfs_file ? procfs_file : stdout,
  308.                  "ioctl (PIOCKILL) ");
  309.         proc_prettyfprint_signal (procfs_file ? procfs_file : stdout,
  310.                                   ptr ? *(long *) ptr : 0, 0);
  311.         fprintf (procfs_file ? procfs_file : stdout, "\n");
  312.         break;
  313. #ifdef PIOCSSPCACT
  314.       case PIOCSSPCACT:
  315.         fprintf (procfs_file ? procfs_file : stdout,
  316.                  "ioctl (PIOCSSPCACT) ");
  317.         arg1 = ptr ? *(long *) ptr : 0;
  318.         if (arg1 & PRFS_STOPFORK)
  319.           fprintf (procfs_file ? procfs_file : stdout, "stopFork ");
  320.         if (arg1 & PRFS_STOPEXEC)
  321.           fprintf (procfs_file ? procfs_file : stdout, "stopExec ");
  322.         if (arg1 & PRFS_STOPTERM)
  323.           fprintf (procfs_file ? procfs_file : stdout, "stopTerm ");
  324.         if (arg1 & PRFS_STOPTCR)
  325.           fprintf (procfs_file ? procfs_file : stdout, "stopThreadCreate ");
  326.         if (arg1 & PRFS_STOPTTERM)
  327.           fprintf (procfs_file ? procfs_file : stdout, "stopThreadTerm ");
  328.         if (arg1 & PRFS_KOLC)
  329.           fprintf (procfs_file ? procfs_file : stdout, "killOnLastClose ");
  330.         fprintf (procfs_file ? procfs_file : stdout, "\n");
  331.         break;
  332. #endif /* PIOCSSPCACT */
  333.       default:
  334.         if (ioctl_table[i].name)
  335.           fprintf (procfs_file ? procfs_file : stdout,
  336.                    "ioctl (%s) %s\n",
  337.                    ioctl_table[i].name,
  338.                    info_verbose ? ioctl_table[i].desc : "");
  339.         else
  340.           fprintf (procfs_file ? procfs_file : stdout,
  341.                    "ioctl (<unknown %ld (0x%lx)) \n", opcode, opcode);
  342.         break;
  343.       }
  344.       if (procfs_file)
  345.         fflush (procfs_file);
  346.     }
  347.   errno = 0;
  348.   ret = ioctl (fd, opcode, ptr);
  349.   if (procfs_trace && ret < 0)
  350.     {
  351.       fprintf (procfs_file ? procfs_file : stdout,
  352.                "[ioctl (%s) FAILED! (%s)]\n",
  353.                ioctl_table[i].name != NULL ?
  354.                ioctl_table[i].name : "<unknown>",
  355.                safe_strerror (errno));
  356.       if (procfs_file)
  357.         fflush (procfs_file);
  358.     }

  359.   return ret;
  360. }

  361. #else        /* NEW_PROC_API */

  362. static struct trans rw_table[] = {
  363. #ifdef PCAGENT                        /* solaris */
  364.   { PCAGENT,  "PCAGENT""create agent lwp with regs from argument" },
  365. #endif
  366.   { PCCFAULT, "PCCFAULT", "clear current fault" },
  367. #ifdef PCCSIG                        /* solaris */
  368.   { PCCSIG,   "PCCSIG",   "clear current signal" },
  369. #endif
  370. #ifdef PCDSTOP                        /* solaris */
  371.   { PCDSTOP,  "PCDSTOP""post stop request" },
  372. #endif
  373.   { PCKILL,   "PCKILL",   "post a signal" },
  374. #ifdef PCNICE                        /* solaris */
  375.   { PCNICE,   "PCNICE",   "set nice priority" },
  376. #endif
  377. #ifdef PCREAD                        /* solaris */
  378.   { PCREAD,   "PCREAD",   "read from the address space" },
  379.   { PCWRITE,  "PCWRITE""write to the address space" },
  380. #endif
  381.   { PCRUN,    "PCRUN",    "make process/lwp runnable" },
  382. #ifdef PCSASRS                        /* solaris 2.7 only */
  383.   { PCSASRS,  "PCSASRS""set ancillary state registers" },
  384. #endif
  385. #ifdef PCSCRED                        /* solaris */
  386.   { PCSCRED,  "PCSCRED""set process credentials" },
  387. #endif
  388.   { PCSENTRY, "PCSENTRY", "set traced syscall entry set" },
  389.   { PCSET,    "PCSET",    "set modes" },
  390.   { PCSEXIT,  "PCSEXIT""set traced syscall exit  set" },
  391.   { PCSFAULT, "PCSFAULT", "set traced fault set" },
  392.   { PCSFPREG, "PCSFPREG", "set floating point registers" },
  393. #ifdef PCSHOLD                        /* solaris */
  394.   { PCSHOLD,  "PCSHOLD""set signal mask" },
  395. #endif
  396.   { PCSREG,   "PCSREG",   "set general registers" },
  397.   { PCSSIG,   "PCSSIG",   "set current signal" },
  398.   { PCSTOP,   "PCSTOP",   "post stop request and wait" },
  399.   { PCSTRACE, "PCSTRACE", "set traced signal set" },
  400. #ifdef PCSVADDR                        /* solaris */
  401.   { PCSVADDR, "PCSVADDR", "set pc virtual address" },
  402. #endif
  403. #ifdef PCSXREG                        /* solaris sparc only */
  404.   { PCSXREG,  "PCSXREG""set extra registers" },
  405. #endif
  406. #ifdef PCTWSTOP                        /* solaris */
  407.   { PCTWSTOP, "PCTWSTOP", "wait for stop, with timeout arg" },
  408. #endif
  409. #ifdef PCUNKILL                        /* solaris */
  410.   { PCUNKILL, "PCUNKILL", "delete a pending signal" },
  411. #endif
  412. #ifdef PCUNSET                        /* solaris */
  413.   { PCUNSET,  "PCUNSET""unset modes" },
  414. #endif
  415. #ifdef PCWATCH                        /* solaris */
  416.   { PCWATCH,  "PCWATCH""set/unset watched memory area" },
  417. #endif
  418.   { PCWSTOP,  "PCWSTOP""wait for process/lwp to stop, no timeout" },
  419.   { 0,        NULL,      NULL }
  420. };

  421. static off_t lseek_offset;

  422. int
  423. write_with_trace (int fd, void *varg, size_t len, char *file, int line)
  424. {
  425.   int i = ARRAY_SIZE (rw_table) - 1;
  426.   int ret;
  427.   procfs_ctl_t *arg = (procfs_ctl_t *) varg;

  428.   prepare_to_trace ();
  429.   if (procfs_trace)
  430.     {
  431.       procfs_ctl_t opcode = arg[0];
  432.       for (i = 0; rw_table[i].name != NULL; i++)
  433.         if (rw_table[i].value == opcode)
  434.           break;

  435.       if (info_verbose)
  436.         fprintf (procfs_file ? procfs_file : stdout,
  437.                  "%s:%d -- ", file, line);
  438.       switch (opcode) {
  439.       case PCSET:
  440.         fprintf (procfs_file ? procfs_file : stdout,
  441.                  "write (PCSET,   %s) %s\n",
  442.                  arg[1] == PR_FORK  ? "PR_FORK"  :
  443.                  arg[1] == PR_RLC   ? "PR_RLC"   :
  444. #ifdef PR_ASYNC
  445.                  arg[1] == PR_ASYNC ? "PR_ASYNC" :
  446. #endif
  447.                  "<unknown flag>",
  448.                  info_verbose ? rw_table[i].desc : "");
  449.         break;
  450. #ifdef PCUNSET
  451.       case PCUNSET:
  452. #endif
  453. #ifdef PCRESET
  454. #if PCRESET != PCUNSET
  455.       case PCRESET:
  456. #endif
  457. #endif
  458.         fprintf (procfs_file ? procfs_file : stdout,
  459.                  "write (PCRESET, %s) %s\n",
  460.                  arg[1] == PR_FORK  ? "PR_FORK"  :
  461.                  arg[1] == PR_RLC   ? "PR_RLC"   :
  462. #ifdef PR_ASYNC
  463.                  arg[1] == PR_ASYNC ? "PR_ASYNC" :
  464. #endif
  465.                  "<unknown flag>",
  466.                  info_verbose ? rw_table[i].desc : "");
  467.         break;
  468.       case PCSTRACE:
  469.         fprintf (procfs_file ? procfs_file : stdout,
  470.                  "write (PCSTRACE) ");
  471.         proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout,
  472.                                      (sigset_t *) &arg[1], 0);
  473.         break;
  474.       case PCSFAULT:
  475.         fprintf (procfs_file ? procfs_file : stdout,
  476.                  "write (PCSFAULT) ");
  477.         proc_prettyfprint_faultset (procfs_file ? procfs_file : stdout,
  478.                                     (fltset_t *) &arg[1], 0);
  479.         break;
  480.       case PCSENTRY:
  481.         fprintf (procfs_file ? procfs_file : stdout,
  482.                  "write (PCSENTRY) ");
  483.         proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout,
  484.                                     (sysset_t *) &arg[1], 0);
  485.         break;
  486.       case PCSEXIT:
  487.         fprintf (procfs_file ? procfs_file : stdout,
  488.                  "write (PCSEXIT) ");
  489.         proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout,
  490.                                     (sysset_t *) &arg[1], 0);
  491.         break;
  492. #ifdef PCSHOLD
  493.       case PCSHOLD:
  494.         fprintf (procfs_file ? procfs_file : stdout,
  495.                  "write (PCSHOLD) ");
  496.         proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout,
  497.                                      (sigset_t *) &arg[1], 0);
  498.         break;
  499. #endif
  500.       case PCSSIG:
  501.         fprintf (procfs_file ? procfs_file : stdout,
  502.                  "write (PCSSIG) ");
  503.         proc_prettyfprint_signal (procfs_file ? procfs_file : stdout,
  504.                                   arg[1] ? ((siginfo_t *) &arg[1])->si_signo
  505.                                          : 0,
  506.                                   0);
  507.         fprintf (procfs_file ? procfs_file : stdout, "\n");
  508.         break;
  509.       case PCRUN:
  510.         fprintf (procfs_file ? procfs_file : stdout,
  511.                  "write (PCRUN) ");
  512.         if (arg[1] & PRCSIG)
  513.           fprintf (procfs_file ? procfs_file : stdout, "clearSig ");
  514.         if (arg[1] & PRCFAULT)
  515.           fprintf (procfs_file ? procfs_file : stdout, "clearFlt ");
  516.         if (arg[1] & PRSTEP)
  517.           fprintf (procfs_file ? procfs_file : stdout, "step ");
  518. #ifdef PRSABORT
  519.         if (arg[1] & PRSABORT)
  520.           fprintf (procfs_file ? procfs_file : stdout, "syscallAbort ");
  521. #endif
  522. #ifdef PRSTOP
  523.         if (arg[1] & PRSTOP)
  524.           fprintf (procfs_file ? procfs_file : stdout, "stopReq ");
  525. #endif

  526.         fprintf (procfs_file ? procfs_file : stdout, "\n");
  527.         break;
  528.       case PCKILL:
  529.         fprintf (procfs_file ? procfs_file : stdout,
  530.                  "write (PCKILL) ");
  531.         proc_prettyfprint_signal (procfs_file ? procfs_file : stdout,
  532.                                   arg[1], 0);
  533.         fprintf (procfs_file ? procfs_file : stdout, "\n");
  534.         break;
  535.       default:
  536.         {
  537.           if (rw_table[i].name)
  538.             fprintf (procfs_file ? procfs_file : stdout,
  539.                      "write (%s) %s\n",
  540.                      rw_table[i].name,
  541.                      info_verbose ? rw_table[i].desc : "");
  542.           else
  543.             {
  544.               if (lseek_offset != -1)
  545.                 fprintf (procfs_file ? procfs_file : stdout,
  546.                          "write (<unknown>, %lud bytes at 0x%08lx) \n",
  547.                          (unsigned long) len, (unsigned long) lseek_offset);
  548.               else
  549.                 fprintf (procfs_file ? procfs_file : stdout,
  550.                          "write (<unknown>, %lud bytes) \n",
  551.                          (unsigned long) len);
  552.             }
  553.           break;
  554.         }
  555.       }
  556.       if (procfs_file)
  557.         fflush (procfs_file);
  558.     }
  559.   errno = 0;
  560.   ret = write (fd, (void *) arg, len);
  561.   if (procfs_trace && ret != len)
  562.     {
  563.       fprintf (procfs_file ? procfs_file : stdout,
  564.                "[write (%s) FAILED! (%s)]\n",
  565.                rw_table[i].name != NULL ?
  566.                rw_table[i].name : "<unknown>",
  567.                safe_strerror (errno));
  568.       if (procfs_file)
  569.         fflush (procfs_file);
  570.     }

  571.   lseek_offset = -1;
  572.   return ret;
  573. }

  574. off_t
  575. lseek_with_trace (int fd, off_t offset, int whence, char *file, int line)
  576. {
  577.   off_t ret;

  578.   prepare_to_trace ();
  579.   errno = 0;
  580.   ret = lseek (fd, offset, whence);
  581.   lseek_offset = ret;
  582.   if (procfs_trace && (ret == -1 || errno != 0))
  583.     {
  584.       fprintf (procfs_file ? procfs_file : stdout,
  585.                "[lseek (0x%08lx) FAILED! (%s)]\n",
  586.                (unsigned long) offset, safe_strerror (errno));
  587.       if (procfs_file)
  588.         fflush (procfs_file);
  589.     }

  590.   return ret;
  591. }

  592. #endif /* NEW_PROC_API */

  593. int
  594. open_with_trace (char *filename, int mode, char *file, int line)
  595. {
  596.   int ret;

  597.   prepare_to_trace ();
  598.   errno = 0;
  599.   ret = open (filename, mode);
  600.   if (procfs_trace)
  601.     {
  602.       if (info_verbose)
  603.         fprintf (procfs_file ? procfs_file : stdout,
  604.                  "%s:%d -- ", file, line);

  605.       if (errno)
  606.         {
  607.           fprintf (procfs_file ? procfs_file : stdout,
  608.                    "[open FAILED! (%s) line %d]\\n",
  609.                    safe_strerror (errno), line);
  610.         }
  611.       else
  612.         {
  613.           fprintf (procfs_file ? procfs_file : stdout,
  614.                    "%d = open (%s, ", ret, filename);
  615.           if (mode == O_RDONLY)
  616.             fprintf (procfs_file ? procfs_file : stdout, "O_RDONLY) %d\n",
  617.                      line);
  618.           else if (mode == O_WRONLY)
  619.             fprintf (procfs_file ? procfs_file : stdout, "O_WRONLY) %d\n",
  620.                      line);
  621.           else if (mode == O_RDWR)
  622.             fprintf (procfs_file ? procfs_file : stdout, "O_RDWR)   %d\n",
  623.                      line);
  624.         }
  625.       if (procfs_file)
  626.         fflush (procfs_file);
  627.     }

  628.   return ret;
  629. }

  630. int
  631. close_with_trace (int fd, char *file, int line)
  632. {
  633.   int ret;

  634.   prepare_to_trace ();
  635.   errno = 0;
  636.   ret = close (fd);
  637.   if (procfs_trace)
  638.     {
  639.       if (info_verbose)
  640.         fprintf (procfs_file ? procfs_file : stdout,
  641.                  "%s:%d -- ", file, line);
  642.       if (errno)
  643.         fprintf (procfs_file ? procfs_file : stdout,
  644.                  "[close FAILED! (%s)]\n", safe_strerror (errno));
  645.       else
  646.         fprintf (procfs_file ? procfs_file : stdout,
  647.                  "%d = close (%d)\n", ret, fd);
  648.       if (procfs_file)
  649.         fflush (procfs_file);
  650.     }

  651.   return ret;
  652. }

  653. pid_t
  654. wait_with_trace (int *wstat, char *file, int line)
  655. {
  656.   int ret, lstat = 0;

  657.   prepare_to_trace ();
  658.   if (procfs_trace)
  659.     {
  660.       if (info_verbose)
  661.         fprintf (procfs_file ? procfs_file : stdout,
  662.                  "%s:%d -- ", file, line);
  663.       fprintf (procfs_file ? procfs_file : stdout,
  664.                "wait (line %d) ", line);
  665.       if (procfs_file)
  666.         fflush (procfs_file);
  667.     }
  668.   errno = 0;
  669.   ret = wait (&lstat);
  670.   if (procfs_trace)
  671.     {
  672.       if (errno)
  673.         fprintf (procfs_file ? procfs_file : stdout,
  674.                  "[wait FAILED! (%s)]\n", safe_strerror (errno));
  675.       else
  676.         fprintf (procfs_file ? procfs_file : stdout,
  677.                  "returned pid %d, status 0x%x\n", ret, lstat);
  678.       if (procfs_file)
  679.         fflush (procfs_file);
  680.     }
  681.   if (wstat)
  682.     *wstat = lstat;

  683.   return ret;
  684. }

  685. void
  686. procfs_note (char *msg, char *file, int line)
  687. {
  688.   prepare_to_trace ();
  689.   if (procfs_trace)
  690.     {
  691.       if (info_verbose)
  692.         fprintf (procfs_file ? procfs_file : stdout,
  693.                  "%s:%d -- ", file, line);
  694.       fprintf (procfs_file ? procfs_file : stdout, "%s", msg);
  695.       if (procfs_file)
  696.         fflush (procfs_file);
  697.     }
  698. }

  699. void
  700. proc_prettyfprint_status (long flags, int why, int what, int thread)
  701. {
  702.   prepare_to_trace ();
  703.   if (procfs_trace)
  704.     {
  705.       if (thread)
  706.         fprintf (procfs_file ? procfs_file : stdout,
  707.                  "Thread %d: ", thread);

  708.       proc_prettyfprint_flags (procfs_file ? procfs_file : stdout,
  709.                                flags, 0);

  710.       if (flags & (PR_STOPPED | PR_ISTOP))
  711.         proc_prettyfprint_why (procfs_file ? procfs_file : stdout,
  712.                                why, what, 0);
  713.       if (procfs_file)
  714.         fflush (procfs_file);
  715.     }
  716. }


  717. /* Provide a prototype to silence -Wmissing-prototypes.  */
  718. extern void _initialize_proc_api (void);

  719. void
  720. _initialize_proc_api (void)
  721. {
  722.   struct cmd_list_element *c;

  723.   add_setshow_boolean_cmd ("procfs-trace", no_class, &procfs_trace, _("\
  724. Set tracing for /proc api calls."), _("\
  725. Show tracing for /proc api calls."), NULL,
  726.                            set_procfs_trace_cmd,
  727.                            NULL, /* FIXME: i18n: */
  728.                            &setlist, &showlist);

  729.   add_setshow_filename_cmd ("procfs-file", no_class, &procfs_filename, _("\
  730. Set filename for /proc tracefile."), _("\
  731. Show filename for /proc tracefile."), NULL,
  732.                             set_procfs_file_cmd,
  733.                             NULL, /* FIXME: i18n: */
  734.                             &setlist, &showlist);
  735. }