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