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