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