OSDN Git Service

2000-05-05 Michael Snyder <msnyder@seadog.cygnus.com>
[pf3gnuchains/pf3gnuchains3x.git] / gdb / proc-api.c
1 /* Machine independent support for SVR4 /proc (process file system) for GDB.
2    Copyright 1999 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
6 This file is part of GDB.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software Foundation, 
20 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
21
22 /*
23  * Pretty-print trace of api calls to the /proc api
24  * (ioctl or read/write calls).
25  * 
26  */
27
28 #include "defs.h"
29 #include "gdbcmd.h"
30
31 #if defined (NEW_PROC_API)
32 #define _STRUCTURED_PROC 1
33 #endif
34
35 #include <stdio.h>
36 #include <sys/types.h>
37 #include <sys/procfs.h>
38 #include <sys/proc.h>   /* for struct proc */
39 #include <sys/user.h>   /* for struct user */
40 #include <fcntl.h>      /* for O_RDWR etc. */
41 #include <sys/wait.h>
42
43 #include "proc-utils.h"
44
45 /*  Much of the information used in the /proc interface, particularly for
46     printing status information, is kept as tables of structures of the
47     following form.  These tables can be used to map numeric values to
48     their symbolic names and to a string that describes their specific use. */
49
50 struct trans {
51   long value;                   /* The numeric value */
52   char *name;                   /* The equivalent symbolic value */
53   char *desc;                   /* Short description of value */
54 };
55
56 static int   procfs_trace    = 1;
57 /*static int   info_verbose    = 1;*/   /* kludge */
58 static FILE *procfs_file     = NULL;
59 static char *procfs_filename = "procfs_trace";
60
61 static void
62 set_procfs_trace_cmd (args, from_tty, c)
63      char *args;
64      int from_tty;
65      struct cmd_list_element *c;
66 {
67 #if 0   /* not sure what I might actually need to do here, if anything */
68   if (procfs_file)
69     fflush (procfs_file);
70 #endif
71 }
72
73 static void
74 set_procfs_file_cmd (args, from_tty, c)
75      char *args;
76      int from_tty;
77      struct cmd_list_element *c;
78 {
79   /* Just changed the filename for procfs tracing.
80      If a file was already open, close it.  */
81   if (procfs_file)
82     fclose (procfs_file);
83   procfs_file = NULL;
84 }
85
86
87 #ifndef NEW_PROC_API
88
89 static struct trans ioctl_table[] = {
90 #ifdef PIOCACINFO                       /* irix */
91   { PIOCACINFO,    "PIOCACINFO",   "get process account info" },
92 #endif
93   { PIOCACTION,    "PIOCACTION",   "get signal action structs" },
94 #ifdef PIOCARGUMENTS                    /* osf */
95   { PIOCARGUMENTS, "PIOCARGUMENTS", "command line args" },
96 #endif
97 #ifdef PIOCAUXV                         /* solaris aux vectors */
98   { PIOCAUXV,      "PIOCAUXV",     "get aux vector" },
99   { PIOCNAUXV,     "PIOCNAUXV",    "get number of aux vector entries" },
100 #endif /* AUXV */
101   { PIOCCFAULT,    "PIOCCFAULT",   "clear current fault" },
102   { PIOCCRED,      "PIOCCRED",     "get process credentials" },
103 #ifdef PIOCENEVCTRS                     /* irix event counters */
104   { PIOCENEVCTRS,    "PIOCENEVCTRS",    "acquire and start event counters" },
105   { PIOCGETEVCTRL,   "PIOCGETEVCTRL",   "get control info of event counters" },
106   { PIOCGETEVCTRS,   "PIOCGETEVCTRS",   "dump event counters" },
107   { PIOCGETPREVCTRS, "PIOCGETPREVCTRS", "dump event counters & prusage info" },
108   { PIOCRELEVCTRS,   "PIOCRELEVCTRS",   "release/stop event counters" },
109   { PIOCSETEVCTRL,   "PIOCSETEVCTRL",   "set control info of event counters" },
110   { PIOCGETPTIMER,   "PIOCGETPTIMER",   "get process timers" },
111 #endif  /* irix event counters */
112   { PIOCGENTRY,    "PIOCGENTRY",   "get traced syscall entry set" },
113   { PIOCGETPR,     "PIOCGETPR",    "read struct proc" },
114   { PIOCGETU,      "PIOCGETU",     "read user area" },
115 #if defined (PIOCGETUTK) && (defined(KERNEL) || defined(SHOW_UTT)) /* osf */
116   { PIOCGETUTK,  "PIOCGETUTK", "get the utask struct" },
117 #endif
118   { PIOCGEXIT,     "PIOCGEXIT",    "get traced syscall exit  set" },
119   { PIOCGFAULT,    "PIOCGFAULT",   "get traced fault set" },
120 #ifdef PIOCGFPCR                        /* osf */
121   { PIOCGFPCR,     "PIOCGFPCR",    "get FP control register" },
122   { PIOCSFPCR,     "PIOCSFPCR",    "set FP conrtol register" },
123 #endif
124   { PIOCGFPREG,    "PIOCGFPREG",   "get floating point registers" },
125   { PIOCGHOLD,     "PIOCGHOLD",    "get held signal set" },
126   { PIOCGREG,      "PIOCGREG",     "get general registers" },
127   { PIOCGROUPS,    "PIOCGROUPS",   "get supplementary groups" },
128 #ifdef PIOCGSPCACT                      /* osf */
129   { PIOCGSPCACT,   "PIOCGSPCACT",  "get special action" },
130   { PIOCSSPCACT,   "PIOCSSPCACT",  "set special action" },
131 #endif
132   { PIOCGTRACE,    "PIOCGTRACE",   "get traced signal set" },
133 #ifdef PIOCGWATCH                       /* irix watchpoints */
134   { PIOCGWATCH,    "PIOCGWATCH",   "get watchpoint" },
135   { PIOCSWATCH,    "PIOCSWATCH",   "set watchpoint" },
136   { PIOCNWATCH,    "PIOCNWATCH",   "get number of watchpoints" },
137 #endif  /* irix watchpoints */
138 #ifdef PIOCGWIN                         /* solaris sparc */
139   { PIOCGWIN,      "PIOCGWIN",     "get gwindows_t" },
140 #endif
141 #ifdef PIOCGXREG                        /* solaris sparc extra regs */
142   { PIOCGXREGSIZE, "PIOCXREGSIZE", "get extra register state size" },
143   { PIOCGXREG,     "PIOCGXREG",    "get extra register state" },
144   { PIOCSXREG,     "PIOCSXREG",    "set extra register state" },
145 #endif /* XREG */
146   { PIOCKILL,      "PIOCKILL",     "send signal" },
147 #ifdef PIOCLDT                          /* solaris i386 */
148   { PIOCLDT,       "PIOCLDT",      "get LDT" },
149   { PIOCNLDT,      "PIOCNLDT",     "get number of LDT entries" },
150 #endif
151 #ifdef PIOCLSTATUS                      /* solaris and unixware */
152   { PIOCLSTATUS,   "PIOCLSTATUS",  "get status of all lwps" },
153   { PIOCLUSAGE,    "PIOCLUSAGE",   "get resource usage of all lwps" },
154   { PIOCOPENLWP,   "PIOCOPENLWP",  "get lwp file descriptor" },
155   { PIOCLWPIDS,    "PIOCLWPIDS",   "get lwp identifiers" },
156 #endif /* LWP */
157   { PIOCMAP,       "PIOCMAP",      "get memory map information" },
158   { PIOCMAXSIG,    "PIOCMAXSIG",   "get max signal number" },
159   { PIOCNICE,      "PIOCNICE",     "set nice priority" },
160   { PIOCNMAP,      "PIOCNMAP",     "get number of memory mappings" },
161   { PIOCOPENM,     "PIOCOPENM",    "open mapped object for reading" },
162 #ifdef PIOCOPENMOBS                     /* osf */
163   { PIOCOPENMOBS,  "PIOCOPENMOBS", "open mapped object" },
164 #endif
165 #ifdef PIOCOPENPD       /* solaris */
166   { PIOCOPENPD,    "PIOCOPENPD",   "get page data file descriptor" },
167 #endif
168   { PIOCPSINFO,    "PIOCPSINFO",   "get ps(1) information" },
169   { PIOCRESET,     "PIOCRESET",    "reset process flags" },
170   { PIOCRFORK,     "PIOCRFORK",    "reset inherit-on-fork flag" },
171   { PIOCRRLC,      "PIOCRRLC",     "reset run-on-last-close flag" },
172   { PIOCRUN,       "PIOCRUN",      "make process runnable" },
173 #ifdef PIOCSAVECCNTRS                   /* irix */
174   { PIOCSAVECCNTRS, "PIOCSAVECCNTRS", "parent gets child cntrs" },
175 #endif
176   { PIOCSENTRY,    "PIOCSENTRY",   "set traced syscall entry set" },
177   { PIOCSET,       "PIOCSET",      "set process flags" },
178   { PIOCSEXIT,     "PIOCSEXIT",    "set traced syscall exit  set" },
179   { PIOCSFAULT,    "PIOCSFAULT",   "set traced fault set" },
180   { PIOCSFORK,     "PIOCSFORK",    "set inherit-on-fork flag" },
181   { PIOCSFPREG,    "PIOCSFPREG",   "set floating point registers" },
182   { PIOCSHOLD,     "PIOCSHOLD",    "set held signal set" },
183   { PIOCSREG,      "PIOCSREG",     "set general registers" },
184   { PIOCSRLC,      "PIOCSRLC",     "set run-on-last-close flag" },
185   { PIOCSSIG,      "PIOCSSIG",     "set current signal" },
186   { PIOCSTATUS,    "PIOCSTATUS",   "get process status" },
187   { PIOCSTOP,      "PIOCSTOP",     "post stop request" },
188   { PIOCSTRACE,    "PIOCSTRACE",   "set traced signal set" },
189   { PIOCUNKILL,    "PIOCUNKILL",   "delete a signal" },
190 #ifdef PIOCUSAGE        /* solaris */
191   { PIOCUSAGE,     "PIOCUSAGE",    "get resource usage" },
192 #endif
193   { PIOCWSTOP,     "PIOCWSTOP",    "wait for process to stop" },
194
195 #ifdef PIOCNTHR                         /* osf threads */
196   { PIOCNTHR,      "PIOCNTHR",     "get thread count" },
197   { PIOCRTINH,     "PIOCRTINH",    "reset inherit-on-thread-creation" },
198   { PIOCSTINH,     "PIOCSTINH",    "set   inherit-on-thread-creation" },
199   { PIOCTLIST,     "PIOCTLIST",    "get thread ids" },
200   { PIOCXPTH,      "PIOCXPTH",     "translate port to thread handle" },
201   { PIOCTRUN,      "PIOCTRUN",     "make thread runnable" },
202   { PIOCTSTATUS,   "PIOCTSTATUS",  "get thread status" },
203   { PIOCTSTOP,     "PIOCTSTOP",    "stop a thread" },
204   /* ... TGTRACE TSTRACE TSSIG TKILL TUNKILL TCFAULT TGFAULT TSFAULT
205      TGFPREG TSFPREG TGREG TSREG TACTION TTERM TABRUN TGENTRY TSENTRY
206      TGEXIT TSEXIT TSHOLD ... thread functions */
207 #endif /* osf threads */
208   { -1,            NULL,           NULL }
209 };
210
211 int
212 ioctl_with_trace (fd, opcode, ptr, file, line)
213      int  fd;
214      long opcode;
215      void *ptr;
216      char *file;
217      int  line;
218 {
219   int i, ret, arg1;
220
221   if (procfs_trace)
222     {
223       if (procfs_file == NULL && procfs_filename != NULL)
224         procfs_file = fopen (procfs_filename, "a");
225
226       for (i = 0; ioctl_table[i].name != NULL; i++)
227         if (ioctl_table[i].value == opcode)
228           break;
229
230       if (info_verbose)
231         fprintf (procfs_file ? procfs_file : stdout, 
232                  "%s:%d -- ", file, line);
233       switch (opcode) {
234       case PIOCSET:
235         arg1 = ptr ? *(long *) ptr : 0;
236         fprintf (procfs_file ? procfs_file : stdout, 
237                  "ioctl (PIOCSET,   %s) %s\n", 
238                  arg1 == PR_FORK  ? "PR_FORK"  :
239                  arg1 == PR_RLC   ? "PR_RLC"   :
240 #ifdef PR_ASYNC
241                  arg1 == PR_ASYNC ? "PR_ASYNC" :
242 #endif
243                  "<unknown flag>",
244                  info_verbose ? ioctl_table[i].desc : "");
245         break;
246       case PIOCRESET:
247         arg1 = ptr ? *(long *) ptr : 0;
248         fprintf (procfs_file ? procfs_file : stdout, 
249                  "ioctl (PIOCRESET, %s) %s\n", 
250                  arg1 == PR_FORK  ? "PR_FORK"  :
251                  arg1 == PR_RLC   ? "PR_RLC"   :
252 #ifdef PR_ASYNC
253                  arg1 == PR_ASYNC ? "PR_ASYNC" :
254 #endif
255                  "<unknown flag>",
256                  info_verbose ? ioctl_table[i].desc : "");
257         break;
258       case PIOCSTRACE:
259         fprintf (procfs_file ? procfs_file : stdout, 
260                  "ioctl (PIOCSTRACE) ");
261         proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout,
262                                      (sigset_t *) ptr, 0);
263         break;
264       case PIOCSFAULT:
265         fprintf (procfs_file ? procfs_file : stdout, 
266                  "ioctl (%s) ", 
267                  opcode == PIOCSFAULT ? "PIOCSFAULT" : "PIOCGFAULT");
268         proc_prettyfprint_faultset (procfs_file ? procfs_file : stdout,
269                                     (fltset_t *) ptr, 0);
270         break;
271       case PIOCSENTRY:
272         fprintf (procfs_file ? procfs_file : stdout, 
273                  "ioctl (%s) ", 
274                  opcode == PIOCSENTRY ? "PIOCSENTRY" : "PIOCGENTRY");
275         proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout,
276                                     (sysset_t *) ptr, 0);
277         break;
278       case PIOCSEXIT:
279         fprintf (procfs_file ? procfs_file : stdout, 
280                  "ioctl (%s) ", 
281                  opcode == PIOCSEXIT ? "PIOCSEXIT" : "PIOCGEXIT");
282         proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout,
283                                     (sysset_t *) ptr, 0);
284         break;
285       case PIOCSHOLD:
286         fprintf (procfs_file ? procfs_file : stdout, 
287                  "ioctl (%s) ", 
288                  opcode == PIOCSHOLD ? "PIOCSHOLD" : "PIOCGHOLD");
289         proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout,
290                                      (sigset_t *) ptr, 0);
291         break;
292       case PIOCSSIG:
293         fprintf (procfs_file ? procfs_file : stdout, 
294                  "ioctl (PIOCSSIG) ");
295         proc_prettyfprint_signal (procfs_file ? procfs_file : stdout,
296                                   ptr ? ((siginfo_t *) ptr)->si_signo : 0, 
297                                   0);
298         fprintf (procfs_file ? procfs_file : stdout, "\n");
299         break;
300       case PIOCRUN:
301         fprintf (procfs_file ? procfs_file : stdout, 
302                  "ioctl (PIOCRUN) ");
303         
304         arg1 = ptr ? *(long *) ptr : 0;
305         if (arg1 & PRCSIG)
306           fprintf (procfs_file ? procfs_file : stdout, "clearSig ");
307         if (arg1 & PRCFAULT)
308           fprintf (procfs_file ? procfs_file : stdout, "clearFlt ");
309         if (arg1 & PRSTRACE)
310           fprintf (procfs_file ? procfs_file : stdout, "setTrace ");
311         if (arg1 & PRSHOLD)
312           fprintf (procfs_file ? procfs_file : stdout, "setHold ");
313         if (arg1 & PRSFAULT)
314           fprintf (procfs_file ? procfs_file : stdout, "setFlt ");
315         if (arg1 & PRSVADDR)
316           fprintf (procfs_file ? procfs_file : stdout, "setVaddr ");
317         if (arg1 & PRSTEP)
318           fprintf (procfs_file ? procfs_file : stdout, "step ");
319         if (arg1 & PRSABORT)
320           fprintf (procfs_file ? procfs_file : stdout, "syscallAbort ");
321         if (arg1 & PRSTOP)
322           fprintf (procfs_file ? procfs_file : stdout, "stopReq ");
323           
324         fprintf (procfs_file ? procfs_file : stdout, "\n");
325         break;
326       case PIOCKILL:
327         fprintf (procfs_file ? procfs_file : stdout, 
328                  "ioctl (PIOCKILL) ");
329         proc_prettyfprint_signal (procfs_file ? procfs_file : stdout,
330                                   ptr ? *(long *) ptr : 0, 0);
331         fprintf (procfs_file ? procfs_file : stdout, "\n");
332         break;
333 #ifdef PIOCSSPCACT
334       case PIOCSSPCACT:
335         fprintf (procfs_file ? procfs_file : stdout, 
336                  "ioctl (PIOCSSPCACT) ");
337         arg1 = ptr ? *(long *) ptr : 0;
338         if (arg1 & PRFS_STOPFORK)
339           fprintf (procfs_file ? procfs_file : stdout, "stopFork ");
340         if (arg1 & PRFS_STOPEXEC)
341           fprintf (procfs_file ? procfs_file : stdout, "stopExec ");
342         if (arg1 & PRFS_STOPTERM)
343           fprintf (procfs_file ? procfs_file : stdout, "stopTerm ");
344         if (arg1 & PRFS_STOPTCR)
345           fprintf (procfs_file ? procfs_file : stdout, "stopThreadCreate ");
346         if (arg1 & PRFS_STOPTTERM)
347           fprintf (procfs_file ? procfs_file : stdout, "stopThreadTerm ");
348         if (arg1 & PRFS_KOLC)
349           fprintf (procfs_file ? procfs_file : stdout, "killOnLastClose ");
350         fprintf (procfs_file ? procfs_file : stdout, "\n");
351         break;
352 #endif /* PIOCSSPCACT */
353       default:
354         if (ioctl_table[i].name)
355           fprintf (procfs_file ? procfs_file : stdout, 
356                    "ioctl (%s) %s\n", 
357                    ioctl_table[i].name,
358                    info_verbose ? ioctl_table[i].desc : "");
359         else
360           fprintf (procfs_file ? procfs_file : stdout, 
361                    "ioctl (<unknown %ld (0x%lx)) \n", opcode, opcode);
362         break;
363       }
364       if (procfs_file)
365         fflush (procfs_file);
366     }
367   ret = ioctl (fd, opcode, ptr);
368   if (procfs_trace && ret < 0)
369     {
370       fprintf (procfs_file ? procfs_file : stdout, 
371                "[ioctl (%s) FAILED!]\n",
372                ioctl_table[i].name != NULL ? 
373                ioctl_table[i].name : "<unknown>");
374       if (procfs_file)
375         fflush (procfs_file);
376     }
377
378   return ret;
379 }
380
381 #else   /* NEW_PROC_API */
382
383 static struct trans rw_table[] = {
384 #ifdef PCAGENT                  /* solaris */
385   { PCAGENT,  "PCAGENT",  "create agent lwp with regs from argument" },
386 #endif
387   { PCCFAULT, "PCCFAULT", "clear current fault" },
388 #ifdef PCCSIG                   /* solaris */
389   { PCCSIG,   "PCCSIG",   "clear current signal" },
390 #endif
391   { PCDSTOP,  "PCDSTOP",  "post stop request" },
392   { PCKILL,   "PCKILL",   "post a signal" },
393   { PCNICE,   "PCNICE",   "set nice priority" },
394 #ifdef PCREAD                   /* solaris */
395   { PCREAD,   "PCREAD",   "read from the address space" },
396   { PCWRITE,  "PCWRITE",  "write to the address space" },
397 #endif
398 #ifdef PCRESET                  /* unixware */
399   { PCRESET,  "PCRESET",  "unset modes" },
400 #endif
401   { PCRUN,    "PCRUN",    "make process/lwp runnable" },
402 #ifdef PCSASRS                  /* solaris 2.7 only */
403   { PCSASRS,  "PCSASRS",  "set ancillary state registers" },
404 #endif
405 #ifdef PCSCRED                  /* solaris */
406   { PCSCRED,  "PCSCRED",  "set process credentials" },
407 #endif
408   { PCSENTRY, "PCSENTRY", "set traced syscall entry set" },
409   { PCSET,    "PCSET",    "set modes" },
410   { PCSEXIT,  "PCSEXIT",  "set traced syscall exit  set" },
411   { PCSFAULT, "PCSFAULT", "set traced fault set" },
412   { PCSFPREG, "PCSFPREG", "set floating point registers" },
413   { PCSHOLD,  "PCSHOLD",  "set signal mask" },
414   { PCSREG,   "PCSREG",   "set general registers" },
415   { PCSSIG,   "PCSSIG",   "set current signal" },
416   { PCSTOP,   "PCSTOP",   "post stop request and wait" },
417   { PCSTRACE, "PCSTRACE", "set traced signal set" },
418 #ifdef PCSVADDR                 /* solaris */
419   { PCSVADDR, "PCSVADDR", "set pc virtual address" },
420 #endif
421 #ifdef PCSXREG                  /* solaris sparc only */
422   { PCSXREG,  "PCSXREG",  "set extra registers" },
423 #endif
424 #ifdef PCTWSTOP                 /* solaris */
425   { PCTWSTOP, "PCTWSTOP", "wait for stop, with timeout arg" },
426 #endif
427   { PCUNKILL, "PCUNKILL", "delete a pending signal" },
428 #ifdef PCUNSET                  /* solaris */
429   { PCUNSET,  "PCUNSET",  "unset modes" },
430 #endif
431 #ifdef PCWATCH                  /* solaris */
432   { PCWATCH,  "PCWATCH",  "set/unset watched memory area" },
433 #endif
434   { PCWSTOP,  "PCWSTOP",  "wait for process/lwp to stop, no timeout" },
435   { 0,        NULL,      NULL }
436 };
437
438 static off_t lseek_offset;
439
440 int
441 write_with_trace (fd, arg, len, file, line)
442      int  fd;
443      long *arg;
444      size_t len;
445      char *file;
446      int  line;
447 {
448   int  i;
449   int ret;
450   long opcode = arg[0];
451
452   if (procfs_trace)
453     {
454       if (procfs_file == NULL && procfs_filename != NULL)
455         procfs_file = fopen (procfs_filename, "a");
456
457       for (i = 0; rw_table[i].name != NULL; i++)
458         if (rw_table[i].value == opcode)
459           break;
460
461       if (info_verbose)
462         fprintf (procfs_file ? procfs_file : stdout, 
463                  "%s:%d -- ", file, line);
464       switch (opcode) {
465       case PCSET:
466         fprintf (procfs_file ? procfs_file : stdout, 
467                  "write (PCSET,   %s) %s\n", 
468                  arg[1] == PR_FORK  ? "PR_FORK"  :
469                  arg[1] == PR_RLC   ? "PR_RLC"   :
470 #ifdef PR_ASYNC
471                  arg[1] == PR_ASYNC ? "PR_ASYNC" :
472 #endif
473                  "<unknown flag>",
474                  info_verbose ? rw_table[i].desc : "");
475         break;
476 #ifdef PCUNSET
477       case PCUNSET:
478 #endif
479 #ifdef PCRESET
480       case PCRESET:
481 #endif
482         fprintf (procfs_file ? procfs_file : stdout, 
483                  "write (PCRESET, %s) %s\n", 
484                  arg[1] == PR_FORK  ? "PR_FORK"  :
485                  arg[1] == PR_RLC   ? "PR_RLC"   :
486 #ifdef PR_ASYNC
487                  arg[1] == PR_ASYNC ? "PR_ASYNC" :
488 #endif
489                  "<unknown flag>",
490                  info_verbose ? rw_table[i].desc : "");
491         break;
492       case PCSTRACE:
493         fprintf (procfs_file ? procfs_file : stdout, 
494                  "write (PCSTRACE) ");
495         proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout,
496                                      (sigset_t *) &arg[1], 0);
497         break;
498       case PCSFAULT:
499         fprintf (procfs_file ? procfs_file : stdout, 
500                  "write (PCSFAULT) ");
501         proc_prettyfprint_faultset (procfs_file ? procfs_file : stdout,
502                                     (fltset_t *) &arg[1], 0);
503         break;
504       case PCSENTRY:
505         fprintf (procfs_file ? procfs_file : stdout, 
506                  "write (PCSENTRY) ");
507         proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout,
508                                     (sysset_t *) &arg[1], 0);
509         break;
510       case PCSEXIT:
511         fprintf (procfs_file ? procfs_file : stdout, 
512                  "write (PCSEXIT) ");
513         proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout,
514                                     (sysset_t *) &arg[1], 0);
515         break;
516       case PCSHOLD:
517         fprintf (procfs_file ? procfs_file : stdout, 
518                  "write (PCSHOLD) ");
519         proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout,
520                                      (sigset_t *) &arg[1], 0);
521         break;
522       case PCSSIG:
523         fprintf (procfs_file ? procfs_file : stdout, 
524                  "write (PCSSIG) ");
525         proc_prettyfprint_signal (procfs_file ? procfs_file : stdout,
526                                   arg[1] ? ((siginfo_t *) &arg[1])->si_signo 
527                                          : 0, 
528                                   0);
529         fprintf (procfs_file ? procfs_file : stdout, "\n");
530         break;
531       case PCRUN:
532         fprintf (procfs_file ? procfs_file : stdout, 
533                  "write (PCRUN) ");
534         if (arg[1] & PRCSIG)
535           fprintf (procfs_file ? procfs_file : stdout, "clearSig ");
536         if (arg[1] & PRCFAULT)
537           fprintf (procfs_file ? procfs_file : stdout, "clearFlt ");
538         if (arg[1] & PRSTEP)
539           fprintf (procfs_file ? procfs_file : stdout, "step ");
540         if (arg[1] & PRSABORT)
541           fprintf (procfs_file ? procfs_file : stdout, "syscallAbort ");
542         if (arg[1] & PRSTOP)
543           fprintf (procfs_file ? procfs_file : stdout, "stopReq ");
544           
545         fprintf (procfs_file ? procfs_file : stdout, "\n");
546         break;
547       case PCKILL:
548         fprintf (procfs_file ? procfs_file : stdout, 
549                  "write (PCKILL) ");
550         proc_prettyfprint_signal (procfs_file ? procfs_file : stdout,
551                                   arg[1], 0);
552         fprintf (procfs_file ? procfs_file : stdout, "\n");
553         break;
554       default:
555         {
556           static unsigned char break_insn[] = BREAKPOINT;
557
558           if (len == sizeof (break_insn) &&
559               memcmp (arg, &break_insn, len) == 0)
560             fprintf (procfs_file ? procfs_file : stdout, 
561                      "write (<breakpoint at 0x%08lx>) \n", 
562                      (unsigned long) lseek_offset);
563           else if (rw_table[i].name)
564             fprintf (procfs_file ? procfs_file : stdout, 
565                      "write (%s) %s\n", 
566                      rw_table[i].name, 
567                      info_verbose ? rw_table[i].desc : "");
568           else
569             {
570               if (lseek_offset != -1)
571                 fprintf (procfs_file ? procfs_file : stdout, 
572                          "write (<unknown>, %lud bytes at 0x%08lx) \n", 
573                          (unsigned long) len, (unsigned long) lseek_offset);
574               else
575                 fprintf (procfs_file ? procfs_file : stdout, 
576                          "write (<unknown>, %lud bytes) \n", 
577                          (unsigned long) len);
578             }
579           break;
580         }
581       }
582       if (procfs_file)
583         fflush (procfs_file);
584     }
585   ret = write (fd, (void *) arg, len);
586   if (procfs_trace && ret != len)
587     {
588       fprintf (procfs_file ? procfs_file : stdout, 
589                "[write (%s) FAILED!\n",
590                rw_table[i].name != NULL ? 
591                rw_table[i].name : "<unknown>");
592       if (procfs_file)
593         fflush (procfs_file);
594     }
595
596   lseek_offset = -1;
597   return ret;
598 }
599
600 off_t
601 lseek_with_trace (fd, offset, whence, file, line)
602      int fd;
603      off_t offset;
604      int whence;
605      char *file;
606      int line;
607 {
608   off_t ret;
609
610 #if 0   /* don't need output, just need address */
611   if (procfs_trace)
612     {
613       if (procfs_file == NULL && procfs_filename != NULL)
614         procfs_file = fopen (procfs_filename, "a");
615
616       if (info_verbose)
617         fprintf (procfs_file ? procfs_file : stdout, 
618                  "%s:%d -- ", file, line);
619       fprintf (procfs_file ? procfs_file : stdout, 
620                "lseek (0x%08x, %s) \n", offset, 
621                whence == SEEK_SET ? "SEEK_SET" :
622                whence == SEEK_CUR ? "SEEK_CUR" : 
623                whence == SEEK_END ? "SEEK_END" :
624                "<unknown whence>");
625       if (procfs_file)
626         fflush (procfs_file);
627     }
628 #endif
629   ret = lseek (fd, offset, whence);
630   lseek_offset = ret;
631   if (procfs_trace && ret == -1)
632     {
633       if (procfs_file == NULL && procfs_filename != NULL)
634         procfs_file = fopen (procfs_filename, "a");
635
636       fprintf (procfs_file ? procfs_file : stdout, 
637                "[lseek (0x%08lx) FAILED!\n", (unsigned long) offset);
638       if (procfs_file)
639         fflush (procfs_file);
640     }
641
642   return ret;
643 }
644
645 #endif /* NEW_PROC_API */
646
647 int
648 open_with_trace (filename, mode, file, line)
649      char *filename;
650      int   mode;
651      char *file;
652      int   line;
653 {
654   int ret = open (filename, mode);
655
656   if (procfs_trace)
657     {
658       if (procfs_file == NULL && procfs_filename != NULL)
659         procfs_file = fopen (procfs_filename, "a");
660
661       if (info_verbose)
662         fprintf (procfs_file ? procfs_file : stdout, 
663                  "%s:%d -- ", file, line);
664       fprintf (procfs_file ? procfs_file : stdout, 
665                "%d = open (%s, ", ret, filename);
666       if (mode == O_RDONLY)
667         fprintf (procfs_file ? procfs_file : stdout, "O_RDONLY) %d\n", line);
668       else if (mode == O_WRONLY)
669         fprintf (procfs_file ? procfs_file : stdout, "O_WRONLY) %d\n", line);
670       else if (mode == O_RDWR)
671         fprintf (procfs_file ? procfs_file : stdout, "O_RDWR)   %d\n", line);
672       if (procfs_file)
673         fflush (procfs_file);
674     }
675
676   return ret;
677 }
678
679 int
680 close_with_trace (fd, file, line)
681      int   fd;
682      char *file;
683      int   line;
684 {
685   int ret = close (fd);
686
687   if (procfs_trace)
688     {
689       if (procfs_file == NULL && procfs_filename != NULL)
690         procfs_file = fopen (procfs_filename, "a");
691
692       if (info_verbose)
693         fprintf (procfs_file ? procfs_file : stdout, 
694                  "%s:%d -- ", file, line);
695       fprintf (procfs_file ? procfs_file : stdout, 
696                "%d = close (%d)\n", ret, fd);
697       if (procfs_file)
698         fflush (procfs_file);
699     }
700
701   return ret;
702 }
703
704 int
705 wait_with_trace (wstat, file, line)
706      int  *wstat;
707      char *file;
708      int   line;
709 {
710   int ret, lstat = 0;
711
712   if (procfs_trace)
713     {
714       if (procfs_file == NULL && procfs_filename != NULL)
715         procfs_file = fopen (procfs_filename, "a");
716
717       if (info_verbose)
718         fprintf (procfs_file ? procfs_file : stdout, 
719                  "%s:%d -- ", file, line);
720       fprintf (procfs_file ? procfs_file : stdout, 
721                "wait (line %d) ", line);
722       if (procfs_file)
723         fflush (procfs_file);
724     }
725   ret = wait (&lstat);
726   if (procfs_trace)
727     {
728       fprintf (procfs_file ? procfs_file : stdout, 
729                "returned pid %d, status 0x%x\n", ret, lstat);
730       if (procfs_file)
731         fflush (procfs_file);
732     }
733   if (wstat)
734     *wstat = lstat;
735
736   return ret;
737 }
738
739 void
740 procfs_note (msg, file, line)
741      char *msg;
742      char *file;
743      int   line;
744 {
745   if (procfs_trace)
746     {
747       if (procfs_file == NULL && procfs_filename != NULL)
748         procfs_file = fopen (procfs_filename, "a");
749
750       if (info_verbose)
751         fprintf (procfs_file ? procfs_file : stdout, 
752                  "%s:%d -- ", file, line);
753       fprintf (procfs_file ? procfs_file : stdout, msg);
754       if (procfs_file)
755         fflush (procfs_file);
756     }
757 }
758
759 void
760 proc_prettyfprint_status (flags, why, what, thread)
761      long flags;
762      int  why;
763      int  what;
764      int  thread;
765 {
766   if (procfs_trace)
767     {
768       if (procfs_file == NULL && procfs_filename != NULL)
769         procfs_file = fopen (procfs_filename, "a");
770
771       if (thread)
772         fprintf (procfs_file ? procfs_file : stdout,
773                  "Thread %d: ", thread);
774
775       proc_prettyfprint_flags (procfs_file ? procfs_file : stdout, 
776                                flags, 0);
777
778       if (flags & (PR_STOPPED | PR_ISTOP))
779         proc_prettyfprint_why (procfs_file ? procfs_file : stdout, 
780                                why, what, 0);
781       if (procfs_file)
782         fflush (procfs_file);
783     }
784 }
785
786
787 void
788 _initialize_proc_api ()
789 {
790   struct cmd_list_element *c;
791
792   c = add_set_cmd ("procfs-trace", no_class,
793                    var_boolean, (char *) &procfs_trace, 
794                    "Set tracing for /proc ioctl calls.\n", &setlist);
795
796   add_show_from_set (c, &showlist);
797   c->function.sfunc = set_procfs_trace_cmd;
798
799   c = add_set_cmd ("procfs-file", no_class, var_filename,
800                    (char *) &procfs_filename, 
801                    "Set filename for /proc tracefile.\n", &setlist);
802
803   add_show_from_set (c, &showlist);
804   c->function.sfunc = set_procfs_file_cmd;
805
806 #ifdef TRACE_PROCFS
807   if (procfs_file == NULL && procfs_filename != NULL)
808     procfs_file = fopen (procfs_filename, "a");
809 #endif
810 }