OSDN Git Service

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