Build unavailable-stack frames for tracepoint.
[deliverable/binutils-gdb.git] / gdb / proc-api.c
index 7ee9bf3c189417d2cf03a763e644442235248954..e05653d33d54808328389dca72e65dc5df196bbd 100644 (file)
@@ -1,23 +1,24 @@
 /* Machine independent support for SVR4 /proc (process file system) for GDB.
-   Copyright 1999 Free Software Foundation, Inc.
+
+   Copyright (C) 1999-2016 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 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 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 3 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.
+   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.  */
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
 /*
  * Pretty-print trace of api calls to the /proc api
@@ -27,25 +28,29 @@ Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
 #include "defs.h"
 #include "gdbcmd.h"
+#include "completer.h"
 
 #if defined (NEW_PROC_API)
 #define _STRUCTURED_PROC 1
 #endif
 
-#include <stdio.h>
 #include <sys/types.h>
 #include <sys/procfs.h>
+#ifdef HAVE_SYS_PROC_H
 #include <sys/proc.h>  /* for struct proc */
+#endif
+#ifdef HAVE_SYS_USER_H
 #include <sys/user.h>  /* for struct user */
-#include <fcntl.h>     /* for O_RDWR etc. */
-#include <sys/wait.h>
+#endif
+#include <fcntl.h>     /* for O_RDWR etc.  */
+#include "gdb_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. */
+    their symbolic names and to a string that describes their specific use.  */
 
 struct trans {
   long value;                   /* The numeric value */
@@ -53,16 +58,21 @@ struct trans {
   char *desc;                   /* Short description of value */
 };
 
-static int   procfs_trace    = 1;
-/*static int   info_verbose    = 1;*/  /* kludge */
+static int   procfs_trace    = 0;
 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;
+prepare_to_trace (void)
+{
+  if (procfs_trace)                    /* if procfs tracing turned on */
+    if (procfs_file == NULL)           /* if output file not yet open */
+      if (procfs_filename != NULL)     /* if output filename known */
+       procfs_file = fopen (procfs_filename, "a");     /* open output file */
+}
+
+static void
+set_procfs_trace_cmd (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)
@@ -71,10 +81,7 @@ set_procfs_trace_cmd (args, from_tty, c)
 }
 
 static void
