]> Git Repo - binutils.git/blob - gdb/proc-api.c
2002-11-09 Klee Dienes <[email protected]>
[binutils.git] / gdb / proc-api.c
1 /* Machine independent support for SVR4 /proc (process file system) for GDB.
2    Copyright 1999, 2000, 2001 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 #include "completer.h"
31
32 #if defined (NEW_PROC_API)
33 #define _STRUCTURED_PROC 1
34 #endif
35
36 #include <stdio.h>
37 #include <sys/types.h>
38 #include <sys/procfs.h>
39 #ifdef HAVE_SYS_PROC_H
40 #include <sys/proc.h>   /* for struct proc */
41 #endif
42 #ifdef HAVE_SYS_USER_H
43 #include <sys/user.h>   /* for struct user */
44 #endif
45 #include <fcntl.h>      /* for O_RDWR etc. */
46 #include <sys/wait.h>
47
48 #include "proc-utils.h"
49
50 /*  Much of the information used in the /proc interface, particularly for
51     printing status information, is kept as tables of structures of the
52     following form.  These tables can be used to map numeric values to
53     their symbolic names and to a string that describes their specific use. */
54
55 struct trans {
56   long value;                   /* The numeric value */
57   char *name;                   /* The equivalent symbolic value */
58   char *desc;                   /* Short description of value */
59 };
60
61 static int   procfs_trace    = 0;
62 static FILE *procfs_file     = NULL;
63 static char *procfs_filename = "procfs_trace";
64
65 static void
66 prepare_to_trace (void)
67 {
68   if (procfs_trace)                     /* if procfs tracing turned on */
69     if (procfs_file == NULL)            /* if output file not yet open */
70       if (procfs_filename != NULL)      /* if output filename known */
71         procfs_file = fopen (procfs_filename, "a");     /* open output file */
72 }
73
74 static void
75 set_procfs_trace_cmd (char *args, int from_tty, struct cmd_list_element *c)
76 {
77 #if 0   /* not sure what I might actually need to do here, if anything */
78   if (procfs_file)
79     fflush (procfs_file);
80 #endif
81 }
82
83 static void
84 set_procfs_file_cmd (char *args, int from_tty, struct cmd_list_element *c)
85 {
86   /* Just changed the filename for procfs tracing.
87      If a file was already open, close it.  */
88   if (procfs_file)
89     fclose (procfs_file);
90   procfs_file = NULL;
91 }
92
93
94 #ifndef NEW_PROC_API
95
96 static struct trans ioctl_table[] = {
97 #ifdef PIOCACINFO                       /* irix */
98   { PIOCACINFO,    "PIOCACINFO",   "get process account info" },
99 #endif
100   { PIOCACTION,    "PIOCACTION",   "get signal action structs" },
101 #ifdef PIOCARGUMENTS                    /* osf */
102   { PIOCARGUMENTS, "PIOCARGUMENTS", "command line args" },
103 #endif
104 #ifdef PIOCAUXV                         /* solaris aux vectors */
105   { PIOCAUXV,      "PIOCAUXV",     "get aux vector" },
106   { PIOCNAUXV,     "PIOCNAUXV",    "get number of aux vector entries" },
107 #endif /* AUXV */
108   { PIOCCFAULT,    "PIOCCFAULT",   "clear current fault" },
109   { PIOCCRED,      "PIOCCRED",     "get process credentials" },
110 #ifdef PIOCENEVCTRS                     /* irix event counters */
111   { PIOCENEVCTRS,    "PIOCENEVCTRS",    "acquire and start event counters" },
112   { PIOCGETEVCTRL,   "PIOCGETEVCTRL",   "get control info of event counters" },
113   { PIOCGETEVCTRS,   "PIOCGETEVCTRS",   "dump event counters" },
114   { PIOCGETPREVCTRS, "PIOCGETPREVCTRS", "dump event counters & prusage info" },
115   { PIOCRELEVCTRS,   "PIOCRELEVCTRS",   "release/stop event counters" },
116   { PIOCSETEVCTRL,   "PIOCSETEVCTRL",   "set control info of event counters" },
117   { PIOCGETPTIMER,   "PIOCGETPTIMER",   "get process timers" },
118 #endif  /* irix event counters */
119   { PIOCGENTRY,    "PIOCGENTRY",   "get traced syscall entry set" },
120 #if defined (PIOCGETPR)
121   { PIOCGETPR,     "PIOCGETPR",    "read struct proc" },
122 #endif
123 #if defined (PIOCGETU)
124   { PIOCGETU,      "PIOCGETU",     "read user area" },
125 #endif
126 #if defined (PIOCGETUTK) && (defined(KERNEL) || defined(SHOW_UTT)) /* osf */
127   { PIOCGETUTK,  "PIOCGETUTK", "get the utask struct" },
128 #endif
129   { PIOCGEXIT,     "PIOCGEXIT",    "get traced syscall exit  set" },
130   { PIOCGFAULT,    "PIOCGFAULT",   "get traced fault set" },
131 #ifdef PIOCGFPCR                        /* osf */
132   { PIOCGFPCR,     "PIOCGFPCR",    "get FP control register" },
133   { PIOCSFPCR,     "PIOCSFPCR",    "set FP conrtol register" },
134 #endif
135   { PIOCGFPREG,    "PIOCGFPREG",   "get floating point registers" },
136   { PIOCGHOLD,     "PIOCGHOLD",    "get held signal set" },
137   { PIOCGREG,      "PIOCGREG",     "get general registers" },
138   { PIOCGROUPS,    "PIOCGROUPS",   "get supplementary groups" },
139 #ifdef PIOCGSPCACT                      /* osf */
140   { PIOCGSPCACT,   "PIOCGSPCACT",  "get special action" },
141   { PIOCSSPCACT,   "PIOCSSPCACT",  "set special action" },
142 #endif
143   { PIOCGTRACE,    "PIOCGTRACE",   "get traced signal set" },
144 #ifdef PIOCGWATCH                       /* irix watchpoints */
145   { PIOCGWATCH,    "PIOCGWATCH",   "get watchpoint" },
146   { PIOCSWATCH,    "PIOCSWATCH",   "set watchpoint" },
147   { PIOCNWATCH,    "PIOCNWATCH",   "get number of watchpoints" },
148 #endif  /* irix watchpoints */
149 #ifdef PIOCGWIN                         /* solaris sparc */
150   { PIOCGWIN,      "PIOCGWIN",     "get gwindows_t" },
151 #endif
152 #ifdef PIOCGXREG                        /* solaris sparc extra regs */
153   { PIOCGXREGSIZE, "PIOCXREGSIZE", "get extra register state size" },
154   { PIOCGXREG,     "PIOCGXREG",    "get extra register state" },
155   { PIOCSXREG,     "PIOCSXREG",    "set extra register state" },
156 #endif /* XREG */
157   { PIOCKILL,      "PIOCKILL",     "send signal" },
158 #ifdef PIOCLDT                          /* solaris i386 */
159   { PIOCLDT,       "PIOCLDT",      "get LDT" },
160   { PIOCNLDT,      "PIOCNLDT",     "get number of LDT entries" },
161 #endif
162 #ifdef PIOCLSTATUS                      /* solaris and unixware */
163   { PIOCLSTATUS,   "PIOCLSTATUS",  "get status of all lwps" },
164   { PIOCLUSAGE,    "PIOCLUSAGE",   "get resource usage of all lwps" },
165   { PIOCOPENLWP,   "PIOCOPENLWP",  "get lwp file descriptor" },
166   { PIOCLWPIDS,    "PIOCLWPIDS",   "get lwp identifiers" },
167 #endif /* LWP */
168   { PIOCMAP,       "PIOCMAP",      "get memory map information" },
169   { PIOCMAXSIG,    "PIOCMAXSIG",   "get max signal number" },
170   { PIOCNICE,      "PIOCNICE",     "set nice priority" },
171   { PIOCNMAP,      "PIOCNMAP",     "get number of memory mappings" },
172   { PIOCOPENM,     "PIOCOPENM",    "open mapped object for reading" },
173 #ifdef PIOCOPENMOBS                     /* osf */
174   { PIOCOPENMOBS,  "PIOCOPENMOBS", "open mapped object" },
175 #endif
176 #ifdef PIOCOPENPD       /* solaris */
177   { PIOCOPENPD,    "PIOCOPENPD",   "get page data file descriptor" },
178 #endif
179   { PIOCPSINFO,    "PIOCPSINFO",   "get ps(1) information" },
180   { PIOCRESET,     "PIOCRESET",    "reset process flags" },
181   { PIOCRFORK,     "PIOCRFORK",    "reset inherit-on-fork flag" },
182   { PIOCRRLC,      "PIOCRRLC",     "reset run-on-last-close flag" },
183   { PIOCRUN,       "PIOCRUN",      "make process runnable" },
184 #ifdef PIOCSAVECCNTRS                   /* irix */
185   { PIOCSAVECCNTRS, "PIOCSAVECCNTRS", "parent gets child cntrs" },
186 #endif
187   { PIOCSENTRY,    "PIOCSENTRY",   "set traced syscall entry set" },
188   { PIOCSET,       "PIOCSET",      "set process flags" },
189   { PIOCSEXIT,     "PIOCSEXIT",    "set traced syscall exit  set" },
190   { PIOCSFAULT,    "PIOCSFAULT",   "set traced fault set" },
191   { PIOCSFORK,     "PIOCSFORK",    "set inherit-on-fork flag" },
192   { PIOCSFPREG,    "PIOCSFPREG",   "set floating point registers" },
193   { PIOCSHOLD,     "PIOCSHOLD",    "set held signal set" },
194   { PIOCSREG,      "PIOCSREG",     "set general registers" },
195   { PIOCSRLC,      "PIOCSRLC",     "set run-on-last-close flag" },
196   { PIOCSSIG,      "PIOCSSIG",     "set current signal" },
197   { PIOCSTATUS,    "PIOCSTATUS",   "get process status" },
198   { PIOCSTOP,      "PIOCSTOP",     "post stop request" },
199   { PIOCSTRACE,    "PIOCSTRACE",   "set traced signal set" },
200   { PIOCUNKILL,    "PIOCUNKILL",   "delete a signal" },
201 #ifdef PIOCUSAGE        /* solaris */
202   { PIOCUSAGE,     "PIOCUSAGE",    "get resource usage" },
203 #endif
204   { PIOCWSTOP,     "PIOCWSTOP",    "wait for process to stop" },
205
206 #ifdef PIOCNTHR                         /* osf threads */
207   { PIOCNTHR,      "PIOCNTHR",     "get thread count" },
208   { PIOCRTINH,     "PIOCRTINH",    "reset inherit-on-thread-creation" },
209   { PIOCSTINH,     "PIOCSTINH",    "set   inherit-on-thread-creation" },
210   { PIOCTLIST,     "PIOCTLIST",    "get thread ids" },
211   { PIOCXPTH,      "PIOCXPTH",     "translate port to thread handle" },
212   { PIOCTRUN,      "PIOCTRUN",     "make thread runnable" },
213   { PIOCTSTATUS,   "PIOCTSTATUS",  "get thread status" },
214   { PIOCTSTOP,     "PIOCTSTOP",    "stop a thread" },
215   /* ... TGTRACE TSTRACE TSSIG TKILL TUNKILL TCFAULT TGFAULT TSFAULT
216      TGFPREG TSFPREG TGREG TSREG TACTION TTERM TABRUN TGENTRY TSENTRY
217      TGEXIT TSEXIT TSHOLD ... thread functions */
218 #endif /* osf threads */
219   { -1,            NULL,           NULL }
220 };
221
222 int
223 ioctl_with_trace (int fd, long opcode, void *ptr, char *file, int line)
224 {
225   int i = 0;
226   int ret;
227   int 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 #ifdef PCDSTOP                  /* solaris */
401   { PCDSTOP,  "PCDSTOP",  "post stop request" },
402 #endif
403   { PCKILL,   "PCKILL",   "post a signal" },
404 #ifdef PCNICE                   /* solaris */
405   { PCNICE,   "PCNICE",   "set nice priority" },
406 #endif
407 #ifdef PCREAD                   /* solaris */
408   { PCREAD,   "PCREAD",   "read from the address space" },
409   { PCWRITE,  "PCWRITE",  "write to the address space" },
410 #endif
411 #ifdef PCRESET                  /* unixware */
412   { PCRESET,  "PCRESET",  "unset modes" },
413 #endif
414   { PCRUN,    "PCRUN",    "make process/lwp runnable" },
415 #ifdef PCSASRS                  /* solaris 2.7 only */
416   { PCSASRS,  "PCSASRS",  "set ancillary state registers" },
417 #endif
418 #ifdef PCSCRED                  /* solaris */
419   { PCSCRED,  "PCSCRED",  "set process credentials" },
420 #endif
421   { PCSENTRY, "PCSENTRY", "set traced syscall entry set" },
422   { PCSET,    "PCSET",    "set modes" },
423   { PCSEXIT,  "PCSEXIT",  "set traced syscall exit  set" },
424   { PCSFAULT, "PCSFAULT", "set traced fault set" },
425   { PCSFPREG, "PCSFPREG", "set floating point registers" },
426 #ifdef PCSHOLD                  /* solaris */
427   { PCSHOLD,  "PCSHOLD",  "set signal mask" },
428 #endif
429   { PCSREG,   "PCSREG",   "set general registers" },
430   { PCSSIG,   "PCSSIG",   "set current signal" },
431   { PCSTOP,   "PCSTOP",   "post stop request and wait" },
432   { PCSTRACE, "PCSTRACE", "set traced signal set" },
433 #ifdef PCSVADDR                 /* solaris */
434   { PCSVADDR, "PCSVADDR", "set pc virtual address" },
435 #endif
436 #ifdef PCSXREG                  /* solaris sparc only */
437   { PCSXREG,  "PCSXREG",  "set extra registers" },
438 #endif
439 #ifdef PCTWSTOP                 /* solaris */
440   { PCTWSTOP, "PCTWSTOP", "wait for stop, with timeout arg" },
441 #endif
442 #ifdef PCUNKILL                 /* solaris */
443   { PCUNKILL, "PCUNKILL", "delete a pending signal" },
444 #endif
445 #ifdef PCUNSET                  /* solaris */
446   { PCUNSET,  "PCUNSET",  "unset modes" },
447 #endif
448 #ifdef PCWATCH                  /* solaris */
449   { PCWATCH,  "PCWATCH",  "set/unset watched memory area" },
450 #endif
451   { PCWSTOP,  "PCWSTOP",  "wait for process/lwp to stop, no timeout" },
452   { 0,        NULL,      NULL }
453 };
454
455 static off_t lseek_offset;
456
457 int
458 write_with_trace (int fd, void *varg, size_t len, char *file, int line)
459 {
460   int  i;
461   int ret;
462   procfs_ctl_t *arg = (procfs_ctl_t *) varg;
463
464   prepare_to_trace ();
465   if (procfs_trace)
466     {
467       procfs_ctl_t opcode = arg[0];
468       for (i = 0; rw_table[i].name != NULL; i++)
469         if (rw_table[i].value == opcode)
470           break;
471
472       if (info_verbose)
473         fprintf (procfs_file ? procfs_file : stdout, 
474                  "%s:%d -- ", file, line);
475       switch (opcode) {
476       case PCSET:
477         fprintf (procfs_file ? procfs_file : stdout, 
478                  "write (PCSET,   %s) %s\n", 
479                  arg[1] == PR_FORK  ? "PR_FORK"  :
480                  arg[1] == PR_RLC   ? "PR_RLC"   :
481 #ifdef PR_ASYNC
482                  arg[1] == PR_ASYNC ? "PR_ASYNC" :
483 #endif
484                  "<unknown flag>",
485                  info_verbose ? rw_table[i].desc : "");
486         break;
487 #ifdef PCUNSET
488       case PCUNSET:
489 #endif
490 #ifdef PCRESET
491 #if PCRESET != PCUNSET
492       case PCRESET:
493 #endif
494 #endif
495         fprintf (procfs_file ? procfs_file : stdout, 
496                  "write (PCRESET, %s) %s\n", 
497                  arg[1] == PR_FORK  ? "PR_FORK"  :
498                  arg[1] == PR_RLC   ? "PR_RLC"   :
499 #ifdef PR_ASYNC
500                  arg[1] == PR_ASYNC ? "PR_ASYNC" :
501 #endif
502                  "<unknown flag>",
503                  info_verbose ? rw_table[i].desc : "");
504         break;
505       case PCSTRACE:
506         fprintf (procfs_file ? procfs_file : stdout, 
507                  "write (PCSTRACE) ");
508         proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout,
509                                      (sigset_t *) &arg[1], 0);
510         break;
511       case PCSFAULT:
512         fprintf (procfs_file ? procfs_file : stdout, 
513                  "write (PCSFAULT) ");
514         proc_prettyfprint_faultset (procfs_file ? procfs_file : stdout,
515                                     (fltset_t *) &arg[1], 0);
516         break;
517       case PCSENTRY:
518         fprintf (procfs_file ? procfs_file : stdout, 
519                  "write (PCSENTRY) ");
520         proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout,
521                                     (sysset_t *) &arg[1], 0);
522         break;
523       case PCSEXIT:
524         fprintf (procfs_file ? procfs_file : stdout, 
525                  "write (PCSEXIT) ");
526         proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout,
527                                     (sysset_t *) &arg[1], 0);
528         break;
529 #ifdef PCSHOLD
530       case PCSHOLD:
531         fprintf (procfs_file ? procfs_file : stdout, 
532                  "write (PCSHOLD) ");
533         proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout,
534                                      (sigset_t *) &arg[1], 0);
535         break;
536 #endif
537       case PCSSIG:
538         fprintf (procfs_file ? procfs_file : stdout, 
539                  "write (PCSSIG) ");
540         proc_prettyfprint_signal (procfs_file ? procfs_file : stdout,
541                                   arg[1] ? ((siginfo_t *) &arg[1])->si_signo 
542                                          : 0, 
543                                   0);
544         fprintf (procfs_file ? procfs_file : stdout, "\n");
545         break;
546       case PCRUN:
547         fprintf (procfs_file ? procfs_file : stdout, 
548                  "write (PCRUN) ");
549         if (arg[1] & PRCSIG)
550           fprintf (procfs_file ? procfs_file : stdout, "clearSig ");
551         if (arg[1] & PRCFAULT)
552           fprintf (procfs_file ? procfs_file : stdout, "clearFlt ");
553         if (arg[1] & PRSTEP)
554           fprintf (procfs_file ? procfs_file : stdout, "step ");
555 #ifdef PRSABORT
556         if (arg[1] & PRSABORT)
557           fprintf (procfs_file ? procfs_file : stdout, "syscallAbort ");
558 #endif
559 #ifdef PRSTOP
560         if (arg[1] & PRSTOP)
561           fprintf (procfs_file ? procfs_file : stdout, "stopReq ");
562 #endif
563           
564         fprintf (procfs_file ? procfs_file : stdout, "\n");
565         break;
566       case PCKILL:
567         fprintf (procfs_file ? procfs_file : stdout, 
568                  "write (PCKILL) ");
569         proc_prettyfprint_signal (procfs_file ? procfs_file : stdout,
570                                   arg[1], 0);
571         fprintf (procfs_file ? procfs_file : stdout, "\n");
572         break;
573       default:
574         {
575 #ifdef BREAKPOINT
576           static unsigned char break_insn[] = BREAKPOINT;
577
578           if (len == sizeof (break_insn) &&
579               memcmp (arg, &break_insn, len) == 0)
580             fprintf (procfs_file ? procfs_file : stdout, 
581                      "write (<breakpoint at 0x%08lx>) \n", 
582                      (unsigned long) lseek_offset);
583           else 
584 #endif
585           if (rw_table[i].name)
586             fprintf (procfs_file ? procfs_file : stdout, 
587                      "write (%s) %s\n", 
588                      rw_table[i].name, 
589                      info_verbose ? rw_table[i].desc : "");
590           else
591             {
592               if (lseek_offset != -1)
593                 fprintf (procfs_file ? procfs_file : stdout, 
594                          "write (<unknown>, %lud bytes at 0x%08lx) \n", 
595                          (unsigned long) len, (unsigned long) lseek_offset);
596               else
597                 fprintf (procfs_file ? procfs_file : stdout, 
598                          "write (<unknown>, %lud bytes) \n", 
599                          (unsigned long) len);
600             }
601           break;
602         }
603       }
604       if (procfs_file)
605         fflush (procfs_file);
606     }
607   errno = 0;
608   ret = write (fd, (void *) arg, len);
609   if (procfs_trace && ret != len)
610     {
611       fprintf (procfs_file ? procfs_file : stdout, 
612                "[write (%s) FAILED! (%s)]\n",
613                rw_table[i].name != NULL ? 
614                rw_table[i].name : "<unknown>", 
615                safe_strerror (errno));
616       if (procfs_file)
617         fflush (procfs_file);
618     }
619
620   lseek_offset = -1;
621   return ret;
622 }
623
624 off_t
625 lseek_with_trace (int fd, off_t offset, int whence, char *file, int line)
626 {
627   off_t ret;
628
629   prepare_to_trace ();
630   errno = 0;
631   ret = lseek (fd, offset, whence);
632   lseek_offset = ret;
633   if (procfs_trace && (ret == -1 || errno != 0))
634     {
635       fprintf (procfs_file ? procfs_file : stdout, 
636                "[lseek (0x%08lx) FAILED! (%s)]\n", 
637                (unsigned long) offset, safe_strerror (errno));
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 (char *filename, int mode, char *file, int line)
649 {
650   int ret;
651
652   prepare_to_trace ();
653   errno = 0;
654   ret = open (filename, mode);
655   if (procfs_trace)
656     {
657       if (info_verbose)
658         fprintf (procfs_file ? procfs_file : stdout, 
659                  "%s:%d -- ", file, line);
660
661       if (errno)
662         {
663           fprintf (procfs_file ? procfs_file : stdout, 
664                    "[open FAILED! (%s) line %d]\\n", 
665                    safe_strerror (errno), line);
666         }
667       else
668         {
669           fprintf (procfs_file ? procfs_file : stdout, 
670                    "%d = open (%s, ", ret, filename);
671           if (mode == O_RDONLY)
672             fprintf (procfs_file ? procfs_file : stdout, "O_RDONLY) %d\n",
673                      line);
674           else if (mode == O_WRONLY)
675             fprintf (procfs_file ? procfs_file : stdout, "O_WRONLY) %d\n",
676                      line);
677           else if (mode == O_RDWR)
678             fprintf (procfs_file ? procfs_file : stdout, "O_RDWR)   %d\n",
679                      line);
680         }
681       if (procfs_file)
682         fflush (procfs_file);
683     }
684
685   return ret;
686 }
687
688 int
689 close_with_trace (int fd, char *file, int line)
690 {
691   int ret;
692
693   prepare_to_trace ();
694   errno = 0;
695   ret = close (fd);
696   if (procfs_trace)
697     {
698       if (info_verbose)
699         fprintf (procfs_file ? procfs_file : stdout, 
700                  "%s:%d -- ", file, line);
701       if (errno)
702         fprintf (procfs_file ? procfs_file : stdout, 
703                  "[close FAILED! (%s)]\n", safe_strerror (errno));
704       else
705         fprintf (procfs_file ? procfs_file : stdout, 
706                  "%d = close (%d)\n", ret, fd);
707       if (procfs_file)
708         fflush (procfs_file);
709     }
710
711   return ret;
712 }
713
714 pid_t
715 wait_with_trace (int *wstat, char *file, int line)
716 {
717   int ret, lstat = 0;
718
719   prepare_to_trace ();
720   if (procfs_trace)
721     {
722       if (info_verbose)
723         fprintf (procfs_file ? procfs_file : stdout, 
724                  "%s:%d -- ", file, line);
725       fprintf (procfs_file ? procfs_file : stdout, 
726                "wait (line %d) ", line);
727       if (procfs_file)
728         fflush (procfs_file);
729     }
730   errno = 0;
731   ret = wait (&lstat);
732   if (procfs_trace)
733     {
734       if (errno)
735         fprintf (procfs_file ? procfs_file : stdout, 
736                  "[wait FAILED! (%s)]\n", safe_strerror (errno));
737       else
738         fprintf (procfs_file ? procfs_file : stdout, 
739                  "returned pid %d, status 0x%x\n", ret, lstat);
740       if (procfs_file)
741         fflush (procfs_file);
742     }
743   if (wstat)
744     *wstat = lstat;
745
746   return ret;
747 }
748
749 void
750 procfs_note (char *msg, char *file, int line)
751 {
752   prepare_to_trace ();
753   if (procfs_trace)
754     {
755       if (info_verbose)
756         fprintf (procfs_file ? procfs_file : stdout, 
757                  "%s:%d -- ", file, line);
758       fprintf (procfs_file ? procfs_file : stdout, msg);
759       if (procfs_file)
760         fflush (procfs_file);
761     }
762 }
763
764 void
765 proc_prettyfprint_status (long flags, int why, int what, int thread)
766 {
767   prepare_to_trace ();
768   if (procfs_trace)
769     {
770       if (thread)
771         fprintf (procfs_file ? procfs_file : stdout,
772                  "Thread %d: ", thread);
773
774       proc_prettyfprint_flags (procfs_file ? procfs_file : stdout, 
775                                flags, 0);
776
777       if (flags & (PR_STOPPED | PR_ISTOP))
778         proc_prettyfprint_why (procfs_file ? procfs_file : stdout, 
779                                why, what, 0);
780       if (procfs_file)
781         fflush (procfs_file);
782     }
783 }
784
785
786 void
787 _initialize_proc_api (void)
788 {
789   struct cmd_list_element *c;
790
791   c = add_set_cmd ("procfs-trace", no_class,
792                    var_boolean, (char *) &procfs_trace, 
793                    "Set tracing for /proc api calls.\n", &setlist);
794
795   add_show_from_set (c, &showlist);
796   set_cmd_sfunc (c, set_procfs_trace_cmd);
797   set_cmd_completer (c, filename_completer);
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   set_cmd_sfunc (c, set_procfs_file_cmd);
805 }
This page took 0.068128 seconds and 4 git commands to generate.