IRIX GCC fixes from 5.0 branch.
[binutils-gdb.git] / gdb / proc-api.c
1 /* Machine independent support for SVR4 /proc (process file system) for GDB.
2 Copyright 1999 Free Software Foundation, Inc.
3 Written by Michael Snyder at Cygnus Solutions.
4 Based on work by Fred Fish, Stu Grossman, Geoff Noer, and others.
5
6 This file is part of GDB.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software Foundation,
20 Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
21
22 /*
23 * Pretty-print trace of api calls to the /proc api
24 * (ioctl or read/write calls).
25 *
26 */
27
28 #include "defs.h"
29 #include "gdbcmd.h"
30
31 #if defined (NEW_PROC_API)
32 #define _STRUCTURED_PROC 1
33 #endif
34
35 #include <stdio.h>
36 #include <sys/types.h>
37 #include <sys/procfs.h>
38 #include <sys/proc.h> /* for struct proc */
39 #ifdef HAVE_SYS_USER_H
40 #include <sys/user.h> /* for struct user */
41 #endif
42 #include <fcntl.h> /* for O_RDWR etc. */
43 #include <sys/wait.h>
44
45 #include "proc-utils.h"
46
47 /* Much of the information used in the /proc interface, particularly for
48 printing status information, is kept as tables of structures of the
49 following form. These tables can be used to map numeric values to
50 their symbolic names and to a string that describes their specific use. */
51
52 struct trans {
53 long value; /* The numeric value */
54 char *name; /* The equivalent symbolic value */
55 char *desc; /* Short description of value */
56 };
57
58 static int procfs_trace = 0;
59 static FILE *procfs_file = NULL;
60 static char *procfs_filename = "procfs_trace";
61
62 static void
63 prepare_to_trace (void)
64 {
65 if (procfs_trace) /* if procfs tracing turned on */
66 if (procfs_file == NULL) /* if output file not yet open */
67 if (procfs_filename != NULL) /* if output filename known */
68 procfs_file = fopen (procfs_filename, "a"); /* open output file */
69 }
70
71 static void
72 set_procfs_trace_cmd (args, from_tty, c)
73 char *args;
74 int from_tty;
75 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 (args, from_tty, c)
85 char *args;
86 int from_tty;
87 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 (fd, opcode, ptr, file, line)
227 int fd;
228 long opcode;
229 void *ptr;
230 char *file;
231 int line;
232 {
233 int i, ret, arg1;
234
235 prepare_to_trace ();
236
237 if (procfs_trace)
238 {
239 for (i = 0; ioctl_table[i].name != NULL; i++)
240 if (ioctl_table[i].value == opcode)
241 break;
242
243 if (info_verbose)
244 fprintf (procfs_file ? procfs_file : stdout,
245 "%s:%d -- ", file, line);
246 switch (opcode) {
247 case PIOCSET:
248 arg1 = ptr ? *(long *) ptr : 0;
249 fprintf (procfs_file ? procfs_file : stdout,
250 "ioctl (PIOCSET, %s) %s\n",
251 arg1 == PR_FORK ? "PR_FORK" :
252 arg1 == PR_RLC ? "PR_RLC" :
253 #ifdef PR_ASYNC
254 arg1 == PR_ASYNC ? "PR_ASYNC" :
255 #endif
256 "<unknown flag>",
257 info_verbose ? ioctl_table[i].desc : "");
258 break;
259 case PIOCRESET:
260 arg1 = ptr ? *(long *) ptr : 0;
261 fprintf (procfs_file ? procfs_file : stdout,
262 "ioctl (PIOCRESET, %s) %s\n",
263 arg1 == PR_FORK ? "PR_FORK" :
264 arg1 == PR_RLC ? "PR_RLC" :
265 #ifdef PR_ASYNC
266 arg1 == PR_ASYNC ? "PR_ASYNC" :
267 #endif
268 "<unknown flag>",
269 info_verbose ? ioctl_table[i].desc : "");
270 break;
271 case PIOCSTRACE:
272 fprintf (procfs_file ? procfs_file : stdout,
273 "ioctl (PIOCSTRACE) ");
274 proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout,
275 (sigset_t *) ptr, 0);
276 break;
277 case PIOCSFAULT:
278 fprintf (procfs_file ? procfs_file : stdout,
279 "ioctl (%s) ",
280 opcode == PIOCSFAULT ? "PIOCSFAULT" : "PIOCGFAULT");
281 proc_prettyfprint_faultset (procfs_file ? procfs_file : stdout,
282 (fltset_t *) ptr, 0);
283 break;
284 case PIOCSENTRY:
285 fprintf (procfs_file ? procfs_file : stdout,
286 "ioctl (%s) ",
287 opcode == PIOCSENTRY ? "PIOCSENTRY" : "PIOCGENTRY");
288 proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout,
289 (sysset_t *) ptr, 0);
290 break;
291 case PIOCSEXIT:
292 fprintf (procfs_file ? procfs_file : stdout,
293 "ioctl (%s) ",
294 opcode == PIOCSEXIT ? "PIOCSEXIT" : "PIOCGEXIT");
295 proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout,
296 (sysset_t *) ptr, 0);
297 break;
298 case PIOCSHOLD:
299 fprintf (procfs_file ? procfs_file : stdout,
300 "ioctl (%s) ",
301 opcode == PIOCSHOLD ? "PIOCSHOLD" : "PIOCGHOLD");
302 proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout,
303 (sigset_t *) ptr, 0);
304 break;
305 case PIOCSSIG:
306 fprintf (procfs_file ? procfs_file : stdout,
307 "ioctl (PIOCSSIG) ");
308 proc_prettyfprint_signal (procfs_file ? procfs_file : stdout,
309 ptr ? ((siginfo_t *) ptr)->si_signo : 0,
310 0);
311 fprintf (procfs_file ? procfs_file : stdout, "\n");
312 break;
313 case PIOCRUN:
314 fprintf (procfs_file ? procfs_file : stdout,
315 "ioctl (PIOCRUN) ");
316
317 arg1 = ptr ? *(long *) ptr : 0;
318 if (arg1 & PRCSIG)
319 fprintf (procfs_file ? procfs_file : stdout, "clearSig ");
320 if (arg1 & PRCFAULT)
321 fprintf (procfs_file ? procfs_file : stdout, "clearFlt ");
322 if (arg1 & PRSTRACE)
323 fprintf (procfs_file ? procfs_file : stdout, "setTrace ");
324 if (arg1 & PRSHOLD)
325 fprintf (procfs_file ? procfs_file : stdout, "setHold ");
326 if (arg1 & PRSFAULT)
327 fprintf (procfs_file ? procfs_file : stdout, "setFlt ");
328 if (arg1 & PRSVADDR)
329 fprintf (procfs_file ? procfs_file : stdout, "setVaddr ");
330 if (arg1 & PRSTEP)
331 fprintf (procfs_file ? procfs_file : stdout, "step ");
332 if (arg1 & PRSABORT)
333 fprintf (procfs_file ? procfs_file : stdout, "syscallAbort ");
334 if (arg1 & PRSTOP)
335 fprintf (procfs_file ? procfs_file : stdout, "stopReq ");
336
337 fprintf (procfs_file ? procfs_file : stdout, "\n");
338 break;
339 case PIOCKILL:
340 fprintf (procfs_file ? procfs_file : stdout,
341 "ioctl (PIOCKILL) ");
342 proc_prettyfprint_signal (procfs_file ? procfs_file : stdout,
343 ptr ? *(long *) ptr : 0, 0);
344 fprintf (procfs_file ? procfs_file : stdout, "\n");
345 break;
346 #ifdef PIOCSSPCACT
347 case PIOCSSPCACT:
348 fprintf (procfs_file ? procfs_file : stdout,
349 "ioctl (PIOCSSPCACT) ");
350 arg1 = ptr ? *(long *) ptr : 0;
351 if (arg1 & PRFS_STOPFORK)
352 fprintf (procfs_file ? procfs_file : stdout, "stopFork ");
353 if (arg1 & PRFS_STOPEXEC)
354 fprintf (procfs_file ? procfs_file : stdout, "stopExec ");
355 if (arg1 & PRFS_STOPTERM)
356 fprintf (procfs_file ? procfs_file : stdout, "stopTerm ");
357 if (arg1 & PRFS_STOPTCR)
358 fprintf (procfs_file ? procfs_file : stdout, "stopThreadCreate ");
359 if (arg1 & PRFS_STOPTTERM)
360 fprintf (procfs_file ? procfs_file : stdout, "stopThreadTerm ");
361 if (arg1 & PRFS_KOLC)
362 fprintf (procfs_file ? procfs_file : stdout, "killOnLastClose ");
363 fprintf (procfs_file ? procfs_file : stdout, "\n");
364 break;
365 #endif /* PIOCSSPCACT */
366 default:
367 if (ioctl_table[i].name)
368 fprintf (procfs_file ? procfs_file : stdout,
369 "ioctl (%s) %s\n",
370 ioctl_table[i].name,
371 info_verbose ? ioctl_table[i].desc : "");
372 else
373 fprintf (procfs_file ? procfs_file : stdout,
374 "ioctl (<unknown %ld (0x%lx)) \n", opcode, opcode);
375 break;
376 }
377 if (procfs_file)
378 fflush (procfs_file);
379 }
380 errno = 0;
381 ret = ioctl (fd, opcode, ptr);
382 if (procfs_trace && ret < 0)
383 {
384 fprintf (procfs_file ? procfs_file : stdout,
385 "[ioctl (%s) FAILED! (%s)]\n",
386 ioctl_table[i].name != NULL ?
387 ioctl_table[i].name : "<unknown>",
388 safe_strerror (errno));
389 if (procfs_file)
390 fflush (procfs_file);
391 }
392
393 return ret;
394 }
395
396 #else /* NEW_PROC_API */
397
398 static struct trans rw_table[] = {
399 #ifdef PCAGENT /* solaris */
400 { PCAGENT, "PCAGENT", "create agent lwp with regs from argument" },
401 #endif
402 { PCCFAULT, "PCCFAULT", "clear current fault" },
403 #ifdef PCCSIG /* solaris */
404 { PCCSIG, "PCCSIG", "clear current signal" },
405 #endif
406 { PCDSTOP, "PCDSTOP", "post stop request" },
407 { PCKILL, "PCKILL", "post a signal" },
408 { PCNICE, "PCNICE", "set nice priority" },
409 #ifdef PCREAD /* solaris */
410 { PCREAD, "PCREAD", "read from the address space" },
411 { PCWRITE, "PCWRITE", "write to the address space" },
412 #endif
413 #ifdef PCRESET /* unixware */
414 { PCRESET, "PCRESET", "unset modes" },
415 #endif
416 { PCRUN, "PCRUN", "make process/lwp runnable" },
417 #ifdef PCSASRS /* solaris 2.7 only */
418 { PCSASRS, "PCSASRS", "set ancillary state registers" },
419 #endif
420 #ifdef PCSCRED /* solaris */
421 { PCSCRED, "PCSCRED", "set process credentials" },
422 #endif
423 { PCSENTRY, "PCSENTRY", "set traced syscall entry set" },
424 { PCSET, "PCSET", "set modes" },
425 { PCSEXIT, "PCSEXIT", "set traced syscall exit set" },
426 { PCSFAULT, "PCSFAULT", "set traced fault set" },
427 { PCSFPREG, "PCSFPREG", "set floating point registers" },
428 { PCSHOLD, "PCSHOLD", "set signal mask" },
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 { PCUNKILL, "PCUNKILL", "delete a pending signal" },
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
456 write_with_trace (fd, varg, len, file, line)
457 int fd;
458 void *varg;
459 size_t len;
460 char *file;
461 int line;
462 {
463 int i;
464 int ret;
465 long *arg = (long *) varg;
466
467 prepare_to_trace ();
468 if (procfs_trace)
469 {
470 long 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 case PCRESET:
495 #endif
496 fprintf (procfs_file ? procfs_file : stdout,
497 "write (PCRESET, %s) %s\n",
498 arg[1] == PR_FORK ? "PR_FORK" :
499 arg[1] == PR_RLC ? "PR_RLC" :
500 #ifdef PR_ASYNC
501 arg[1] == PR_ASYNC ? "PR_ASYNC" :
502 #endif
503 "<unknown flag>",
504 info_verbose ? rw_table[i].desc : "");
505 break;
506 case PCSTRACE:
507 fprintf (procfs_file ? procfs_file : stdout,
508 "write (PCSTRACE) ");
509 proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout,
510 (sigset_t *) &arg[1], 0);
511 break;
512 case PCSFAULT:
513 fprintf (procfs_file ? procfs_file : stdout,
514 "write (PCSFAULT) ");
515 proc_prettyfprint_faultset (procfs_file ? procfs_file : stdout,
516 (fltset_t *) &arg[1], 0);
517 break;
518 case PCSENTRY:
519 fprintf (procfs_file ? procfs_file : stdout,
520 "write (PCSENTRY) ");
521 proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout,
522 (sysset_t *) &arg[1], 0);
523 break;
524 case PCSEXIT:
525 fprintf (procfs_file ? procfs_file : stdout,
526 "write (PCSEXIT) ");
527 proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout,
528 (sysset_t *) &arg[1], 0);
529 break;
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 case PCSSIG:
537 fprintf (procfs_file ? procfs_file : stdout,
538 "write (PCSSIG) ");
539 proc_prettyfprint_signal (procfs_file ? procfs_file : stdout,
540 arg[1] ? ((siginfo_t *) &arg[1])->si_signo
541 : 0,
542 0);
543 fprintf (procfs_file ? procfs_file : stdout, "\n");
544 break;
545 case PCRUN:
546 fprintf (procfs_file ? procfs_file : stdout,
547 "write (PCRUN) ");
548 if (arg[1] & PRCSIG)
549 fprintf (procfs_file ? procfs_file : stdout, "clearSig ");
550 if (arg[1] & PRCFAULT)
551 fprintf (procfs_file ? procfs_file : stdout, "clearFlt ");
552 if (arg[1] & PRSTEP)
553 fprintf (procfs_file ? procfs_file : stdout, "step ");
554 if (arg[1] & PRSABORT)
555 fprintf (procfs_file ? procfs_file : stdout, "syscallAbort ");
556 if (arg[1] & PRSTOP)
557 fprintf (procfs_file ? procfs_file : stdout, "stopReq ");
558
559 fprintf (procfs_file ? procfs_file : stdout, "\n");
560 break;
561 case PCKILL:
562 fprintf (procfs_file ? procfs_file : stdout,
563 "write (PCKILL) ");
564 proc_prettyfprint_signal (procfs_file ? procfs_file : stdout,
565 arg[1], 0);
566 fprintf (procfs_file ? procfs_file : stdout, "\n");
567 break;
568 default:
569 {
570 static unsigned char break_insn[] = BREAKPOINT;
571
572 if (len == sizeof (break_insn) &&
573 memcmp (arg, &break_insn, len) == 0)
574 fprintf (procfs_file ? procfs_file : stdout,
575 "write (<breakpoint at 0x%08lx>) \n",
576 (unsigned long) lseek_offset);
577 else if (rw_table[i].name)
578 fprintf (procfs_file ? procfs_file : stdout,
579 "write (%s) %s\n",
580 rw_table[i].name,
581 info_verbose ? rw_table[i].desc : "");
582 else
583 {
584 if (lseek_offset != -1)
585 fprintf (procfs_file ? procfs_file : stdout,
586 "write (<unknown>, %lud bytes at 0x%08lx) \n",
587 (unsigned long) len, (unsigned long) lseek_offset);
588 else
589 fprintf (procfs_file ? procfs_file : stdout,
590 "write (<unknown>, %lud bytes) \n",
591 (unsigned long) len);
592 }
593 break;
594 }
595 }
596 if (procfs_file)
597 fflush (procfs_file);
598 }
599 errno = 0;
600 ret = write (fd, (void *) arg, len);
601 if (procfs_trace && ret != len)
602 {
603 fprintf (procfs_file ? procfs_file : stdout,
604 "[write (%s) FAILED! (%s)]\n",
605 rw_table[i].name != NULL ?
606 rw_table[i].name : "<unknown>",
607 safe_strerror (errno));
608 if (procfs_file)
609 fflush (procfs_file);
610 }
611
612 lseek_offset = -1;
613 return ret;
614 }
615
616 off_t
617 lseek_with_trace (fd, offset, whence, file, line)
618 int fd;
619 off_t offset;
620 int whence;
621 char *file;
622 int line;
623 {
624 off_t ret;
625
626 prepare_to_trace ();
627 errno = 0;
628 ret = lseek (fd, offset, whence);
629 lseek_offset = ret;
630 if (procfs_trace && (ret == -1 || errno != 0))
631 {
632 fprintf (procfs_file ? procfs_file : stdout,
633 "[lseek (0x%08lx) FAILED! (%s)]\n",
634 (unsigned long) offset, safe_strerror (errno));
635 if (procfs_file)
636 fflush (procfs_file);
637 }
638
639 return ret;
640 }
641
642 #endif /* NEW_PROC_API */
643
644 int
645 open_with_trace (filename, mode, file, line)
646 char *filename;
647 int mode;
648 char *file;
649 int line;
650 {
651 int ret;
652
653 prepare_to_trace ();
654 errno = 0;
655 ret = open (filename, mode);
656 if (procfs_trace)
657 {
658 if (info_verbose)
659 fprintf (procfs_file ? procfs_file : stdout,
660 "%s:%d -- ", file, line);
661
662 if (errno)
663 {
664 fprintf (procfs_file ? procfs_file : stdout,
665 "[open FAILED! (%s) line %d]\\n",
666 safe_strerror (errno), line);
667 }
668 else
669 {
670 fprintf (procfs_file ? procfs_file : stdout,
671 "%d = open (%s, ", ret, filename);
672 if (mode == O_RDONLY)
673 fprintf (procfs_file ? procfs_file : stdout, "O_RDONLY) %d\n",
674 line);
675 else if (mode == O_WRONLY)
676 fprintf (procfs_file ? procfs_file : stdout, "O_WRONLY) %d\n",
677 line);
678 else if (mode == O_RDWR)
679 fprintf (procfs_file ? procfs_file : stdout, "O_RDWR) %d\n",
680 line);
681 }
682 if (procfs_file)
683 fflush (procfs_file);
684 }
685
686 return ret;
687 }
688
689 int
690 close_with_trace (fd, file, line)
691 int fd;
692 char *file;
693 int line;
694 {
695 int ret;
696
697 prepare_to_trace ();
698 errno = 0;
699 ret = close (fd);
700 if (procfs_trace)
701 {
702 if (info_verbose)
703 fprintf (procfs_file ? procfs_file : stdout,
704 "%s:%d -- ", file, line);
705 if (errno)
706 fprintf (procfs_file ? procfs_file : stdout,
707 "[close FAILED! (%s)]\n", safe_strerror (errno));
708 else
709 fprintf (procfs_file ? procfs_file : stdout,
710 "%d = close (%d)\n", ret, fd);
711 if (procfs_file)
712 fflush (procfs_file);
713 }
714
715 return ret;
716 }
717
718 pid_t
719 wait_with_trace (wstat, file, line)
720 int *wstat;
721 char *file;
722 int line;
723 {
724 int ret, lstat = 0;
725
726 prepare_to_trace ();
727 if (procfs_trace)
728 {
729 if (info_verbose)
730 fprintf (procfs_file ? procfs_file : stdout,
731 "%s:%d -- ", file, line);
732 fprintf (procfs_file ? procfs_file : stdout,
733 "wait (line %d) ", line);
734 if (procfs_file)
735 fflush (procfs_file);
736 }
737 errno = 0;
738 ret = wait (&lstat);
739 if (procfs_trace)
740 {
741 if (errno)
742 fprintf (procfs_file ? procfs_file : stdout,
743 "[wait FAILED! (%s)]\n", safe_strerror (errno));
744 else
745 fprintf (procfs_file ? procfs_file : stdout,
746 "returned pid %d, status 0x%x\n", ret, lstat);
747 if (procfs_file)
748 fflush (procfs_file);
749 }
750 if (wstat)
751 *wstat = lstat;
752
753 return ret;
754 }
755
756 void
757 procfs_note (msg, file, line)
758 char *msg;
759 char *file;
760 int line;
761 {
762 prepare_to_trace ();
763 if (procfs_trace)
764 {
765 if (info_verbose)
766 fprintf (procfs_file ? procfs_file : stdout,
767 "%s:%d -- ", file, line);
768 fprintf (procfs_file ? procfs_file : stdout, msg);
769 if (procfs_file)
770 fflush (procfs_file);
771 }
772 }
773
774 void
775 proc_prettyfprint_status (flags, why, what, thread)
776 long flags;
777 int why;
778 int what;
779 int thread;
780 {
781 prepare_to_trace ();
782 if (procfs_trace)
783 {
784 if (thread)
785 fprintf (procfs_file ? procfs_file : stdout,
786 "Thread %d: ", thread);
787
788 proc_prettyfprint_flags (procfs_file ? procfs_file : stdout,
789 flags, 0);
790
791 if (flags & (PR_STOPPED | PR_ISTOP))
792 proc_prettyfprint_why (procfs_file ? procfs_file : stdout,
793 why, what, 0);
794 if (procfs_file)
795 fflush (procfs_file);
796 }
797 }
798
799
800 void
801 _initialize_proc_api ()
802 {
803 struct cmd_list_element *c;
804
805 c = add_set_cmd ("procfs-trace", no_class,
806 var_boolean, (char *) &procfs_trace,
807 "Set tracing for /proc api calls.\n", &setlist);
808
809 add_show_from_set (c, &showlist);
810 c->function.sfunc = set_procfs_trace_cmd;
811
812 c = add_set_cmd ("procfs-file", no_class, var_filename,
813 (char *) &procfs_filename,
814 "Set filename for /proc tracefile.\n", &setlist);
815
816 add_show_from_set (c, &showlist);
817 c->function.sfunc = set_procfs_file_cmd;
818 }