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