1 /* Machine independent support for Solaris /proc (process file system) for GDB.
3 Copyright (C) 1999-2024 Free Software Foundation, Inc.
5 Written by Michael Snyder at Cygnus Solutions.
6 Based on work by Fred Fish, Stu Grossman, Geoff Noer, and others.
8 This file is part of GDB.
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 3 of the License, or
13 (at your option) any later version.
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.
20 You should have received a copy of the GNU General Public License
21 along with this program. If not, see <http://www.gnu.org/licenses/>. */
24 * Pretty-print trace of api calls to the /proc api
27 #include "cli/cli-cmds.h"
28 #include "completer.h"
30 #include <sys/types.h>
31 #include <sys/procfs.h>
35 #include "gdbsupport/gdb_wait.h"
37 #include "proc-utils.h"
39 /* Much of the information used in the /proc interface, particularly for
40 printing status information, is kept as tables of structures of the
41 following form. These tables can be used to map numeric values to
42 their symbolic names and to a string that describes their specific use. */
45 long value
; /* The numeric value */
46 const char *name
; /* The equivalent symbolic value */
47 const char *desc
; /* Short description of value */
50 static bool procfs_trace
= false;
51 static FILE *procfs_file
= NULL
;
52 static std::string procfs_filename
= "procfs_trace";
55 prepare_to_trace (void)
57 if (procfs_trace
) /* if procfs tracing turned on */
58 if (procfs_file
== NULL
) /* if output file not yet open */
59 procfs_file
= fopen (procfs_filename
.c_str (), "a"); /* open output file */
63 set_procfs_trace_cmd (const char *args
,
64 int from_tty
, struct cmd_list_element
*c
)
66 #if 0 /* not sure what I might actually need to do here, if anything */
73 set_procfs_file_cmd (const char *args
,
74 int from_tty
, struct cmd_list_element
*c
)
76 /* Just changed the filename for procfs tracing.
77 If a file was already open, close it. */
83 static struct trans rw_table
[] = {
84 { PCAGENT
, "PCAGENT", "create agent lwp with regs from argument" },
85 { PCCFAULT
, "PCCFAULT", "clear current fault" },
86 { PCCSIG
, "PCCSIG", "clear current signal" },
87 { PCDSTOP
, "PCDSTOP", "post stop request" },
88 { PCKILL
, "PCKILL", "post a signal" },
89 { PCNICE
, "PCNICE", "set nice priority" },
90 { PCREAD
, "PCREAD", "read from the address space" },
91 { PCWRITE
, "PCWRITE", "write to the address space" },
92 { PCRUN
, "PCRUN", "make process/lwp runnable" },
93 { PCSASRS
, "PCSASRS", "set ancillary state registers" },
94 { PCSCRED
, "PCSCRED", "set process credentials" },
95 { PCSENTRY
, "PCSENTRY", "set traced syscall entry set" },
96 { PCSET
, "PCSET", "set modes" },
97 { PCSEXIT
, "PCSEXIT", "set traced syscall exit set" },
98 { PCSFAULT
, "PCSFAULT", "set traced fault set" },
99 { PCSFPREG
, "PCSFPREG", "set floating point registers" },
100 { PCSHOLD
, "PCSHOLD", "set signal mask" },
101 { PCSREG
, "PCSREG", "set general registers" },
102 { PCSSIG
, "PCSSIG", "set current signal" },
103 { PCSTOP
, "PCSTOP", "post stop request and wait" },
104 { PCSTRACE
, "PCSTRACE", "set traced signal set" },
105 { PCSVADDR
, "PCSVADDR", "set pc virtual address" },
106 { PCSXREG
, "PCSXREG", "set extra registers" },
107 { PCTWSTOP
, "PCTWSTOP", "wait for stop, with timeout arg" },
108 { PCUNKILL
, "PCUNKILL", "delete a pending signal" },
109 { PCUNSET
, "PCUNSET", "unset modes" },
110 { PCWATCH
, "PCWATCH", "set/unset watched memory area" },
111 { PCWSTOP
, "PCWSTOP", "wait for process/lwp to stop, no timeout" },
115 static off_t lseek_offset
;
118 write_with_trace (int fd
, void *varg
, size_t len
, char *file
, int line
)
120 int i
= ARRAY_SIZE (rw_table
) - 1;
122 procfs_ctl_t
*arg
= (procfs_ctl_t
*) varg
;
127 procfs_ctl_t opcode
= arg
[0];
128 for (i
= 0; rw_table
[i
].name
!= NULL
; i
++)
129 if (rw_table
[i
].value
== opcode
)
133 fprintf (procfs_file
? procfs_file
: stdout
,
134 "%s:%d -- ", file
, line
);
137 fprintf (procfs_file
? procfs_file
: stdout
,
138 "write (PCSET, %s) %s\n",
139 arg
[1] == PR_FORK
? "PR_FORK" :
140 arg
[1] == PR_RLC
? "PR_RLC" :
141 arg
[1] == PR_ASYNC
? "PR_ASYNC" :
143 info_verbose
? rw_table
[i
].desc
: "");
146 fprintf (procfs_file
? procfs_file
: stdout
,
147 "write (PCRESET, %s) %s\n",
148 arg
[1] == PR_FORK
? "PR_FORK" :
149 arg
[1] == PR_RLC
? "PR_RLC" :
150 arg
[1] == PR_ASYNC
? "PR_ASYNC" :
152 info_verbose
? rw_table
[i
].desc
: "");
155 fprintf (procfs_file
? procfs_file
: stdout
,
156 "write (PCSTRACE) ");
157 proc_prettyfprint_signalset (procfs_file
? procfs_file
: stdout
,
158 (sigset_t
*) &arg
[1], 0);
161 fprintf (procfs_file
? procfs_file
: stdout
,
162 "write (PCSFAULT) ");
163 proc_prettyfprint_faultset (procfs_file
? procfs_file
: stdout
,
164 (fltset_t
*) &arg
[1], 0);
167 fprintf (procfs_file
? procfs_file
: stdout
,
168 "write (PCSENTRY) ");
169 proc_prettyfprint_syscalls (procfs_file
? procfs_file
: stdout
,
170 (sysset_t
*) &arg
[1], 0);
173 fprintf (procfs_file
? procfs_file
: stdout
,
175 proc_prettyfprint_syscalls (procfs_file
? procfs_file
: stdout
,
176 (sysset_t
*) &arg
[1], 0);
179 fprintf (procfs_file
? procfs_file
: stdout
,
181 proc_prettyfprint_signalset (procfs_file
? procfs_file
: stdout
,
182 (sigset_t
*) &arg
[1], 0);
185 fprintf (procfs_file
? procfs_file
: stdout
,
187 proc_prettyfprint_signal (procfs_file
? procfs_file
: stdout
,
188 arg
[1] ? ((siginfo_t
*) &arg
[1])->si_signo
191 fprintf (procfs_file
? procfs_file
: stdout
, "\n");
194 fprintf (procfs_file
? procfs_file
: stdout
,
197 fprintf (procfs_file
? procfs_file
: stdout
, "clearSig ");
198 if (arg
[1] & PRCFAULT
)
199 fprintf (procfs_file
? procfs_file
: stdout
, "clearFlt ");
201 fprintf (procfs_file
? procfs_file
: stdout
, "step ");
202 if (arg
[1] & PRSABORT
)
203 fprintf (procfs_file
? procfs_file
: stdout
, "syscallAbort ");
205 fprintf (procfs_file
? procfs_file
: stdout
, "stopReq ");
207 fprintf (procfs_file
? procfs_file
: stdout
, "\n");
210 fprintf (procfs_file
? procfs_file
: stdout
,
212 proc_prettyfprint_signal (procfs_file
? procfs_file
: stdout
,
214 fprintf (procfs_file
? procfs_file
: stdout
, "\n");
218 if (rw_table
[i
].name
)
219 fprintf (procfs_file
? procfs_file
: stdout
,
222 info_verbose
? rw_table
[i
].desc
: "");
225 if (lseek_offset
!= -1)
226 fprintf (procfs_file
? procfs_file
: stdout
,
227 "write (<unknown>, %lud bytes at 0x%08lx) \n",
228 (unsigned long) len
, (unsigned long) lseek_offset
);
230 fprintf (procfs_file
? procfs_file
: stdout
,
231 "write (<unknown>, %lud bytes) \n",
232 (unsigned long) len
);
238 fflush (procfs_file
);
241 ret
= write (fd
, (void *) arg
, len
);
242 if (procfs_trace
&& ret
!= len
)
244 fprintf (procfs_file
? procfs_file
: stdout
,
245 "[write (%s) FAILED! (%s)]\n",
246 rw_table
[i
].name
!= NULL
?
247 rw_table
[i
].name
: "<unknown>",
248 safe_strerror (errno
));
250 fflush (procfs_file
);
258 lseek_with_trace (int fd
, off_t offset
, int whence
, char *file
, int line
)
264 ret
= lseek (fd
, offset
, whence
);
266 if (procfs_trace
&& (ret
== -1 || errno
!= 0))
268 fprintf (procfs_file
? procfs_file
: stdout
,
269 "[lseek (0x%08lx) FAILED! (%s)]\n",
270 (unsigned long) offset
, safe_strerror (errno
));
272 fflush (procfs_file
);
279 open_with_trace (char *filename
, int mode
, char *file
, int line
)
285 ret
= open (filename
, mode
);
289 fprintf (procfs_file
? procfs_file
: stdout
,
290 "%s:%d -- ", file
, line
);
294 fprintf (procfs_file
? procfs_file
: stdout
,
295 "[open FAILED! (%s) line %d]\\n",
296 safe_strerror (errno
), line
);
300 fprintf (procfs_file
? procfs_file
: stdout
,
301 "%d = open (%s, ", ret
, filename
);
302 if (mode
== O_RDONLY
)
303 fprintf (procfs_file
? procfs_file
: stdout
, "O_RDONLY) %d\n",
305 else if (mode
== O_WRONLY
)
306 fprintf (procfs_file
? procfs_file
: stdout
, "O_WRONLY) %d\n",
308 else if (mode
== O_RDWR
)
309 fprintf (procfs_file
? procfs_file
: stdout
, "O_RDWR) %d\n",
313 fflush (procfs_file
);
320 close_with_trace (int fd
, char *file
, int line
)
330 fprintf (procfs_file
? procfs_file
: stdout
,
331 "%s:%d -- ", file
, line
);
333 fprintf (procfs_file
? procfs_file
: stdout
,
334 "[close FAILED! (%s)]\n", safe_strerror (errno
));
336 fprintf (procfs_file
? procfs_file
: stdout
,
337 "%d = close (%d)\n", ret
, fd
);
339 fflush (procfs_file
);
346 wait_with_trace (int *wstat
, char *file
, int line
)
354 fprintf (procfs_file
? procfs_file
: stdout
,
355 "%s:%d -- ", file
, line
);
356 fprintf (procfs_file
? procfs_file
: stdout
,
357 "wait (line %d) ", line
);
359 fflush (procfs_file
);
366 fprintf (procfs_file
? procfs_file
: stdout
,
367 "[wait FAILED! (%s)]\n", safe_strerror (errno
));
369 fprintf (procfs_file
? procfs_file
: stdout
,
370 "returned pid %d, status 0x%x\n", ret
, lstat
);
372 fflush (procfs_file
);
381 procfs_note (const char *msg
, const char *file
, int line
)
387 fprintf (procfs_file
? procfs_file
: stdout
,
388 "%s:%d -- ", file
, line
);
389 fprintf (procfs_file
? procfs_file
: stdout
, "%s", msg
);
391 fflush (procfs_file
);
396 proc_prettyfprint_status (long flags
, int why
, int what
, int thread
)
402 fprintf (procfs_file
? procfs_file
: stdout
,
403 "Thread %d: ", thread
);
405 proc_prettyfprint_flags (procfs_file
? procfs_file
: stdout
,
408 if (flags
& (PR_STOPPED
| PR_ISTOP
))
409 proc_prettyfprint_why (procfs_file
? procfs_file
: stdout
,
412 fflush (procfs_file
);
416 void _initialize_proc_api ();
418 _initialize_proc_api ()
420 add_setshow_boolean_cmd ("procfs-trace", no_class
, &procfs_trace
, _("\
421 Set tracing for /proc api calls."), _("\
422 Show tracing for /proc api calls."), NULL
,
423 set_procfs_trace_cmd
,
424 NULL
, /* FIXME: i18n: */
425 &setlist
, &showlist
);
427 add_setshow_filename_cmd ("procfs-file", no_class
, &procfs_filename
, _("\
428 Set filename for /proc tracefile."), _("\
429 Show filename for /proc tracefile."), NULL
,
431 NULL
, /* FIXME: i18n: */
432 &setlist
, &showlist
);