GDB (xrefs)
/tmp/gdb-8.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-2018 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 #define _STRUCTURED_PROC 1
32 
33 #include <sys/types.h>
34 #include <sys/procfs.h>
35 #include <sys/proc.h> /* for struct proc */
36 #include <sys/user.h> /* for struct user */
37 #include <fcntl.h> /* for O_RDWR etc. */
38 #include "gdb_wait.h"
39 
40 #include "proc-utils.h"
41 
42 /* Much of the information used in the /proc interface, particularly for
43  printing status information, is kept as tables of structures of the
44  following form. These tables can be used to map numeric values to
45  their symbolic names and to a string that describes their specific use. */
46 
47 struct trans {
48  long value; /* The numeric value */
49  const char *name; /* The equivalent symbolic value */
50  const char *desc; /* Short description of value */
51 };
52 
53 static int procfs_trace = 0;
54 static FILE *procfs_file = NULL;
55 static char *procfs_filename;
56 
57 static void
59 {
60  if (procfs_trace) /* if procfs tracing turned on */
61  if (procfs_file == NULL) /* if output file not yet open */
62  procfs_file = fopen (procfs_filename, "a"); /* open output file */
63 }
64 
65 static void
66 set_procfs_trace_cmd (const char *args,
67  int from_tty, struct cmd_list_element *c)
68 {
69 #if 0 /* not sure what I might actually need to do here, if anything */
70  if (procfs_file)
71  fflush (procfs_file);
72 #endif
73 }
74 
75 static void
76 set_procfs_file_cmd (const char *args,
77  int from_tty, struct cmd_list_element *c)
78 {
79  /* Just changed the filename for procfs tracing.
80  If a file was already open, close it. */
81  if (procfs_file)
82  fclose (procfs_file);
83  procfs_file = NULL;
84 }
85 
86 static struct trans rw_table[] = {
87  { PCAGENT, "PCAGENT", "create agent lwp with regs from argument" },
88  { PCCFAULT, "PCCFAULT", "clear current fault" },
89  { PCCSIG, "PCCSIG", "clear current signal" },
90  { PCDSTOP, "PCDSTOP", "post stop request" },
91  { PCKILL, "PCKILL", "post a signal" },
92  { PCNICE, "PCNICE", "set nice priority" },
93  { PCREAD, "PCREAD", "read from the address space" },
94  { PCWRITE, "PCWRITE", "write to the address space" },
95  { PCRUN, "PCRUN", "make process/lwp runnable" },
96  { PCSASRS, "PCSASRS", "set ancillary state registers" },
97  { PCSCRED, "PCSCRED", "set process credentials" },
98  { PCSENTRY, "PCSENTRY", "set traced syscall entry set" },
99  { PCSET, "PCSET", "set modes" },
100  { PCSEXIT, "PCSEXIT", "set traced syscall exit set" },
101  { PCSFAULT, "PCSFAULT", "set traced fault set" },
102  { PCSFPREG, "PCSFPREG", "set floating point registers" },
103  { PCSHOLD, "PCSHOLD", "set signal mask" },
104  { PCSREG, "PCSREG", "set general registers" },
105  { PCSSIG, "PCSSIG", "set current signal" },
106  { PCSTOP, "PCSTOP", "post stop request and wait" },
107  { PCSTRACE, "PCSTRACE", "set traced signal set" },
108  { PCSVADDR, "PCSVADDR", "set pc virtual address" },
109  { PCSXREG, "PCSXREG", "set extra registers" },
110  { PCTWSTOP, "PCTWSTOP", "wait for stop, with timeout arg" },
111  { PCUNKILL, "PCUNKILL", "delete a pending signal" },
112  { PCUNSET, "PCUNSET", "unset modes" },
113  { PCWATCH, "PCWATCH", "set/unset watched memory area" },
114  { PCWSTOP, "PCWSTOP", "wait for process/lwp to stop, no timeout" },
115  { 0, NULL, NULL }
116 };
117 
118 static off_t lseek_offset;
119 
120 int
121 write_with_trace (int fd, void *varg, size_t len, char *file, int line)
122 {
123  int i = ARRAY_SIZE (rw_table) - 1;
124  int ret;
125  procfs_ctl_t *arg = (procfs_ctl_t *) varg;
126 
127  prepare_to_trace ();
128  if (procfs_trace)
129  {
130  procfs_ctl_t opcode = arg[0];
131  for (i = 0; rw_table[i].name != NULL; i++)
132  if (rw_table[i].value == opcode)
133  break;
134 
135  if (info_verbose)
136  fprintf (procfs_file ? procfs_file : stdout,
137  "%s:%d -- ", file, line);
138  switch (opcode) {
139  case PCSET:
140  fprintf (procfs_file ? procfs_file : stdout,
141  "write (PCSET, %s) %s\n",
142  arg[1] == PR_FORK ? "PR_FORK" :
143  arg[1] == PR_RLC ? "PR_RLC" :
144  arg[1] == PR_ASYNC ? "PR_ASYNC" :
145  "<unknown flag>",
146  info_verbose ? rw_table[i].desc : "");
147  break;
148  case PCUNSET:
149  fprintf (procfs_file ? procfs_file : stdout,
150  "write (PCRESET, %s) %s\n",
151  arg[1] == PR_FORK ? "PR_FORK" :
152  arg[1] == PR_RLC ? "PR_RLC" :
153  arg[1] == PR_ASYNC ? "PR_ASYNC" :
154  "<unknown flag>",
155  info_verbose ? rw_table[i].desc : "");
156  break;
157  case PCSTRACE:
158  fprintf (procfs_file ? procfs_file : stdout,
159  "write (PCSTRACE) ");
161  (sigset_t *) &arg[1], 0);
162  break;
163  case PCSFAULT:
164  fprintf (procfs_file ? procfs_file : stdout,
165  "write (PCSFAULT) ");
167  (fltset_t *) &arg[1], 0);
168  break;
169  case PCSENTRY:
170  fprintf (procfs_file ? procfs_file : stdout,
171  "write (PCSENTRY) ");
173  (sysset_t *) &arg[1], 0);
174  break;
175  case PCSEXIT:
176  fprintf (procfs_file ? procfs_file : stdout,
177  "write (PCSEXIT) ");
179  (sysset_t *) &arg[1], 0);
180  break;
181  case PCSHOLD:
182  fprintf (procfs_file ? procfs_file : stdout,
183  "write (PCSHOLD) ");
185  (sigset_t *) &arg[1], 0);
186  break;
187  case PCSSIG:
188  fprintf (procfs_file ? procfs_file : stdout,
189  "write (PCSSIG) ");
191  arg[1] ? ((siginfo_t *) &arg[1])->si_signo
192  : 0,
193  0);
194  fprintf (procfs_file ? procfs_file : stdout, "\n");
195  break;
196  case PCRUN:
197  fprintf (procfs_file ? procfs_file : stdout,
198  "write (PCRUN) ");
199  if (arg[1] & PRCSIG)
200  fprintf (procfs_file ? procfs_file : stdout, "clearSig ");
201  if (arg[1] & PRCFAULT)
202  fprintf (procfs_file ? procfs_file : stdout, "clearFlt ");
203  if (arg[1] & PRSTEP)
204  fprintf (procfs_file ? procfs_file : stdout, "step ");
205  if (arg[1] & PRSABORT)
206  fprintf (procfs_file ? procfs_file : stdout, "syscallAbort ");
207  if (arg[1] & PRSTOP)
208  fprintf (procfs_file ? procfs_file : stdout, "stopReq ");
209 
210  fprintf (procfs_file ? procfs_file : stdout, "\n");
211  break;
212  case PCKILL:
213  fprintf (procfs_file ? procfs_file : stdout,
214  "write (PCKILL) ");
216  arg[1], 0);
217  fprintf (procfs_file ? procfs_file : stdout, "\n");
218  break;
219  default:
220  {
221  if (rw_table[i].name)
222  fprintf (procfs_file ? procfs_file : stdout,
223  "write (%s) %s\n",
224  rw_table[i].name,
225  info_verbose ? rw_table[i].desc : "");
226  else
227  {
228  if (lseek_offset != -1)
229  fprintf (procfs_file ? procfs_file : stdout,
230  "write (<unknown>, %lud bytes at 0x%08lx) \n",
231  (unsigned long) len, (unsigned long) lseek_offset);
232  else
233  fprintf (procfs_file ? procfs_file : stdout,
234  "write (<unknown>, %lud bytes) \n",
235  (unsigned long) len);
236  }
237  break;
238  }
239  }
240  if (procfs_file)
241  fflush (procfs_file);
242  }
243  errno = 0;
244  ret = write (fd, (void *) arg, len);
245  if (procfs_trace && ret != len)
246  {
247  fprintf (procfs_file ? procfs_file : stdout,
248  "[write (%s) FAILED! (%s)]\n",
249  rw_table[i].name != NULL ?
250  rw_table[i].name : "<unknown>",
251  safe_strerror (errno));
252  if (procfs_file)
253  fflush (procfs_file);
254  }
255 
256  lseek_offset = -1;
257  return ret;
258 }
259 
260 off_t
261 lseek_with_trace (int fd, off_t offset, int whence, char *file, int line)
262 {
263  off_t ret;
264 
265  prepare_to_trace ();
266  errno = 0;
267  ret = lseek (fd, offset, whence);
268  lseek_offset = ret;
269  if (procfs_trace && (ret == -1 || errno != 0))
270  {
271  fprintf (procfs_file ? procfs_file : stdout,
272  "[lseek (0x%08lx) FAILED! (%s)]\n",
273  (unsigned long) offset, safe_strerror (errno));
274  if (procfs_file)
275  fflush (procfs_file);
276  }
277 
278  return ret;
279 }
280 
281 int
282 open_with_trace (char *filename, int mode, char *file, int line)
283 {
284  int ret;
285 
286  prepare_to_trace ();
287  errno = 0;
288  ret = open (filename, mode);
289  if (procfs_trace)
290  {
291  if (info_verbose)
292  fprintf (procfs_file ? procfs_file : stdout,
293  "%s:%d -- ", file, line);
294 
295  if (errno)
296  {
297  fprintf (procfs_file ? procfs_file : stdout,
298  "[open FAILED! (%s) line %d]\\n",
299  safe_strerror (errno), line);
300  }
301  else
302  {
303  fprintf (procfs_file ? procfs_file : stdout,
304  "%d = open (%s, ", ret, filename);
305  if (mode == O_RDONLY)
306  fprintf (procfs_file ? procfs_file : stdout, "O_RDONLY) %d\n",
307  line);
308  else if (mode == O_WRONLY)
309  fprintf (procfs_file ? procfs_file : stdout, "O_WRONLY) %d\n",
310  line);
311  else if (mode == O_RDWR)
312  fprintf (procfs_file ? procfs_file : stdout, "O_RDWR) %d\n",
313  line);
314  }
315  if (procfs_file)
316  fflush (procfs_file);
317  }
318 
319  return ret;
320 }
321 
322 int
323 close_with_trace (int fd, char *file, int line)
324 {
325  int ret;
326 
327  prepare_to_trace ();
328  errno = 0;
329  ret = close (fd);
330  if (procfs_trace)
331  {
332  if (info_verbose)
333  fprintf (procfs_file ? procfs_file : stdout,
334  "%s:%d -- ", file, line);
335  if (errno)
336  fprintf (procfs_file ? procfs_file : stdout,
337  "[close FAILED! (%s)]\n", safe_strerror (errno));
338  else
339  fprintf (procfs_file ? procfs_file : stdout,
340  "%d = close (%d)\n", ret, fd);
341  if (procfs_file)
342  fflush (procfs_file);
343  }
344 
345  return ret;
346 }
347 
348 pid_t
349 wait_with_trace (int *wstat, char *file, int line)
350 {
351  int ret, lstat = 0;
352 
353  prepare_to_trace ();
354  if (procfs_trace)
355  {
356  if (info_verbose)
357  fprintf (procfs_file ? procfs_file : stdout,
358  "%s:%d -- ", file, line);
359  fprintf (procfs_file ? procfs_file : stdout,
360  "wait (line %d) ", line);
361  if (procfs_file)
362  fflush (procfs_file);
363  }
364  errno = 0;
365  ret = wait (&lstat);
366  if (procfs_trace)
367  {
368  if (errno)
369  fprintf (procfs_file ? procfs_file : stdout,
370  "[wait FAILED! (%s)]\n", safe_strerror (errno));
371  else
372  fprintf (procfs_file ? procfs_file : stdout,
373  "returned pid %d, status 0x%x\n", ret, lstat);
374  if (procfs_file)
375  fflush (procfs_file);
376  }
377  if (wstat)
378  *wstat = lstat;
379 
380  return ret;
381 }
382 
383 void
384 procfs_note (const char *msg, const char *file, int line)
385 {
386  prepare_to_trace ();
387  if (procfs_trace)
388  {
389  if (info_verbose)
390  fprintf (procfs_file ? procfs_file : stdout,
391  "%s:%d -- ", file, line);
392  fprintf (procfs_file ? procfs_file : stdout, "%s", msg);
393  if (procfs_file)
394  fflush (procfs_file);
395  }
396 }
397 
398 void
399 proc_prettyfprint_status (long flags, int why, int what, int thread)
400 {
401  prepare_to_trace ();
402  if (procfs_trace)
403  {
404  if (thread)
405  fprintf (procfs_file ? procfs_file : stdout,
406  "Thread %d: ", thread);
407 
409  flags, 0);
410 
411  if (flags & (PR_STOPPED | PR_ISTOP))
413  why, what, 0);
414  if (procfs_file)
415  fflush (procfs_file);
416  }
417 }
418 
419 void
421 {
422  struct cmd_list_element *c;
423 
424  add_setshow_boolean_cmd ("procfs-trace", no_class, &procfs_trace, _("\
425 Set tracing for /proc api calls."), _("\
426 Show tracing for /proc api calls."), NULL,
428  NULL, /* FIXME: i18n: */
429  &setlist, &showlist);
430 
431  procfs_filename = xstrdup ("procfs_trace");
432  add_setshow_filename_cmd ("procfs-file", no_class, &procfs_filename, _("\
433 Set filename for /proc tracefile."), _("\
434 Show filename for /proc tracefile."), NULL,
436  NULL, /* FIXME: i18n: */
437  &setlist, &showlist);
438 }
void add_setshow_filename_cmd(const char *name, enum command_class theclass, char **var, const char *set_doc, const char *show_doc, const char *help_doc, cmd_const_sfunc_ftype *set_func, show_value_ftype *show_func, struct cmd_list_element **set_list, struct cmd_list_element **show_list)
Definition: cli-decode.c:591
long procfs_ctl_t
Definition: proc-utils.h:118
void procfs_note(const char *msg, const char *file, int line)
Definition: proc-api.c:384
int close_with_trace(int fd, char *file, int line)
Definition: proc-api.c:323
static int procfs_trace
Definition: proc-api.c:53
static void prepare_to_trace(void)
Definition: proc-api.c:58
int info_verbose
Definition: top.c:1791
static off_t lseek_offset
Definition: proc-api.c:118
static void set_procfs_file_cmd(const char *args, int from_tty, struct cmd_list_element *c)
Definition: proc-api.c:76
off_t lseek_with_trace(int fd, off_t offset, int whence, char *file, int line)
Definition: proc-api.c:261
#define _(String)
Definition: gdb_locale.h:35
int write_with_trace(int fd, void *varg, size_t len, char *file, int line)
Definition: proc-api.c:121
static void set_procfs_trace_cmd(const char *args, int from_tty, struct cmd_list_element *c)
Definition: proc-api.c:66
mach_port_t kern_return_t mach_port_t msgports 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:1891
struct cmd_list_element * setlist
Definition: cli-cmds.c:111
static char * procfs_filename
Definition: proc-api.c:55
const char *const name
Definition: aarch64-tdep.c:76
struct cmd_list_element * showlist
Definition: cli-cmds.c:119
void proc_prettyfprint_faultset(FILE *file, fltset_t *fltset, int verbose)
Definition: proc-events.c:734
long value
Definition: proc-api.c:48
Definition: value.c:169
pid_t wait_with_trace(int *wstat, char *file, int line)
Definition: proc-api.c:349
static FILE * procfs_file
Definition: proc-api.c:54
void _initialize_proc_api(void)
Definition: proc-api.c:420
void proc_prettyfprint_why(FILE *file, unsigned long why, unsigned long what, int verbose)
Definition: proc-why.c:63
void proc_prettyfprint_syscalls(FILE *file, sysset_t *sysset, int verbose)
Definition: proc-events.c:543
char * safe_strerror(int)
int offset
Definition: agent.c:65
void add_setshow_boolean_cmd(const char *name, enum command_class theclass, int *var, const char *set_doc, const char *show_doc, const char *help_doc, cmd_const_sfunc_ftype *set_func, show_value_ftype *show_func, struct cmd_list_element **set_list, struct cmd_list_element **show_list)
Definition: cli-decode.c:569
void proc_prettyfprint_signal(FILE *file, int signo, int verbose)
Definition: proc-events.c:625
int open_with_trace(char *filename, int mode, char *file, int line)
Definition: proc-api.c:282
const char * name
Definition: proc-api.c:49
static struct trans rw_table[]
Definition: proc-api.c:86
const char * desc
Definition: proc-api.c:50
void proc_prettyfprint_signalset(FILE *file, sigset_t *sigset, int verbose)
Definition: proc-events.c:651
void proc_prettyfprint_status(long flags, int why, int what, int thread)
Definition: proc-api.c:399
Definition: proc-api.c:47
void proc_prettyfprint_flags(FILE *file, unsigned long flags, int verbose)
Definition: proc-flags.c:94