1 /* Machine independent support for Solaris /proc (process file system) for GDB.
3 Copyright (C) 1999-2022 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
29 #include "completer.h"
31 #include <sys/types.h>
32 #include <sys/procfs.h>
33 #include <sys/proc.h> /* for struct proc */
34 #include <sys/user.h> /* for struct user */
35 #include <fcntl.h> /* for O_RDWR etc. */
36 #include "gdbsupport/gdb_wait.h"
38 #include "proc-utils.h"
40 /* Much of the information used in the /proc interface, particularly for
41 printing status information, is kept as tables of structures of the
42 following form. These tables can be used to map numeric values to
43 their symbolic names and to a string that describes their specific use. */
46 long value
; /* The numeric value */
47 const char *name
; /* The equivalent symbolic value */
48 const char *desc
; /* Short description of value */
51 static bool procfs_trace
= false;
52 static FILE *procfs_file
= NULL
;
53 static std::string procfs_filename
= "procfs_trace";
56 prepare_to_trace (void)
58 if (procfs_trace
) /* if procfs tracing turned on */
59 if (procfs_file
== NULL
) /* if output file not yet open */
60 procfs_file
= fopen (procfs_filename
.c_str (), "a"); /* open output file */
64 set_procfs_trace_cmd (const char *args
,
65 int from_tty
, struct cmd_list_element
*c
)
67 #if 0 /* not sure what I might actually need to do here, if anything */
74 set_procfs_file_cmd (const char *args
,
75 int from_tty
, struct cmd_list_element
*c
)
77 /* Just changed the filename for procfs tracing.
78 If a file was already open, close it. */
84 static struct trans rw_table
[] = {
85 { PCAGENT
, "PCAGENT", "create agent lwp with regs from argument" },
86 { PCCFAULT
, "PCCFAULT", "clear current fault" },
87 { PCCSIG
, "PCCSIG", "clear current signal" },
88 { PCDSTOP
, "PCDSTOP", "post stop request" },
89 { PCKILL
, "PCKILL", "post a signal" },
90 { PCNICE
, "PCNICE", "set nice priority" },
91 { PCREAD
, "PCREAD", "read from the address space" },
92 { PCWRITE
, "PCWRITE", "write to the address space" },
93 { PCRUN
, "PCRUN", "make process/lwp runnable" },
94 { PCSASRS
, "PCSASRS", "set ancillary state registers" },
95 { PCSCRED
, "PCSCRED", "set process credentials" },
96 { PCSENTRY
, "PCSENTRY", "set traced syscall entry set" },
97 { PCSET
, "PCSET", "set modes" },
98 { PCSEXIT
, "PCSEXIT", "set traced syscall exit set" },
99 { PCSFAULT
, "PCSFAULT", "set traced fault set" },
100 { PCSFPREG
, "PCSFPREG", "set floating point registers" },
101 { PCSHOLD
, "PCSHOLD", "set signal mask" },
102 { PCSREG
, "PCSREG", "set general registers" },
103 { PCSSIG
, "PCSSIG", "set current signal" },
104 { PCSTOP
, "PCSTOP", "post stop request and wait" },
105 { PCSTRACE
, "PCSTRACE", "set traced signal set" },
106 { PCSVADDR
, "PCSVADDR", "set pc virtual address" },
107 { PCSXREG
, "PCSXREG", "set extra registers" },
108 { PCTWSTOP
, "PCTWSTOP", "wait for stop, with timeout arg" },
109 { PCUNKILL
, "PCUNKILL", "delete a pending signal" },
110 { PCUNSET
, "PCUNSET", "unset modes" },
111 { PCWATCH
, "PCWATCH", "set/unset watched memory area" },
112 { PCWSTOP
, "PCWSTOP", "wait for process/lwp to stop, no timeout" },
116 static off_t lseek_offset
;
119 write_with_trace (int fd
, void *varg
, size_t len
, char *file
, int line
)
121 int i
= ARRAY_SIZE (rw_table
) - 1;
123 procfs_ctl_t
*arg
= (procfs_ctl_t
*) varg
;
128 procfs_ctl_t opcode
= arg
[0];
129 for (i
= 0; rw_table
[i
].name
!= NULL
; i
++)
130 if (rw_table
[i
].value
== opcode
)
134 fprintf (procfs_file
? procfs_file
: stdout
,
135 "%s:%d -- ", file
, line
);
138 fprintf (procfs_file
? procfs_file
: stdout
,
139 "write (PCSET, %s) %s\n",
140 arg
[1] == PR_FORK
? "PR_FORK" :
141 arg
[1] == PR_RLC
? "PR_RLC" :
142 arg
[1] == PR_ASYNC
? "PR_ASYNC" :
144 info_verbose
? rw_table
[i
].desc
: "");
147 fprintf (procfs_file
? procfs_file
: stdout
,
148 "write (PCRESET, %s) %s\n",
149 arg
[1] == PR_FORK
? "PR_FORK" :
150 arg
[1] == PR_RLC
? "PR_RLC" :
151 arg
[1] == PR_ASYNC
? "PR_ASYNC" :
153 info_verbose
? rw_table
[i
].desc
: "");
156 fprintf (procfs_file
? procfs_file
: stdout
,
157 "write (PCSTRACE) ");
158 proc_prettyfprint_signalset (procfs_file
? procfs_file
: stdout
,
159 (sigset_t
*) &arg
[1], 0);
162 fprintf (procfs_file
? procfs_file
: stdout
,
163 "write (PCSFAULT) ");
164 proc_prettyfprint_faultset (procfs_file
? procfs_file
: stdout
,
165 (fltset_t
*) &arg
[1], 0);
168 fprintf (procfs_file
? procfs_file
: stdout
,
169 "write (PCSENTRY) ");
170 proc_prettyfprint_syscalls (procfs_file
? procfs_file
: stdout
,
171 (sysset_t
*) &arg
[1], 0);
174 fprintf (procfs_file
? procfs_file
: stdout
,
176 proc_prettyfprint_syscalls (procfs_file
? procfs_file
: stdout
,
177 (sysset_t
*) &arg
[1], 0);
180 fprintf (procfs_file
? procfs_file
: stdout
,
182 proc_prettyfprint_signalset (procfs_file
? procfs_file
: stdout
,
183 (sigset_t
*) &arg
[1], 0);
186 fprintf (procfs_file
? procfs_file
: stdout
,
188 proc_prettyfprint_signal (procfs_file
? procfs_file
: stdout
,
189 arg
[1] ? ((siginfo_t
*) &arg
[1])->si_signo
192 fprintf (procfs_file
? procfs_file
: stdout
, "\n");
195 fprintf (procfs_file
? procfs_file
: stdout
,
198 fprintf (procfs_file
? procfs_file
: stdout
, "clearSig ");
199 if (arg
[1] & PRCFAULT
)
200 fprintf (procfs_file
? procfs_file
: stdout
, "clearFlt ");
202 fprintf (procfs_file
? procfs_file
: stdout
, "step ");
203 if (arg
[1] & PRSABORT
)
204 fprintf (procfs_file
? procfs_file
: stdout
, "syscallAbort ");
206 fprintf (procfs_file
? procfs_file
: stdout
, "stopReq ");
208 fprintf (procfs_file
? procfs_file
: stdout
, "\n");
211 fprintf (procfs_file
? procfs_file
: stdout
,
213 proc_prettyfprint_signal (procfs_file
? procfs_file
: stdout
,
215 fprintf (procfs_file
? procfs_file
: stdout
, "\n");
219 if (rw_table
[i
].name
)
220 fprintf (procfs_file
? procfs_file
: stdout
,
223 info_verbose
? rw_table
[i
].desc
: "");
226 if (lseek_offset
!= -1)
227 fprintf (procfs_file
? procfs_file
: stdout
,
228 "write (<unknown>, %lud bytes at 0x%08lx) \n",
229 (unsigned long) len
, (unsigned long) lseek_offset
);
231 fprintf (procfs_file
? procfs_file
: stdout
,
232 "write (<unknown>, %lud bytes) \n",
233 (unsigned long) len
);
239 fflush (procfs_file
);
242 ret
= write (fd
, (void *) arg
, len
);
243 if (procfs_trace
&& ret
!= len
)
245 fprintf (procfs_file
? procfs_file
: stdout
,
246 "[write (%s) FAILED! (%s)]\n",
247 rw_table
[i
].name
!= NULL
?
248 rw_table
[i
].name
: "<unknown>",
249 safe_strerror (errno
));
251 fflush (procfs_file
);
259 lseek_with_trace (int fd
, off_t offset
, int whence
, char *file
, int line
)
265 ret
= lseek (fd
, offset
, whence
);
267 if (procfs_trace
&& (ret
== -1 || errno
!= 0))
269 fprintf (procfs_file
? procfs_file
: stdout
,
270 "[lseek (0x%08lx) FAILED! (%s)]\n",
271 (unsigned long) offset
, safe_strerror (errno
));
273 fflush (procfs_file
);
280 open_with_trace (char *filename
, int mode
, char *file
, int line
)
286 ret
= open (filename
, mode
);
290 fprintf (procfs_file
? procfs_file
: stdout
,
291 "%s:%d -- ", file
, line
);
295 fprintf (procfs_file
? procfs_file
: stdout
,
296 "[open FAILED! (%s) line %d]\\n",
297 safe_strerror (errno
), line
);
301 fprintf (procfs_file
? procfs_file
: stdout
,
302 "%d = open (%s, ", ret
, filename
);
303 if (mode
== O_RDONLY
)
304 fprintf (procfs_file
? procfs_file
: stdout
, "O_RDONLY) %d\n",
306 else if (mode
== O_WRONLY
)
307 fprintf (procfs_file
? procfs_file
: stdout
, "O_WRONLY) %d\n",
309 else if (mode
== O_RDWR
)
310 fprintf (procfs_file
? procfs_file
: stdout
, "O_RDWR) %d\n",
314 fflush (procfs_file
);
321 close_with_trace (int fd
, char *file
, int line
)
331 fprintf (procfs_file
? procfs_file
: stdout
,
332 "%s:%d -- ", file
, line
);
334 fprintf (procfs_file
? procfs_file
: stdout
,
335 "[close FAILED! (%s)]\n", safe_strerror (errno
));
337 fprintf (procfs_file
? procfs_file
: stdout
,
338 "%d = close (%d)\n", ret
, fd
);
340 fflush (procfs_file
);
347 wait_with_trace (int *wstat
, char *file
, int line
)
355 fprintf (procfs_file
? procfs_file
: stdout
,
356 "%s:%d -- ", file
, line
);
357 fprintf (procfs_file
? procfs_file
: stdout
,
358 "wait (line %d) ", line
);
360 fflush (procfs_file
);
367 fprintf (procfs_file
? procfs_file
: stdout
,
368 "[wait FAILED! (%s)]\n", safe_strerror (errno
));
370 fprintf (procfs_file
? procfs_file
: stdout
,
371 "returned pid %d, status 0x%x\n", ret
, lstat
);
373 fflush (procfs_file
);
382 procfs_note (const char *msg
, const char *file
, int line
)
388 fprintf (procfs_file
? procfs_file
: stdout
,
389 "%s:%d -- ", file
, line
);
390 fprintf (procfs_file
? procfs_file
: stdout
, "%s", msg
);
392 fflush (procfs_file
);
397 proc_prettyfprint_status (long flags
, int why
, int what
, int thread
)
403 fprintf (procfs_file
? procfs_file
: stdout
,
404 "Thread %d: ", thread
);
406 proc_prettyfprint_flags (procfs_file
? procfs_file
: stdout
,
409 if (flags
& (PR_STOPPED
| PR_ISTOP
))
410 proc_prettyfprint_why (procfs_file
? procfs_file
: stdout
,
413 fflush (procfs_file
);
417 void _initialize_proc_api ();
419 _initialize_proc_api ()
421 add_setshow_boolean_cmd ("procfs-trace", no_class
, &procfs_trace
, _("\
422 Set tracing for /proc api calls."), _("\
423 Show tracing for /proc api calls."), NULL
,
424 set_procfs_trace_cmd
,
425 NULL
, /* FIXME: i18n: */
426 &setlist
, &showlist
);
428 add_setshow_filename_cmd ("procfs-file", no_class
, &procfs_filename
, _("\
429 Set filename for /proc tracefile."), _("\
430 Show filename for /proc tracefile."), NULL
,
432 NULL
, /* FIXME: i18n: */
433 &setlist
, &showlist
);