GDB (xrefs)
Loading...
Searching...
No Matches
/tmp/gdb-13.1/gdb/proc-api.c
Go to the documentation of this file.
1/* Machine independent support for Solaris /proc (process file system) for GDB.
2
3 Copyright (C) 1999-2023 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 3 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, see <http://www.gnu.org/licenses/>. */
22
23/*
24 * Pretty-print trace of api calls to the /proc api
25 */
26
27#include "defs.h"
28#include "gdbcmd.h"
29#include "completer.h"
30
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"
37
38#include "proc-utils.h"
39
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. */
44
45struct trans {
46 long value; /* The numeric value */
47 const char *name; /* The equivalent symbolic value */
48 const char *desc; /* Short description of value */
49};
50
51static bool procfs_trace = false;
52static FILE *procfs_file = NULL;
53static std::string procfs_filename = "procfs_trace";
54
55static void
57{
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 */
61}
62
63static void
64set_procfs_trace_cmd (const char *args,
65 int from_tty, struct cmd_list_element *c)
66{
67#if 0 /* not sure what I might actually need to do here, if anything */
68 if (procfs_file)
69 fflush (procfs_file);
70#endif
71}
72
73static void
74set_procfs_file_cmd (const char *args,
75 int from_tty, struct cmd_list_element *c)
76{
77 /* Just changed the filename for procfs tracing.
78 If a file was already open, close it. */
79 if (procfs_file)
80 fclose (procfs_file);
81 procfs_file = NULL;
82}
83
84static 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" },
113 { 0, NULL, NULL }
114};
115
116static off_t lseek_offset;
117
118int
119write_with_trace (int fd, void *varg, size_t len, char *file, int line)
120{
121 int i = ARRAY_SIZE (rw_table) - 1;
122 int ret;
123 procfs_ctl_t *arg = (procfs_ctl_t *) varg;
124
126 if (procfs_trace)
127 {
128 procfs_ctl_t opcode = arg[0];
129 for (i = 0; rw_table[i].name != NULL; i++)
130 if (rw_table[i].value == opcode)
131 break;
132
133 if (info_verbose)
134 fprintf (procfs_file ? procfs_file : stdout,
135 "%s:%d -- ", file, line);
136 switch (opcode) {
137 case PCSET:
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" :
143 "<unknown flag>",
144 info_verbose ? rw_table[i].desc : "");
145 break;
146 case PCUNSET:
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" :
152 "<unknown flag>",
153 info_verbose ? rw_table[i].desc : "");
154 break;
155 case PCSTRACE:
156 fprintf (procfs_file ? procfs_file : stdout,
157 "write (PCSTRACE) ");
159 (sigset_t *) &arg[1], 0);
160 break;
161 case PCSFAULT:
162 fprintf (procfs_file ? procfs_file : stdout,
163 "write (PCSFAULT) ");
165 (fltset_t *) &arg[1], 0);
166 break;
167 case PCSENTRY:
168 fprintf (procfs_file ? procfs_file : stdout,
169 "write (PCSENTRY) ");
171 (sysset_t *) &arg[1], 0);
172 break;
173 case PCSEXIT:
174 fprintf (procfs_file ? procfs_file : stdout,
175 "write (PCSEXIT) ");
177 (sysset_t *) &arg[1], 0);
178 break;
179 case PCSHOLD:
180 fprintf (procfs_file ? procfs_file : stdout,
181 "write (PCSHOLD) ");
183 (sigset_t *) &arg[1], 0);
184 break;
185 case PCSSIG:
186 fprintf (procfs_file ? procfs_file : stdout,
187 "write (PCSSIG) ");
189 arg[1] ? ((siginfo_t *) &arg[1])->si_signo
190 : 0,
191 0);
192 fprintf (procfs_file ? procfs_file : stdout, "\n");
193 break;
194 case PCRUN:
195 fprintf (procfs_file ? procfs_file : stdout,
196 "write (PCRUN) ");
197 if (arg[1] & PRCSIG)
198 fprintf (procfs_file ? procfs_file : stdout, "clearSig ");
199 if (arg[1] & PRCFAULT)
200 fprintf (procfs_file ? procfs_file : stdout, "clearFlt ");
201 if (arg[1] & PRSTEP)
202 fprintf (procfs_file ? procfs_file : stdout, "step ");
203 if (arg[1] & PRSABORT)
204 fprintf (procfs_file ? procfs_file : stdout, "syscallAbort ");
205 if (arg[1] & PRSTOP)
206 fprintf (procfs_file ? procfs_file : stdout, "stopReq ");
207
208 fprintf (procfs_file ? procfs_file : stdout, "\n");
209 break;
210 case PCKILL:
211 fprintf (procfs_file ? procfs_file : stdout,
212 "write (PCKILL) ");
214 arg[1], 0);
215 fprintf (procfs_file ? procfs_file : stdout, "\n");
216 break;
217 default:
218 {
219 if (rw_table[i].name)
220 fprintf (procfs_file ? procfs_file : stdout,
221 "write (%s) %s\n",
222 rw_table[i].name,
223 info_verbose ? rw_table[i].desc : "");
224 else
225 {
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);
230 else
231 fprintf (procfs_file ? procfs_file : stdout,
232 "write (<unknown>, %lud bytes) \n",
233 (unsigned long) len);
234 }
235 break;
236 }
237 }
238 if (procfs_file)
239 fflush (procfs_file);
240 }
241 errno = 0;
242 ret = write (fd, (void *) arg, len);
243 if (procfs_trace && ret != len)
244 {
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));
250 if (procfs_file)
251 fflush (procfs_file);
252 }
253
254 lseek_offset = -1;
255 return ret;
256}
257
258off_t
259lseek_with_trace (int fd, off_t offset, int whence, char *file, int line)
260{
261 off_t ret;
262
264 errno = 0;
265 ret = lseek (fd, offset, whence);
266 lseek_offset = ret;
267 if (procfs_trace && (ret == -1 || errno != 0))
268 {
269 fprintf (procfs_file ? procfs_file : stdout,
270 "[lseek (0x%08lx) FAILED! (%s)]\n",
271 (unsigned long) offset, safe_strerror (errno));
272 if (procfs_file)
273 fflush (procfs_file);
274 }
275
276 return ret;
277}
278
279int
280open_with_trace (char *filename, int mode, char *file, int line)
281{
282 int ret;
283
285 errno = 0;
286 ret = open (filename, mode);
287 if (procfs_trace)
288 {
289 if (info_verbose)
290 fprintf (procfs_file ? procfs_file : stdout,
291 "%s:%d -- ", file, line);
292
293 if (errno)
294 {
295 fprintf (procfs_file ? procfs_file : stdout,
296 "[open FAILED! (%s) line %d]\\n",
297 safe_strerror (errno), line);
298 }
299 else
300 {
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",
305 line);
306 else if (mode == O_WRONLY)
307 fprintf (procfs_file ? procfs_file : stdout, "O_WRONLY) %d\n",
308 line);
309 else if (mode == O_RDWR)
310 fprintf (procfs_file ? procfs_file : stdout, "O_RDWR) %d\n",
311 line);
312 }
313 if (procfs_file)
314 fflush (procfs_file);
315 }
316
317 return ret;
318}
319
320int
321close_with_trace (int fd, char *file, int line)
322{
323 int ret;
324
326 errno = 0;
327 ret = close (fd);
328 if (procfs_trace)
329 {
330 if (info_verbose)
331 fprintf (procfs_file ? procfs_file : stdout,
332 "%s:%d -- ", file, line);
333 if (errno)
334 fprintf (procfs_file ? procfs_file : stdout,
335 "[close FAILED! (%s)]\n", safe_strerror (errno));
336 else
337 fprintf (procfs_file ? procfs_file : stdout,
338 "%d = close (%d)\n", ret, fd);
339 if (procfs_file)
340 fflush (procfs_file);
341 }
342
343 return ret;
344}
345
346pid_t
347wait_with_trace (int *wstat, char *file, int line)
348{
349 int ret, lstat = 0;
350
352 if (procfs_trace)
353 {
354 if (info_verbose)
355 fprintf (procfs_file ? procfs_file : stdout,
356 "%s:%d -- ", file, line);
357 fprintf (procfs_file ? procfs_file : stdout,
358 "wait (line %d) ", line);
359 if (procfs_file)
360 fflush (procfs_file);
361 }
362 errno = 0;
363 ret = wait (&lstat);
364 if (procfs_trace)
365 {
366 if (errno)
367 fprintf (procfs_file ? procfs_file : stdout,
368 "[wait FAILED! (%s)]\n", safe_strerror (errno));
369 else
370 fprintf (procfs_file ? procfs_file : stdout,
371 "returned pid %d, status 0x%x\n", ret, lstat);
372 if (procfs_file)
373 fflush (procfs_file);
374 }
375 if (wstat)
376 *wstat = lstat;
377
378 return ret;
379}
380
381void
382procfs_note (const char *msg, const char *file, int line)
383{
385 if (procfs_trace)
386 {
387 if (info_verbose)
388 fprintf (procfs_file ? procfs_file : stdout,
389 "%s:%d -- ", file, line);
390 fprintf (procfs_file ? procfs_file : stdout, "%s", msg);
391 if (procfs_file)
392 fflush (procfs_file);
393 }
394}
395
396void
397proc_prettyfprint_status (long flags, int why, int what, int thread)
398{
400 if (procfs_trace)
401 {
402 if (thread)
403 fprintf (procfs_file ? procfs_file : stdout,
404 "Thread %d: ", thread);
405
407 flags, 0);
408
409 if (flags & (PR_STOPPED | PR_ISTOP))
411 why, what, 0);
412 if (procfs_file)
413 fflush (procfs_file);
414 }
415}
416
418void
420{
421 add_setshow_boolean_cmd ("procfs-trace", no_class, &procfs_trace, _("\
422Set tracing for /proc api calls."), _("\
423Show tracing for /proc api calls."), NULL,
425 NULL, /* FIXME: i18n: */
426 &setlist, &showlist);
427
429Set filename for /proc tracefile."), _("\
430Show filename for /proc tracefile."), NULL,
432 NULL, /* FIXME: i18n: */
433 &setlist, &showlist);
434}
const char *const name
Definition: aarch64-tdep.c:67
struct cmd_list_element * showlist
Definition: cli-cmds.c:125
struct cmd_list_element * setlist
Definition: cli-cmds.c:117
set_show_commands add_setshow_filename_cmd(const char *name, enum command_class theclass, std::string *var, const char *set_doc, const char *show_doc, const char *help_doc, cmd_func_ftype *set_func, show_value_ftype *show_func, struct cmd_list_element **set_list, struct cmd_list_element **show_list)
Definition: cli-decode.c:785
set_show_commands add_setshow_boolean_cmd(const char *name, enum command_class theclass, bool *var, const char *set_doc, const char *show_doc, const char *help_doc, cmd_func_ftype *set_func, show_value_ftype *show_func, struct cmd_list_element **set_list, struct cmd_list_element **show_list)
Definition: cli-decode.c:739
@ no_class
Definition: command.h:53
bool info_verbose
Definition: top.c:2022
mach_port_t kern_return_t mach_port_t mach_msg_type_name_t msgportsPoly mach_port_t kern_return_t pid_t pid mach_port_t kern_return_t mach_port_t task mach_port_t kern_return_t int flags
Definition: gnu-nat.c:1862
static void set_procfs_file_cmd(const char *args, int from_tty, struct cmd_list_element *c)
Definition: proc-api.c:74
static void set_procfs_trace_cmd(const char *args, int from_tty, struct cmd_list_element *c)
Definition: proc-api.c:64
int close_with_trace(int fd, char *file, int line)
Definition: proc-api.c:321
static FILE * procfs_file
Definition: proc-api.c:52
static off_t lseek_offset
Definition: proc-api.c:116
int open_with_trace(char *filename, int mode, char *file, int line)
Definition: proc-api.c:280
static void prepare_to_trace(void)
Definition: proc-api.c:56
void proc_prettyfprint_status(long flags, int why, int what, int thread)
Definition: proc-api.c:397
static bool procfs_trace
Definition: proc-api.c:51
off_t lseek_with_trace(int fd, off_t offset, int whence, char *file, int line)
Definition: proc-api.c:259
static struct trans rw_table[]
Definition: proc-api.c:84
void procfs_note(const char *msg, const char *file, int line)
Definition: proc-api.c:382
pid_t wait_with_trace(int *wstat, char *file, int line)
Definition: proc-api.c:347
static std::string procfs_filename
Definition: proc-api.c:53
int write_with_trace(int fd, void *varg, size_t len, char *file, int line)
Definition: proc-api.c:119
void _initialize_proc_api()
Definition: proc-api.c:419
void proc_prettyfprint_syscalls(FILE *file, sysset_t *sysset, int verbose)
Definition: proc-events.c:543
void proc_prettyfprint_signalset(FILE *file, sigset_t *sigset, int verbose)
Definition: proc-events.c:651
void proc_prettyfprint_faultset(FILE *file, fltset_t *fltset, int verbose)
Definition: proc-events.c:734
void proc_prettyfprint_signal(FILE *file, int signo, int verbose)
Definition: proc-events.c:625
void proc_prettyfprint_flags(FILE *file, unsigned long flags, int verbose)
Definition: proc-flags.c:92
void proc_prettyfprint_why(FILE *file, unsigned long why, unsigned long what, int verbose)
Definition: proc-why.c:61
long procfs_ctl_t
Definition: proc-utils.h:118
Definition: proc-api.c:45
long value
Definition: proc-api.c:46
const char * desc
Definition: proc-api.c:48
const char * name
Definition: proc-api.c:47
Definition: value.c:181