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