-set_procfs_file_cmd (args, from_tty, c)
-     char *args;
-     int from_tty;
-     struct cmd_list_element *c;
+set_procfs_file_cmd (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.  */
@@ -110,8 +117,12 @@ static struct trans ioctl_table[] = {
   { PIOCGETPTIMER,   "PIOCGETPTIMER",   "get process timers" },
 #endif /* irix event counters */
   { PIOCGENTRY,    "PIOCGENTRY",   "get traced syscall entry set" },
+#if defined (PIOCGETPR)
   { PIOCGETPR,     "PIOCGETPR",    "read struct proc" },
+#endif
+#if defined (PIOCGETU)
   { PIOCGETU,      "PIOCGETU",     "read user area" },
+#endif
 #if defined (PIOCGETUTK) && (defined(KERNEL) || defined(SHOW_UTT)) /* osf */
   { PIOCGETUTK,  "PIOCGETUTK", "get the utask struct" },
 #endif
@@ -148,7 +159,7 @@ static struct trans ioctl_table[] = {
   { PIOCLDT,       "PIOCLDT",      "get LDT" },
   { PIOCNLDT,      "PIOCNLDT",     "get number of LDT entries" },
 #endif
-#ifdef PIOCLSTATUS                     /* solaris and unixware */
+#ifdef PIOCLSTATUS                     /* solaris */
   { PIOCLSTATUS,   "PIOCLSTATUS",  "get status of all lwps" },
   { PIOCLUSAGE,    "PIOCLUSAGE",   "get resource usage of all lwps" },
   { PIOCOPENLWP,   "PIOCOPENLWP",  "get lwp file descriptor" },
@@ -209,20 +220,16 @@ static struct trans ioctl_table[] = {
 };
 
 int
-ioctl_with_trace (fd, opcode, ptr, file, line)
-     int  fd;
-     long opcode;
-     void *ptr;
-     char *file;
-     int  line;
+ioctl_with_trace (int fd, long opcode, void *ptr, char *file, int line)
 {
-  int i, ret, arg1;
+  int i = 0;
+  int ret;
+  int arg1;
+
+  prepare_to_trace ();
 
   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;
@@ -364,13 +371,15 @@ ioctl_with_trace (fd, opcode, ptr, file, line)
       if (procfs_file)
        fflush (procfs_file);
     }
+  errno = 0;
   ret = ioctl (fd, opcode, ptr);
   if (procfs_trace && ret < 0)
     {
       fprintf (procfs_file ? procfs_file : stdout, 
-              "[ioctl (%s) FAILED!]\n",
+              "[ioctl (%s) FAILED! (%s)]\n",
               ioctl_table[i].name != NULL ? 
-              ioctl_table[i].name : "<unknown>");
+              ioctl_table[i].name : "<unknown>",
+              safe_strerror (errno));
       if (procfs_file)
        fflush (procfs_file);
     }
@@ -388,15 +397,16 @@ static struct trans rw_table[] = {
 #ifdef PCCSIG                  /* solaris */
   { PCCSIG,   "PCCSIG",   "clear current signal" },
 #endif
+#ifdef PCDSTOP                 /* solaris */
   { PCDSTOP,  "PCDSTOP",  "post stop request" },
+#endif
   { PCKILL,   "PCKILL",   "post a signal" },
+#ifdef PCNICE                  /* solaris */
   { PCNICE,   "PCNICE",   "set nice priority" },
+#endif
 #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 */
@@ -410,7 +420,9 @@ static struct trans rw_table[] = {
   { PCSEXIT,  "PCSEXIT",  "set traced syscall exit  set" },
   { PCSFAULT, "PCSFAULT", "set traced fault set" },
   { PCSFPREG, "PCSFPREG", "set floating point registers" },
+#ifdef PCSHOLD                 /* solaris */
   { PCSHOLD,  "PCSHOLD",  "set signal mask" },
+#endif
   { PCSREG,   "PCSREG",   "set general registers" },
   { PCSSIG,   "PCSSIG",   "set current signal" },
   { PCSTOP,   "PCSTOP",   "post stop request and wait" },
@@ -424,7 +436,9 @@ static struct trans rw_table[] = {
 #ifdef PCTWSTOP                        /* solaris */
   { PCTWSTOP, "PCTWSTOP", "wait for stop, with timeout arg" },
 #endif
+#ifdef PCUNKILL                        /* solaris */
   { PCUNKILL, "PCUNKILL", "delete a pending signal" },
+#endif
 #ifdef PCUNSET                 /* solaris */
   { PCUNSET,  "PCUNSET",  "unset modes" },
 #endif
@@ -438,22 +452,16 @@ static struct trans rw_table[] = {
 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;
+write_with_trace (int fd, void *varg, size_t len, char *file, int line)
 {
-  int  i;
+  int i = ARRAY_SIZE (rw_table) - 1;
   int ret;
-  long opcode = arg[0];
+  procfs_ctl_t *arg = (procfs_ctl_t *) varg;
 
+  prepare_to_trace ();
   if (procfs_trace)
     {
-      if (procfs_file == NULL && procfs_filename != NULL)
-       procfs_file = fopen (procfs_filename, "a");
-
+      procfs_ctl_t opcode = arg[0];
       for (i = 0; rw_table[i].name != NULL; i++)
        if (rw_table[i].value == opcode)
          break;
@@ -477,7 +485,9 @@ write_with_trace (fd, arg, len, file, line)
       case PCUNSET:
 #endif
 #ifdef PCRESET
+#if PCRESET != PCUNSET
       case PCRESET:
+#endif
 #endif
        fprintf (procfs_file ? procfs_file : stdout, 
                 "write (PCRESET, %s) %s\n", 
@@ -513,12 +523,14 @@ write_with_trace (fd, arg, len, file, line)
        proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout,
                                    (sysset_t *) &arg[1], 0);
        break;
+#ifdef PCSHOLD
       case PCSHOLD:
        fprintf (procfs_file ? procfs_file : stdout, 
                 "write (PCSHOLD) ");
        proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout,
                                     (sigset_t *) &arg[1], 0);
        break;
+#endif
       case PCSSIG:
        fprintf (procfs_file ? procfs_file : stdout, 
                 "write (PCSSIG) ");
@@ -537,10 +549,14 @@ write_with_trace (fd, arg, len, file, line)
          fprintf (procfs_file ? procfs_file : stdout, "clearFlt ");
        if (arg[1] & PRSTEP)
          fprintf (procfs_file ? procfs_file : stdout, "step ");
+#ifdef PRSABORT
        if (arg[1] & PRSABORT)
          fprintf (procfs_file ? procfs_file : stdout, "syscallAbort ");
+#endif
+#ifdef PRSTOP
        if (arg[1] & PRSTOP)
          fprintf (procfs_file ? procfs_file : stdout, "stopReq ");
+#endif
          
        fprintf (procfs_file ? procfs_file : stdout, "\n");
        break;
@@ -553,14 +569,7 @@ write_with_trace (fd, arg, len, file, line)
        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%08lx>) \n", 
-                    (unsigned long) lseek_offset);
-         else if (rw_table[i].name)
+         if (rw_table[i].name)
            fprintf (procfs_file ? procfs_file : stdout, 
                     "write (%s) %s\n", 
                     rw_table[i].name, 
@@ -582,13 +591,15 @@ write_with_trace (fd, arg, len, file, line)
       if (procfs_file)
        fflush (procfs_file);
     }
+  errno = 0;
   ret = write (fd, (void *) arg, len);
   if (procfs_trace && ret != len)
     {
       fprintf (procfs_file ? procfs_file : stdout, 
-              "[write (%s) FAILED!\n",
+              "[write (%s) FAILED! (%s)]\n",
               rw_table[i].name != NULL ? 
-              rw_table[i].name : "<unknown>");
+              rw_table[i].name : "<unknown>", 
+              safe_strerror (errno));
       if (procfs_file)
        fflush (procfs_file);
     }
@@ -598,43 +609,19 @@ write_with_trace (fd, arg, len, file, line)
 }
 
 off_t
-lseek_with_trace (fd, offset, whence, file, line)
-     int fd;
-     off_t offset;
-     int whence;
-     char *file;
-     int line;
+lseek_with_trace (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
+  prepare_to_trace ();
+  errno = 0;
   ret = lseek (fd, offset, whence);
   lseek_offset = ret;
-  if (procfs_trace && ret == -1)
+  if (procfs_trace && (ret == -1 || errno != 0))
     {
-      if (procfs_file == NULL && procfs_filename != NULL)
-       procfs_file = fopen (procfs_filename, "a");
-
       fprintf (procfs_file ? procfs_file : stdout, 
-              "[lseek (0x%08lx) FAILED!\n", (unsigned long) offset);
+              "[lseek (0x%08lx) FAILED! (%s)]\n", 
+              (unsigned long) offset, safe_strerror (errno));
       if (procfs_file)
        fflush (procfs_file);
     }
@@ -645,30 +632,39 @@ lseek_with_trace (fd, offset, whence, file, line)
 #endif /* NEW_PROC_API */
 
 int
-open_with_trace (filename, mode, file, line)
-     char *filename;
-     int   mode;
-     char *file;
-     int   line;
+open_with_trace (char *filename, int mode, char *file, int line)
 {
-  int ret = open (filename, mode);
+  int ret;
 
+  prepare_to_trace ();
+  errno = 0;
+  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 (errno)
+       {
+         fprintf (procfs_file ? procfs_file : stdout, 
+                  "[open FAILED! (%s) line %d]\\n", 
+                  safe_strerror (errno), line);
+       }
+      else
+       {
+         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);
     }
@@ -677,23 +673,24 @@ open_with_trace (filename, mode, file, line)
 }
 
 int
-close_with_trace (fd, file, line)
-     int   fd;
-     char *file;
-     int   line;
+close_with_trace (int fd, char *file, int line)
 {
-  int ret = close (fd);
+  int ret;
 
+  prepare_to_trace ();
+  errno = 0;
+  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 (errno)
+       fprintf (procfs_file ? procfs_file : stdout, 
+                "[close FAILED! (%s)]\n", safe_strerror (errno));
+      else
+       fprintf (procfs_file ? procfs_file : stdout, 
+                "%d = close (%d)\n", ret, fd);
       if (procfs_file)
        fflush (procfs_file);
     }
@@ -701,19 +698,14 @@ close_with_trace (fd, file, line)
   return ret;
 }
 
-int
-wait_with_trace (wstat, file, line)
-     int  *wstat;
-     char *file;
-     int   line;
+pid_t
+wait_with_trace (int *wstat, char *file, int line)
 {
   int ret, lstat = 0;
 
+  prepare_to_trace ();
   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);
@@ -722,11 +714,16 @@ wait_with_trace (wstat, file, line)
       if (procfs_file)
        fflush (procfs_file);
     }
