198944Sobrien/* Machine independent support for SVR4 /proc (process file system) for GDB.
2130803Smarcel
3130803Smarcel   Copyright 1999, 2000, 2001, 2003 Free Software Foundation, Inc.
4130803Smarcel
598944Sobrien   Written by Michael Snyder at Cygnus Solutions.
698944Sobrien   Based on work by Fred Fish, Stu Grossman, Geoff Noer, and others.
798944Sobrien
898944SobrienThis file is part of GDB.
998944Sobrien
1098944SobrienThis program is free software; you can redistribute it and/or modify
1198944Sobrienit under the terms of the GNU General Public License as published by
1298944Sobrienthe Free Software Foundation; either version 2 of the License, or
1398944Sobrien(at your option) any later version.
1498944Sobrien
1598944SobrienThis program is distributed in the hope that it will be useful,
1698944Sobrienbut WITHOUT ANY WARRANTY; without even the implied warranty of
1798944SobrienMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1898944SobrienGNU General Public License for more details.
1998944Sobrien
2098944SobrienYou should have received a copy of the GNU General Public License
2198944Sobrienalong with this program; if not, write to the Free Software Foundation,
2298944SobrienInc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
2398944Sobrien
2498944Sobrien/*
2598944Sobrien * Pretty-print trace of api calls to the /proc api
2698944Sobrien * (ioctl or read/write calls).
2798944Sobrien *
2898944Sobrien */
2998944Sobrien
3098944Sobrien#include "defs.h"
3198944Sobrien#include "gdbcmd.h"
3298944Sobrien#include "completer.h"
3398944Sobrien
3498944Sobrien#if defined (NEW_PROC_API)
3598944Sobrien#define _STRUCTURED_PROC 1
3698944Sobrien#endif
3798944Sobrien
3898944Sobrien#include <stdio.h>
3998944Sobrien#include <sys/types.h>
4098944Sobrien#include <sys/procfs.h>
41130803Smarcel#ifdef HAVE_SYS_PROC_H
4298944Sobrien#include <sys/proc.h>	/* for struct proc */
43130803Smarcel#endif
4498944Sobrien#ifdef HAVE_SYS_USER_H
4598944Sobrien#include <sys/user.h>	/* for struct user */
4698944Sobrien#endif
4798944Sobrien#include <fcntl.h>	/* for O_RDWR etc. */
48130803Smarcel#include "gdb_wait.h"
4998944Sobrien
5098944Sobrien#include "proc-utils.h"
5198944Sobrien
5298944Sobrien/*  Much of the information used in the /proc interface, particularly for
5398944Sobrien    printing status information, is kept as tables of structures of the
5498944Sobrien    following form.  These tables can be used to map numeric values to
5598944Sobrien    their symbolic names and to a string that describes their specific use. */
5698944Sobrien
5798944Sobrienstruct trans {
5898944Sobrien  long value;                   /* The numeric value */
5998944Sobrien  char *name;                   /* The equivalent symbolic value */
6098944Sobrien  char *desc;                   /* Short description of value */
6198944Sobrien};
6298944Sobrien
6398944Sobrienstatic int   procfs_trace    = 0;
6498944Sobrienstatic FILE *procfs_file     = NULL;
6598944Sobrienstatic char *procfs_filename = "procfs_trace";
6698944Sobrien
6798944Sobrienstatic void
6898944Sobrienprepare_to_trace (void)
6998944Sobrien{
7098944Sobrien  if (procfs_trace)			/* if procfs tracing turned on */
7198944Sobrien    if (procfs_file == NULL)		/* if output file not yet open */
7298944Sobrien      if (procfs_filename != NULL)	/* if output filename known */
7398944Sobrien	procfs_file = fopen (procfs_filename, "a");	/* open output file */
7498944Sobrien}
7598944Sobrien
7698944Sobrienstatic void
7798944Sobrienset_procfs_trace_cmd (char *args, int from_tty, struct cmd_list_element *c)
7898944Sobrien{
7998944Sobrien#if 0	/* not sure what I might actually need to do here, if anything */
8098944Sobrien  if (procfs_file)
8198944Sobrien    fflush (procfs_file);
8298944Sobrien#endif
8398944Sobrien}
8498944Sobrien
8598944Sobrienstatic void
8698944Sobrienset_procfs_file_cmd (char *args, int from_tty, struct cmd_list_element *c)
8798944Sobrien{
8898944Sobrien  /* Just changed the filename for procfs tracing.
8998944Sobrien     If a file was already open, close it.  */
9098944Sobrien  if (procfs_file)
9198944Sobrien    fclose (procfs_file);
9298944Sobrien  procfs_file = NULL;
9398944Sobrien}
9498944Sobrien
9598944Sobrien
9698944Sobrien#ifndef NEW_PROC_API
9798944Sobrien
9898944Sobrienstatic struct trans ioctl_table[] = {
9998944Sobrien#ifdef PIOCACINFO			/* irix */
10098944Sobrien  { PIOCACINFO,    "PIOCACINFO",   "get process account info" },
10198944Sobrien#endif
10298944Sobrien  { PIOCACTION,    "PIOCACTION",   "get signal action structs" },
10398944Sobrien#ifdef PIOCARGUMENTS			/* osf */
10498944Sobrien  { PIOCARGUMENTS, "PIOCARGUMENTS", "command line args" },
10598944Sobrien#endif
10698944Sobrien#ifdef PIOCAUXV				/* solaris aux vectors */
10798944Sobrien  { PIOCAUXV,      "PIOCAUXV",     "get aux vector" },
10898944Sobrien  { PIOCNAUXV,     "PIOCNAUXV",    "get number of aux vector entries" },
10998944Sobrien#endif /* AUXV */
11098944Sobrien  { PIOCCFAULT,    "PIOCCFAULT",   "clear current fault" },
11198944Sobrien  { PIOCCRED,      "PIOCCRED",     "get process credentials" },
11298944Sobrien#ifdef PIOCENEVCTRS			/* irix event counters */
11398944Sobrien  { PIOCENEVCTRS,    "PIOCENEVCTRS",    "acquire and start event counters" },
11498944Sobrien  { PIOCGETEVCTRL,   "PIOCGETEVCTRL",   "get control info of event counters" },
11598944Sobrien  { PIOCGETEVCTRS,   "PIOCGETEVCTRS",   "dump event counters" },
11698944Sobrien  { PIOCGETPREVCTRS, "PIOCGETPREVCTRS", "dump event counters & prusage info" },
11798944Sobrien  { PIOCRELEVCTRS,   "PIOCRELEVCTRS",   "release/stop event counters" },
11898944Sobrien  { PIOCSETEVCTRL,   "PIOCSETEVCTRL",   "set control info of event counters" },
11998944Sobrien  { PIOCGETPTIMER,   "PIOCGETPTIMER",   "get process timers" },
12098944Sobrien#endif	/* irix event counters */
12198944Sobrien  { PIOCGENTRY,    "PIOCGENTRY",   "get traced syscall entry set" },
12298944Sobrien#if defined (PIOCGETPR)
12398944Sobrien  { PIOCGETPR,     "PIOCGETPR",    "read struct proc" },
12498944Sobrien#endif
12598944Sobrien#if defined (PIOCGETU)
12698944Sobrien  { PIOCGETU,      "PIOCGETU",     "read user area" },
12798944Sobrien#endif
12898944Sobrien#if defined (PIOCGETUTK) && (defined(KERNEL) || defined(SHOW_UTT)) /* osf */
12998944Sobrien  { PIOCGETUTK,  "PIOCGETUTK", "get the utask struct" },
13098944Sobrien#endif
13198944Sobrien  { PIOCGEXIT,     "PIOCGEXIT",    "get traced syscall exit  set" },
13298944Sobrien  { PIOCGFAULT,    "PIOCGFAULT",   "get traced fault set" },
13398944Sobrien#ifdef PIOCGFPCR			/* osf */
13498944Sobrien  { PIOCGFPCR,     "PIOCGFPCR",    "get FP control register" },
13598944Sobrien  { PIOCSFPCR,     "PIOCSFPCR",    "set FP conrtol register" },
13698944Sobrien#endif
13798944Sobrien  { PIOCGFPREG,    "PIOCGFPREG",   "get floating point registers" },
13898944Sobrien  { PIOCGHOLD,     "PIOCGHOLD",    "get held signal set" },
13998944Sobrien  { PIOCGREG,      "PIOCGREG",     "get general registers" },
14098944Sobrien  { PIOCGROUPS,    "PIOCGROUPS",   "get supplementary groups" },
14198944Sobrien#ifdef PIOCGSPCACT			/* osf */
14298944Sobrien  { PIOCGSPCACT,   "PIOCGSPCACT",  "get special action" },
14398944Sobrien  { PIOCSSPCACT,   "PIOCSSPCACT",  "set special action" },
14498944Sobrien#endif
14598944Sobrien  { PIOCGTRACE,    "PIOCGTRACE",   "get traced signal set" },
14698944Sobrien#ifdef PIOCGWATCH			/* irix watchpoints */
14798944Sobrien  { PIOCGWATCH,    "PIOCGWATCH",   "get watchpoint" },
14898944Sobrien  { PIOCSWATCH,    "PIOCSWATCH",   "set watchpoint" },
14998944Sobrien  { PIOCNWATCH,    "PIOCNWATCH",   "get number of watchpoints" },
15098944Sobrien#endif	/* irix watchpoints */
15198944Sobrien#ifdef PIOCGWIN				/* solaris sparc */
15298944Sobrien  { PIOCGWIN,      "PIOCGWIN",     "get gwindows_t" },
15398944Sobrien#endif
15498944Sobrien#ifdef PIOCGXREG			/* solaris sparc extra regs */
15598944Sobrien  { PIOCGXREGSIZE, "PIOCXREGSIZE", "get extra register state size" },
15698944Sobrien  { PIOCGXREG,     "PIOCGXREG",    "get extra register state" },
15798944Sobrien  { PIOCSXREG,     "PIOCSXREG",    "set extra register state" },
15898944Sobrien#endif /* XREG */
15998944Sobrien  { PIOCKILL,      "PIOCKILL",     "send signal" },
16098944Sobrien#ifdef PIOCLDT				/* solaris i386 */
16198944Sobrien  { PIOCLDT,       "PIOCLDT",      "get LDT" },
16298944Sobrien  { PIOCNLDT,      "PIOCNLDT",     "get number of LDT entries" },
16398944Sobrien#endif
16498944Sobrien#ifdef PIOCLSTATUS			/* solaris and unixware */
16598944Sobrien  { PIOCLSTATUS,   "PIOCLSTATUS",  "get status of all lwps" },
16698944Sobrien  { PIOCLUSAGE,    "PIOCLUSAGE",   "get resource usage of all lwps" },
16798944Sobrien  { PIOCOPENLWP,   "PIOCOPENLWP",  "get lwp file descriptor" },
16898944Sobrien  { PIOCLWPIDS,    "PIOCLWPIDS",   "get lwp identifiers" },
16998944Sobrien#endif /* LWP */
17098944Sobrien  { PIOCMAP,       "PIOCMAP",      "get memory map information" },
17198944Sobrien  { PIOCMAXSIG,    "PIOCMAXSIG",   "get max signal number" },
17298944Sobrien  { PIOCNICE,      "PIOCNICE",     "set nice priority" },
17398944Sobrien  { PIOCNMAP,      "PIOCNMAP",     "get number of memory mappings" },
17498944Sobrien  { PIOCOPENM,     "PIOCOPENM",    "open mapped object for reading" },
17598944Sobrien#ifdef PIOCOPENMOBS			/* osf */
17698944Sobrien  { PIOCOPENMOBS,  "PIOCOPENMOBS", "open mapped object" },
17798944Sobrien#endif
17898944Sobrien#ifdef PIOCOPENPD	/* solaris */
17998944Sobrien  { PIOCOPENPD,    "PIOCOPENPD",   "get page data file descriptor" },
18098944Sobrien#endif
18198944Sobrien  { PIOCPSINFO,    "PIOCPSINFO",   "get ps(1) information" },
18298944Sobrien  { PIOCRESET,     "PIOCRESET",    "reset process flags" },
18398944Sobrien  { PIOCRFORK,     "PIOCRFORK",    "reset inherit-on-fork flag" },
18498944Sobrien  { PIOCRRLC,      "PIOCRRLC",     "reset run-on-last-close flag" },
18598944Sobrien  { PIOCRUN,       "PIOCRUN",      "make process runnable" },
18698944Sobrien#ifdef PIOCSAVECCNTRS			/* irix */
18798944Sobrien  { PIOCSAVECCNTRS, "PIOCSAVECCNTRS", "parent gets child cntrs" },
18898944Sobrien#endif
18998944Sobrien  { PIOCSENTRY,    "PIOCSENTRY",   "set traced syscall entry set" },
19098944Sobrien  { PIOCSET,       "PIOCSET",      "set process flags" },
19198944Sobrien  { PIOCSEXIT,     "PIOCSEXIT",    "set traced syscall exit  set" },
19298944Sobrien  { PIOCSFAULT,    "PIOCSFAULT",   "set traced fault set" },
19398944Sobrien  { PIOCSFORK,     "PIOCSFORK",    "set inherit-on-fork flag" },
19498944Sobrien  { PIOCSFPREG,    "PIOCSFPREG",   "set floating point registers" },
19598944Sobrien  { PIOCSHOLD,     "PIOCSHOLD",    "set held signal set" },
19698944Sobrien  { PIOCSREG,      "PIOCSREG",     "set general registers" },
19798944Sobrien  { PIOCSRLC,      "PIOCSRLC",     "set run-on-last-close flag" },
19898944Sobrien  { PIOCSSIG,      "PIOCSSIG",     "set current signal" },
19998944Sobrien  { PIOCSTATUS,    "PIOCSTATUS",   "get process status" },
20098944Sobrien  { PIOCSTOP,      "PIOCSTOP",     "post stop request" },
20198944Sobrien  { PIOCSTRACE,    "PIOCSTRACE",   "set traced signal set" },
20298944Sobrien  { PIOCUNKILL,    "PIOCUNKILL",   "delete a signal" },
20398944Sobrien#ifdef PIOCUSAGE	/* solaris */
20498944Sobrien  { PIOCUSAGE,     "PIOCUSAGE",    "get resource usage" },
20598944Sobrien#endif
20698944Sobrien  { PIOCWSTOP,     "PIOCWSTOP",    "wait for process to stop" },
20798944Sobrien
20898944Sobrien#ifdef PIOCNTHR				/* osf threads */
20998944Sobrien  { PIOCNTHR,      "PIOCNTHR",     "get thread count" },
21098944Sobrien  { PIOCRTINH,     "PIOCRTINH",    "reset inherit-on-thread-creation" },
21198944Sobrien  { PIOCSTINH,     "PIOCSTINH",    "set   inherit-on-thread-creation" },
21298944Sobrien  { PIOCTLIST,     "PIOCTLIST",    "get thread ids" },
21398944Sobrien  { PIOCXPTH,      "PIOCXPTH",     "translate port to thread handle" },
21498944Sobrien  { PIOCTRUN,      "PIOCTRUN",     "make thread runnable" },
21598944Sobrien  { PIOCTSTATUS,   "PIOCTSTATUS",  "get thread status" },
21698944Sobrien  { PIOCTSTOP,     "PIOCTSTOP",    "stop a thread" },
21798944Sobrien  /* ... TGTRACE TSTRACE TSSIG TKILL TUNKILL TCFAULT TGFAULT TSFAULT
21898944Sobrien     TGFPREG TSFPREG TGREG TSREG TACTION TTERM TABRUN TGENTRY TSENTRY
21998944Sobrien     TGEXIT TSEXIT TSHOLD ... thread functions */
22098944Sobrien#endif /* osf threads */
22198944Sobrien  { -1,            NULL,           NULL }
22298944Sobrien};
22398944Sobrien
22498944Sobrienint
22598944Sobrienioctl_with_trace (int fd, long opcode, void *ptr, char *file, int line)
22698944Sobrien{
22798944Sobrien  int i = 0;
22898944Sobrien  int ret;
22998944Sobrien  int arg1;
23098944Sobrien
23198944Sobrien  prepare_to_trace ();
23298944Sobrien
23398944Sobrien  if (procfs_trace)
23498944Sobrien    {
23598944Sobrien      for (i = 0; ioctl_table[i].name != NULL; i++)
23698944Sobrien	if (ioctl_table[i].value == opcode)
23798944Sobrien	  break;
23898944Sobrien
23998944Sobrien      if (info_verbose)
24098944Sobrien	fprintf (procfs_file ? procfs_file : stdout,
24198944Sobrien		 "%s:%d -- ", file, line);
24298944Sobrien      switch (opcode) {
24398944Sobrien      case PIOCSET:
24498944Sobrien	arg1 = ptr ? *(long *) ptr : 0;
24598944Sobrien	fprintf (procfs_file ? procfs_file : stdout,
24698944Sobrien		 "ioctl (PIOCSET,   %s) %s\n",
24798944Sobrien		 arg1 == PR_FORK  ? "PR_FORK"  :
24898944Sobrien		 arg1 == PR_RLC   ? "PR_RLC"   :
24998944Sobrien#ifdef PR_ASYNC
25098944Sobrien		 arg1 == PR_ASYNC ? "PR_ASYNC" :
25198944Sobrien#endif
25298944Sobrien		 "<unknown flag>",
25398944Sobrien		 info_verbose ? ioctl_table[i].desc : "");
25498944Sobrien	break;
25598944Sobrien      case PIOCRESET:
25698944Sobrien	arg1 = ptr ? *(long *) ptr : 0;
25798944Sobrien	fprintf (procfs_file ? procfs_file : stdout,
25898944Sobrien		 "ioctl (PIOCRESET, %s) %s\n",
25998944Sobrien		 arg1 == PR_FORK  ? "PR_FORK"  :
26098944Sobrien		 arg1 == PR_RLC   ? "PR_RLC"   :
26198944Sobrien#ifdef PR_ASYNC
26298944Sobrien		 arg1 == PR_ASYNC ? "PR_ASYNC" :
26398944Sobrien#endif
26498944Sobrien		 "<unknown flag>",
26598944Sobrien		 info_verbose ? ioctl_table[i].desc : "");
26698944Sobrien	break;
26798944Sobrien      case PIOCSTRACE:
26898944Sobrien	fprintf (procfs_file ? procfs_file : stdout,
26998944Sobrien		 "ioctl (PIOCSTRACE) ");
27098944Sobrien	proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout,
27198944Sobrien				     (sigset_t *) ptr, 0);
27298944Sobrien	break;
27398944Sobrien      case PIOCSFAULT:
27498944Sobrien	fprintf (procfs_file ? procfs_file : stdout,
27598944Sobrien		 "ioctl (%s) ",
27698944Sobrien		 opcode == PIOCSFAULT ? "PIOCSFAULT" : "PIOCGFAULT");
27798944Sobrien	proc_prettyfprint_faultset (procfs_file ? procfs_file : stdout,
27898944Sobrien				    (fltset_t *) ptr, 0);
27998944Sobrien	break;
28098944Sobrien      case PIOCSENTRY:
28198944Sobrien	fprintf (procfs_file ? procfs_file : stdout,
28298944Sobrien		 "ioctl (%s) ",
28398944Sobrien		 opcode == PIOCSENTRY ? "PIOCSENTRY" : "PIOCGENTRY");
28498944Sobrien	proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout,
28598944Sobrien				    (sysset_t *) ptr, 0);
28698944Sobrien	break;
28798944Sobrien      case PIOCSEXIT:
28898944Sobrien	fprintf (procfs_file ? procfs_file : stdout,
28998944Sobrien		 "ioctl (%s) ",
29098944Sobrien		 opcode == PIOCSEXIT ? "PIOCSEXIT" : "PIOCGEXIT");
29198944Sobrien	proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout,
29298944Sobrien				    (sysset_t *) ptr, 0);
29398944Sobrien	break;
29498944Sobrien      case PIOCSHOLD:
29598944Sobrien	fprintf (procfs_file ? procfs_file : stdout,
29698944Sobrien		 "ioctl (%s) ",
29798944Sobrien		 opcode == PIOCSHOLD ? "PIOCSHOLD" : "PIOCGHOLD");
29898944Sobrien	proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout,
29998944Sobrien				     (sigset_t *) ptr, 0);
30098944Sobrien	break;
30198944Sobrien      case PIOCSSIG:
30298944Sobrien	fprintf (procfs_file ? procfs_file : stdout,
30398944Sobrien		 "ioctl (PIOCSSIG) ");
30498944Sobrien	proc_prettyfprint_signal (procfs_file ? procfs_file : stdout,
30598944Sobrien				  ptr ? ((siginfo_t *) ptr)->si_signo : 0,
30698944Sobrien				  0);
30798944Sobrien	fprintf (procfs_file ? procfs_file : stdout, "\n");
30898944Sobrien	break;
30998944Sobrien      case PIOCRUN:
31098944Sobrien	fprintf (procfs_file ? procfs_file : stdout,
31198944Sobrien		 "ioctl (PIOCRUN) ");
31298944Sobrien
31398944Sobrien	arg1 = ptr ? *(long *) ptr : 0;
31498944Sobrien	if (arg1 & PRCSIG)
31598944Sobrien	  fprintf (procfs_file ? procfs_file : stdout, "clearSig ");
31698944Sobrien	if (arg1 & PRCFAULT)
31798944Sobrien	  fprintf (procfs_file ? procfs_file : stdout, "clearFlt ");
31898944Sobrien	if (arg1 & PRSTRACE)
31998944Sobrien	  fprintf (procfs_file ? procfs_file : stdout, "setTrace ");
32098944Sobrien	if (arg1 & PRSHOLD)
32198944Sobrien	  fprintf (procfs_file ? procfs_file : stdout, "setHold ");
32298944Sobrien	if (arg1 & PRSFAULT)
32398944Sobrien	  fprintf (procfs_file ? procfs_file : stdout, "setFlt ");
32498944Sobrien	if (arg1 & PRSVADDR)
32598944Sobrien	  fprintf (procfs_file ? procfs_file : stdout, "setVaddr ");
32698944Sobrien	if (arg1 & PRSTEP)
32798944Sobrien	  fprintf (procfs_file ? procfs_file : stdout, "step ");
32898944Sobrien	if (arg1 & PRSABORT)
32998944Sobrien	  fprintf (procfs_file ? procfs_file : stdout, "syscallAbort ");
33098944Sobrien	if (arg1 & PRSTOP)
33198944Sobrien	  fprintf (procfs_file ? procfs_file : stdout, "stopReq ");
33298944Sobrien
33398944Sobrien	fprintf (procfs_file ? procfs_file : stdout, "\n");
33498944Sobrien	break;
33598944Sobrien      case PIOCKILL:
33698944Sobrien	fprintf (procfs_file ? procfs_file : stdout,
33798944Sobrien		 "ioctl (PIOCKILL) ");
33898944Sobrien	proc_prettyfprint_signal (procfs_file ? procfs_file : stdout,
33998944Sobrien				  ptr ? *(long *) ptr : 0, 0);
34098944Sobrien	fprintf (procfs_file ? procfs_file : stdout, "\n");
34198944Sobrien	break;
34298944Sobrien#ifdef PIOCSSPCACT
34398944Sobrien      case PIOCSSPCACT:
34498944Sobrien	fprintf (procfs_file ? procfs_file : stdout,
34598944Sobrien		 "ioctl (PIOCSSPCACT) ");
34698944Sobrien	arg1 = ptr ? *(long *) ptr : 0;
34798944Sobrien	if (arg1 & PRFS_STOPFORK)
34898944Sobrien	  fprintf (procfs_file ? procfs_file : stdout, "stopFork ");
34998944Sobrien	if (arg1 & PRFS_STOPEXEC)
35098944Sobrien	  fprintf (procfs_file ? procfs_file : stdout, "stopExec ");
35198944Sobrien	if (arg1 & PRFS_STOPTERM)
35298944Sobrien	  fprintf (procfs_file ? procfs_file : stdout, "stopTerm ");
35398944Sobrien	if (arg1 & PRFS_STOPTCR)
35498944Sobrien	  fprintf (procfs_file ? procfs_file : stdout, "stopThreadCreate ");
35598944Sobrien	if (arg1 & PRFS_STOPTTERM)
35698944Sobrien	  fprintf (procfs_file ? procfs_file : stdout, "stopThreadTerm ");
35798944Sobrien	if (arg1 & PRFS_KOLC)
35898944Sobrien	  fprintf (procfs_file ? procfs_file : stdout, "killOnLastClose ");
35998944Sobrien	fprintf (procfs_file ? procfs_file : stdout, "\n");
36098944Sobrien	break;
36198944Sobrien#endif /* PIOCSSPCACT */
36298944Sobrien      default:
36398944Sobrien	if (ioctl_table[i].name)
36498944Sobrien	  fprintf (procfs_file ? procfs_file : stdout,
36598944Sobrien		   "ioctl (%s) %s\n",
36698944Sobrien		   ioctl_table[i].name,
36798944Sobrien		   info_verbose ? ioctl_table[i].desc : "");
36898944Sobrien	else
36998944Sobrien	  fprintf (procfs_file ? procfs_file : stdout,
37098944Sobrien		   "ioctl (<unknown %ld (0x%lx)) \n", opcode, opcode);
37198944Sobrien	break;
37298944Sobrien      }
37398944Sobrien      if (procfs_file)
37498944Sobrien	fflush (procfs_file);
37598944Sobrien    }
37698944Sobrien  errno = 0;
37798944Sobrien  ret = ioctl (fd, opcode, ptr);
37898944Sobrien  if (procfs_trace && ret < 0)
37998944Sobrien    {
38098944Sobrien      fprintf (procfs_file ? procfs_file : stdout,
38198944Sobrien	       "[ioctl (%s) FAILED! (%s)]\n",
38298944Sobrien	       ioctl_table[i].name != NULL ?
38398944Sobrien	       ioctl_table[i].name : "<unknown>",
38498944Sobrien	       safe_strerror (errno));
38598944Sobrien      if (procfs_file)
38698944Sobrien	fflush (procfs_file);
38798944Sobrien    }
38898944Sobrien
38998944Sobrien  return ret;
39098944Sobrien}
39198944Sobrien
39298944Sobrien#else	/* NEW_PROC_API */
39398944Sobrien
39498944Sobrienstatic struct trans rw_table[] = {
39598944Sobrien#ifdef PCAGENT			/* solaris */
39698944Sobrien  { PCAGENT,  "PCAGENT",  "create agent lwp with regs from argument" },
39798944Sobrien#endif
39898944Sobrien  { PCCFAULT, "PCCFAULT", "clear current fault" },
39998944Sobrien#ifdef PCCSIG			/* solaris */
40098944Sobrien  { PCCSIG,   "PCCSIG",   "clear current signal" },
40198944Sobrien#endif
402130803Smarcel#ifdef PCDSTOP			/* solaris */
40398944Sobrien  { PCDSTOP,  "PCDSTOP",  "post stop request" },
404130803Smarcel#endif
40598944Sobrien  { PCKILL,   "PCKILL",   "post a signal" },
406130803Smarcel#ifdef PCNICE			/* solaris */
40798944Sobrien  { PCNICE,   "PCNICE",   "set nice priority" },
408130803Smarcel#endif
40998944Sobrien#ifdef PCREAD			/* solaris */
41098944Sobrien  { PCREAD,   "PCREAD",   "read from the address space" },
41198944Sobrien  { PCWRITE,  "PCWRITE",  "write to the address space" },
41298944Sobrien#endif
41398944Sobrien#ifdef PCRESET			/* unixware */
41498944Sobrien  { PCRESET,  "PCRESET",  "unset modes" },
41598944Sobrien#endif
41698944Sobrien  { PCRUN,    "PCRUN",    "make process/lwp runnable" },
41798944Sobrien#ifdef PCSASRS			/* solaris 2.7 only */
41898944Sobrien  { PCSASRS,  "PCSASRS",  "set ancillary state registers" },
41998944Sobrien#endif
42098944Sobrien#ifdef PCSCRED			/* solaris */
42198944Sobrien  { PCSCRED,  "PCSCRED",  "set process credentials" },
42298944Sobrien#endif
42398944Sobrien  { PCSENTRY, "PCSENTRY", "set traced syscall entry set" },
42498944Sobrien  { PCSET,    "PCSET",    "set modes" },
42598944Sobrien  { PCSEXIT,  "PCSEXIT",  "set traced syscall exit  set" },
42698944Sobrien  { PCSFAULT, "PCSFAULT", "set traced fault set" },
42798944Sobrien  { PCSFPREG, "PCSFPREG", "set floating point registers" },
428130803Smarcel#ifdef PCSHOLD			/* solaris */
42998944Sobrien  { PCSHOLD,  "PCSHOLD",  "set signal mask" },
430130803Smarcel#endif
43198944Sobrien  { PCSREG,   "PCSREG",   "set general registers" },
43298944Sobrien  { PCSSIG,   "PCSSIG",   "set current signal" },
43398944Sobrien  { PCSTOP,   "PCSTOP",   "post stop request and wait" },
43498944Sobrien  { PCSTRACE, "PCSTRACE", "set traced signal set" },
43598944Sobrien#ifdef PCSVADDR			/* solaris */
43698944Sobrien  { PCSVADDR, "PCSVADDR", "set pc virtual address" },
43798944Sobrien#endif
43898944Sobrien#ifdef PCSXREG			/* solaris sparc only */
43998944Sobrien  { PCSXREG,  "PCSXREG",  "set extra registers" },
44098944Sobrien#endif
44198944Sobrien#ifdef PCTWSTOP			/* solaris */
44298944Sobrien  { PCTWSTOP, "PCTWSTOP", "wait for stop, with timeout arg" },
44398944Sobrien#endif
444130803Smarcel#ifdef PCUNKILL			/* solaris */
44598944Sobrien  { PCUNKILL, "PCUNKILL", "delete a pending signal" },
446130803Smarcel#endif
44798944Sobrien#ifdef PCUNSET			/* solaris */
44898944Sobrien  { PCUNSET,  "PCUNSET",  "unset modes" },
44998944Sobrien#endif
45098944Sobrien#ifdef PCWATCH			/* solaris */
45198944Sobrien  { PCWATCH,  "PCWATCH",  "set/unset watched memory area" },
45298944Sobrien#endif
45398944Sobrien  { PCWSTOP,  "PCWSTOP",  "wait for process/lwp to stop, no timeout" },
45498944Sobrien  { 0,        NULL,      NULL }
45598944Sobrien};
45698944Sobrien
45798944Sobrienstatic off_t lseek_offset;
45898944Sobrien
45998944Sobrienint
46098944Sobrienwrite_with_trace (int fd, void *varg, size_t len, char *file, int line)
46198944Sobrien{
462130803Smarcel  int i = ARRAY_SIZE (rw_table) - 1;
46398944Sobrien  int ret;
46498944Sobrien  procfs_ctl_t *arg = (procfs_ctl_t *) varg;
46598944Sobrien
46698944Sobrien  prepare_to_trace ();
46798944Sobrien  if (procfs_trace)
46898944Sobrien    {
46998944Sobrien      procfs_ctl_t opcode = arg[0];
47098944Sobrien      for (i = 0; rw_table[i].name != NULL; i++)
47198944Sobrien	if (rw_table[i].value == opcode)
47298944Sobrien	  break;
47398944Sobrien
47498944Sobrien      if (info_verbose)
47598944Sobrien	fprintf (procfs_file ? procfs_file : stdout,
47698944Sobrien		 "%s:%d -- ", file, line);
47798944Sobrien      switch (opcode) {
47898944Sobrien      case PCSET:
47998944Sobrien	fprintf (procfs_file ? procfs_file : stdout,
48098944Sobrien		 "write (PCSET,   %s) %s\n",
48198944Sobrien		 arg[1] == PR_FORK  ? "PR_FORK"  :
48298944Sobrien		 arg[1] == PR_RLC   ? "PR_RLC"   :
48398944Sobrien#ifdef PR_ASYNC
48498944Sobrien		 arg[1] == PR_ASYNC ? "PR_ASYNC" :
48598944Sobrien#endif
48698944Sobrien		 "<unknown flag>",
48798944Sobrien		 info_verbose ? rw_table[i].desc : "");
48898944Sobrien	break;
48998944Sobrien#ifdef PCUNSET
49098944Sobrien      case PCUNSET:
49198944Sobrien#endif
49298944Sobrien#ifdef PCRESET
49398944Sobrien#if PCRESET != PCUNSET
49498944Sobrien      case PCRESET:
49598944Sobrien#endif
49698944Sobrien#endif
49798944Sobrien	fprintf (procfs_file ? procfs_file : stdout,
49898944Sobrien		 "write (PCRESET, %s) %s\n",
49998944Sobrien		 arg[1] == PR_FORK  ? "PR_FORK"  :
50098944Sobrien		 arg[1] == PR_RLC   ? "PR_RLC"   :
50198944Sobrien#ifdef PR_ASYNC
50298944Sobrien		 arg[1] == PR_ASYNC ? "PR_ASYNC" :
50398944Sobrien#endif
50498944Sobrien		 "<unknown flag>",
50598944Sobrien		 info_verbose ? rw_table[i].desc : "");
50698944Sobrien	break;
50798944Sobrien      case PCSTRACE:
50898944Sobrien	fprintf (procfs_file ? procfs_file : stdout,
50998944Sobrien		 "write (PCSTRACE) ");
51098944Sobrien	proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout,
51198944Sobrien				     (sigset_t *) &arg[1], 0);
51298944Sobrien	break;
51398944Sobrien      case PCSFAULT:
51498944Sobrien	fprintf (procfs_file ? procfs_file : stdout,
51598944Sobrien		 "write (PCSFAULT) ");
51698944Sobrien	proc_prettyfprint_faultset (procfs_file ? procfs_file : stdout,
51798944Sobrien				    (fltset_t *) &arg[1], 0);
51898944Sobrien	break;
51998944Sobrien      case PCSENTRY:
52098944Sobrien	fprintf (procfs_file ? procfs_file : stdout,
52198944Sobrien		 "write (PCSENTRY) ");
52298944Sobrien	proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout,
52398944Sobrien				    (sysset_t *) &arg[1], 0);
52498944Sobrien	break;
52598944Sobrien      case PCSEXIT:
52698944Sobrien	fprintf (procfs_file ? procfs_file : stdout,
52798944Sobrien		 "write (PCSEXIT) ");
52898944Sobrien	proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout,
52998944Sobrien				    (sysset_t *) &arg[1], 0);
53098944Sobrien	break;
531130803Smarcel#ifdef PCSHOLD
53298944Sobrien      case PCSHOLD:
53398944Sobrien	fprintf (procfs_file ? procfs_file : stdout,
53498944Sobrien		 "write (PCSHOLD) ");
53598944Sobrien	proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout,
53698944Sobrien				     (sigset_t *) &arg[1], 0);
53798944Sobrien	break;
538130803Smarcel#endif
53998944Sobrien      case PCSSIG:
54098944Sobrien	fprintf (procfs_file ? procfs_file : stdout,
54198944Sobrien		 "write (PCSSIG) ");
54298944Sobrien	proc_prettyfprint_signal (procfs_file ? procfs_file : stdout,
54398944Sobrien				  arg[1] ? ((siginfo_t *) &arg[1])->si_signo
54498944Sobrien				         : 0,
54598944Sobrien				  0);
54698944Sobrien	fprintf (procfs_file ? procfs_file : stdout, "\n");
54798944Sobrien	break;
54898944Sobrien      case PCRUN:
54998944Sobrien	fprintf (procfs_file ? procfs_file : stdout,
55098944Sobrien		 "write (PCRUN) ");
55198944Sobrien	if (arg[1] & PRCSIG)
55298944Sobrien	  fprintf (procfs_file ? procfs_file : stdout, "clearSig ");
55398944Sobrien	if (arg[1] & PRCFAULT)
55498944Sobrien	  fprintf (procfs_file ? procfs_file : stdout, "clearFlt ");
55598944Sobrien	if (arg[1] & PRSTEP)
55698944Sobrien	  fprintf (procfs_file ? procfs_file : stdout, "step ");
557130803Smarcel#ifdef PRSABORT
55898944Sobrien	if (arg[1] & PRSABORT)
55998944Sobrien	  fprintf (procfs_file ? procfs_file : stdout, "syscallAbort ");
560130803Smarcel#endif
561130803Smarcel#ifdef PRSTOP
56298944Sobrien	if (arg[1] & PRSTOP)
56398944Sobrien	  fprintf (procfs_file ? procfs_file : stdout, "stopReq ");
564130803Smarcel#endif
56598944Sobrien
56698944Sobrien	fprintf (procfs_file ? procfs_file : stdout, "\n");
56798944Sobrien	break;
56898944Sobrien      case PCKILL:
56998944Sobrien	fprintf (procfs_file ? procfs_file : stdout,
57098944Sobrien		 "write (PCKILL) ");
57198944Sobrien	proc_prettyfprint_signal (procfs_file ? procfs_file : stdout,
57298944Sobrien				  arg[1], 0);
57398944Sobrien	fprintf (procfs_file ? procfs_file : stdout, "\n");
57498944Sobrien	break;
57598944Sobrien      default:
57698944Sobrien	{
57798944Sobrien	  if (rw_table[i].name)
57898944Sobrien	    fprintf (procfs_file ? procfs_file : stdout,
57998944Sobrien		     "write (%s) %s\n",
58098944Sobrien		     rw_table[i].name,
58198944Sobrien		     info_verbose ? rw_table[i].desc : "");
58298944Sobrien	  else
58398944Sobrien	    {
58498944Sobrien	      if (lseek_offset != -1)
58598944Sobrien		fprintf (procfs_file ? procfs_file : stdout,
58698944Sobrien			 "write (<unknown>, %lud bytes at 0x%08lx) \n",
58798944Sobrien			 (unsigned long) len, (unsigned long) lseek_offset);
58898944Sobrien	      else
58998944Sobrien		fprintf (procfs_file ? procfs_file : stdout,
59098944Sobrien			 "write (<unknown>, %lud bytes) \n",
59198944Sobrien			 (unsigned long) len);
59298944Sobrien	    }
59398944Sobrien	  break;
59498944Sobrien	}
59598944Sobrien      }
59698944Sobrien      if (procfs_file)
59798944Sobrien	fflush (procfs_file);
59898944Sobrien    }
59998944Sobrien  errno = 0;
60098944Sobrien  ret = write (fd, (void *) arg, len);
60198944Sobrien  if (procfs_trace && ret != len)
60298944Sobrien    {
60398944Sobrien      fprintf (procfs_file ? procfs_file : stdout,
60498944Sobrien	       "[write (%s) FAILED! (%s)]\n",
60598944Sobrien	       rw_table[i].name != NULL ?
60698944Sobrien	       rw_table[i].name : "<unknown>",
60798944Sobrien	       safe_strerror (errno));
60898944Sobrien      if (procfs_file)
60998944Sobrien	fflush (procfs_file);
61098944Sobrien    }
61198944Sobrien
61298944Sobrien  lseek_offset = -1;
61398944Sobrien  return ret;
61498944Sobrien}
61598944Sobrien
61698944Sobrienoff_t
61798944Sobrienlseek_with_trace (int fd, off_t offset, int whence, char *file, int line)
61898944Sobrien{
61998944Sobrien  off_t ret;
62098944Sobrien
62198944Sobrien  prepare_to_trace ();
62298944Sobrien  errno = 0;
62398944Sobrien  ret = lseek (fd, offset, whence);
62498944Sobrien  lseek_offset = ret;
62598944Sobrien  if (procfs_trace && (ret == -1 || errno != 0))
62698944Sobrien    {
62798944Sobrien      fprintf (procfs_file ? procfs_file : stdout,
62898944Sobrien	       "[lseek (0x%08lx) FAILED! (%s)]\n",
62998944Sobrien	       (unsigned long) offset, safe_strerror (errno));
63098944Sobrien      if (procfs_file)
63198944Sobrien	fflush (procfs_file);
63298944Sobrien    }
63398944Sobrien
63498944Sobrien  return ret;
63598944Sobrien}
63698944Sobrien
63798944Sobrien#endif /* NEW_PROC_API */
63898944Sobrien
63998944Sobrienint
64098944Sobrienopen_with_trace (char *filename, int mode, char *file, int line)
64198944Sobrien{
64298944Sobrien  int ret;
64398944Sobrien
64498944Sobrien  prepare_to_trace ();
64598944Sobrien  errno = 0;
64698944Sobrien  ret = open (filename, mode);
64798944Sobrien  if (procfs_trace)
64898944Sobrien    {
64998944Sobrien      if (info_verbose)
65098944Sobrien	fprintf (procfs_file ? procfs_file : stdout,
65198944Sobrien		 "%s:%d -- ", file, line);
65298944Sobrien
65398944Sobrien      if (errno)
65498944Sobrien	{
65598944Sobrien	  fprintf (procfs_file ? procfs_file : stdout,
65698944Sobrien		   "[open FAILED! (%s) line %d]\\n",
65798944Sobrien		   safe_strerror (errno), line);
65898944Sobrien	}
65998944Sobrien      else
66098944Sobrien	{
66198944Sobrien	  fprintf (procfs_file ? procfs_file : stdout,
66298944Sobrien		   "%d = open (%s, ", ret, filename);
66398944Sobrien	  if (mode == O_RDONLY)
66498944Sobrien	    fprintf (procfs_file ? procfs_file : stdout, "O_RDONLY) %d\n",
66598944Sobrien		     line);
66698944Sobrien	  else if (mode == O_WRONLY)
66798944Sobrien	    fprintf (procfs_file ? procfs_file : stdout, "O_WRONLY) %d\n",
66898944Sobrien		     line);
66998944Sobrien	  else if (mode == O_RDWR)
67098944Sobrien	    fprintf (procfs_file ? procfs_file : stdout, "O_RDWR)   %d\n",
67198944Sobrien		     line);
67298944Sobrien	}
67398944Sobrien      if (procfs_file)
67498944Sobrien	fflush (procfs_file);
67598944Sobrien    }
67698944Sobrien
67798944Sobrien  return ret;
67898944Sobrien}
67998944Sobrien
68098944Sobrienint
68198944Sobrienclose_with_trace (int fd, char *file, int line)
68298944Sobrien{
68398944Sobrien  int ret;
68498944Sobrien
68598944Sobrien  prepare_to_trace ();
68698944Sobrien  errno = 0;
68798944Sobrien  ret = close (fd);
68898944Sobrien  if (procfs_trace)
68998944Sobrien    {
69098944Sobrien      if (info_verbose)
69198944Sobrien	fprintf (procfs_file ? procfs_file : stdout,
69298944Sobrien		 "%s:%d -- ", file, line);
69398944Sobrien      if (errno)
69498944Sobrien	fprintf (procfs_file ? procfs_file : stdout,
69598944Sobrien		 "[close FAILED! (%s)]\n", safe_strerror (errno));
69698944Sobrien      else
69798944Sobrien	fprintf (procfs_file ? procfs_file : stdout,
69898944Sobrien		 "%d = close (%d)\n", ret, fd);
69998944Sobrien      if (procfs_file)
70098944Sobrien	fflush (procfs_file);
70198944Sobrien    }
70298944Sobrien
70398944Sobrien  return ret;
70498944Sobrien}
70598944Sobrien
70698944Sobrienpid_t
70798944Sobrienwait_with_trace (int *wstat, char *file, int line)
70898944Sobrien{
70998944Sobrien  int ret, lstat = 0;
71098944Sobrien
71198944Sobrien  prepare_to_trace ();
71298944Sobrien  if (procfs_trace)
71398944Sobrien    {
71498944Sobrien      if (info_verbose)
71598944Sobrien	fprintf (procfs_file ? procfs_file : stdout,
71698944Sobrien		 "%s:%d -- ", file, line);
71798944Sobrien      fprintf (procfs_file ? procfs_file : stdout,
71898944Sobrien	       "wait (line %d) ", line);
71998944Sobrien      if (procfs_file)
72098944Sobrien	fflush (procfs_file);
72198944Sobrien    }
72298944Sobrien  errno = 0;
72398944Sobrien  ret = wait (&lstat);
72498944Sobrien  if (procfs_trace)
72598944Sobrien    {
72698944Sobrien      if (errno)
72798944Sobrien	fprintf (procfs_file ? procfs_file : stdout,
72898944Sobrien		 "[wait FAILED! (%s)]\n", safe_strerror (errno));
72998944Sobrien      else
73098944Sobrien	fprintf (procfs_file ? procfs_file : stdout,
73198944Sobrien		 "returned pid %d, status 0x%x\n", ret, lstat);
73298944Sobrien      if (procfs_file)
73398944Sobrien	fflush (procfs_file);
73498944Sobrien    }
73598944Sobrien  if (wstat)
73698944Sobrien    *wstat = lstat;
73798944Sobrien
73898944Sobrien  return ret;
73998944Sobrien}
74098944Sobrien
74198944Sobrienvoid
74298944Sobrienprocfs_note (char *msg, char *file, int line)
74398944Sobrien{
74498944Sobrien  prepare_to_trace ();
74598944Sobrien  if (procfs_trace)
74698944Sobrien    {
74798944Sobrien      if (info_verbose)
74898944Sobrien	fprintf (procfs_file ? procfs_file : stdout,
74998944Sobrien		 "%s:%d -- ", file, line);
750130803Smarcel      fprintf (procfs_file ? procfs_file : stdout, "%s", msg);
75198944Sobrien      if (procfs_file)
75298944Sobrien	fflush (procfs_file);
75398944Sobrien    }
75498944Sobrien}
75598944Sobrien
75698944Sobrienvoid
75798944Sobrienproc_prettyfprint_status (long flags, int why, int what, int thread)
75898944Sobrien{
75998944Sobrien  prepare_to_trace ();
76098944Sobrien  if (procfs_trace)
76198944Sobrien    {
76298944Sobrien      if (thread)
76398944Sobrien	fprintf (procfs_file ? procfs_file : stdout,
76498944Sobrien		 "Thread %d: ", thread);
76598944Sobrien
76698944Sobrien      proc_prettyfprint_flags (procfs_file ? procfs_file : stdout,
76798944Sobrien			       flags, 0);
76898944Sobrien
76998944Sobrien      if (flags & (PR_STOPPED | PR_ISTOP))
77098944Sobrien	proc_prettyfprint_why (procfs_file ? procfs_file : stdout,
77198944Sobrien			       why, what, 0);
77298944Sobrien      if (procfs_file)
77398944Sobrien	fflush (procfs_file);
77498944Sobrien    }
77598944Sobrien}
77698944Sobrien
77798944Sobrien
77898944Sobrienvoid
77998944Sobrien_initialize_proc_api (void)
78098944Sobrien{
78198944Sobrien  struct cmd_list_element *c;
78298944Sobrien
78398944Sobrien  c = add_set_cmd ("procfs-trace", no_class,
78498944Sobrien		   var_boolean, (char *) &procfs_trace,
78598944Sobrien		   "Set tracing for /proc api calls.\n", &setlist);
78698944Sobrien
78798944Sobrien  add_show_from_set (c, &showlist);
78898944Sobrien  set_cmd_sfunc (c, set_procfs_trace_cmd);
789130803Smarcel  set_cmd_completer (c, filename_completer);
79098944Sobrien
79198944Sobrien  c = add_set_cmd ("procfs-file", no_class, var_filename,
79298944Sobrien		   (char *) &procfs_filename,
79398944Sobrien		   "Set filename for /proc tracefile.\n", &setlist);
79498944Sobrien
79598944Sobrien  add_show_from_set (c, &showlist);
79698944Sobrien  set_cmd_sfunc (c, set_procfs_file_cmd);
79798944Sobrien}
798