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