+  errno = 0;
   ret = wait (&lstat);
   if (procfs_trace)
     {
-      fprintf (procfs_file ? procfs_file : stdout, 
-              "returned pid %d, status 0x%x\n", ret, lstat);
+      if (errno)
+       fprintf (procfs_file ? procfs_file : stdout, 
+                "[wait FAILED! (%s)]\n", safe_strerror (errno));
+      else
+       fprintf (procfs_file ? procfs_file : stdout, 
+                "returned pid %d, status 0x%x\n", ret, lstat);
       if (procfs_file)
        fflush (procfs_file);
     }
@@ -737,37 +734,26 @@ wait_with_trace (wstat, file, line)
 }
 
 void
-procfs_note (msg, file, line)
-     char *msg;
-     char *file;
-     int   line;
+procfs_note (char *msg, char *file, int line)
 {
+  prepare_to_trace ();
   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);
+      fprintf (procfs_file ? procfs_file : stdout, "%s", msg);
       if (procfs_file)
        fflush (procfs_file);
     }
 }
 
 void
-proc_prettyfprint_status (flags, why, what, thread)
-     long flags;
-     int  why;
-     int  what;
-     int  thread;
+proc_prettyfprint_status (long flags, int why, int what, int thread)
 {
+  prepare_to_trace ();
   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);
@@ -784,27 +770,25 @@ proc_prettyfprint_status (flags, why, what, thread)
 }
 
 
+/* Provide a prototype to silence -Wmissing-prototypes.  */
+extern void _initialize_proc_api (void);
+
 void
-_initialize_proc_api ()
+_initialize_proc_api (void)
 {
   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
+  add_setshow_boolean_cmd ("procfs-trace", no_class, &procfs_trace, _("\
+Set tracing for /proc api calls."), _("\
+Show tracing for /proc api calls."), NULL,
+                          set_procfs_trace_cmd,
+                          NULL, /* FIXME: i18n: */
+                          &setlist, &showlist);
+
+  add_setshow_filename_cmd ("procfs-file", no_class, &procfs_filename, _("\
+Set filename for /proc tracefile."), _("\
+Show filename for /proc tracefile."), NULL,
+                           set_procfs_file_cmd,
+                           NULL, /* FIXME: i18n: */
+                           &setlist, &showlist);
 }
This page took 0.030959 seconds and 4 git commands to generate.