]> Git Repo - binutils.git/blob - gdb/proc-api.c
gdb: delete unused function print_char_chars
[binutils.git] / gdb / proc-api.c
1 /* Machine independent support for Solaris /proc (process file system) for GDB.
2
3    Copyright (C) 1999-2020 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
45 struct 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
51 static bool  procfs_trace   = false;
52 static FILE *procfs_file     = NULL;
53 static char *procfs_filename;
54
55 static void
56 prepare_to_trace (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, "a");       /* open output file */
61 }
62
63 static void
64 set_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
73 static void
74 set_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
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" },
113   { 0,        NULL,      NULL }
114 };
115
116 static off_t lseek_offset;
117
118 int
119 write_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
125   prepare_to_trace ();
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) ");
158         proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout,
159                                      (sigset_t *) &arg[1], 0);
160         break;
161       case PCSFAULT:
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);
166         break;
167       case PCSENTRY:
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);
172         break;
173       case PCSEXIT:
174         fprintf (procfs_file ? procfs_file : stdout, 
175                  "write (PCSEXIT) ");
176         proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout,
177                                     (sysset_t *) &arg[1], 0);
178         break;
179       case PCSHOLD:
180         fprintf (procfs_file ? procfs_file : stdout, 
181                  "write (PCSHOLD) ");
182         proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout,
183                                      (sigset_t *) &arg[1], 0);
184         break;
185       case PCSSIG:
186         fprintf (procfs_file ? procfs_file : stdout, 
187                  "write (PCSSIG) ");
188         proc_prettyfprint_signal (procfs_file ? procfs_file : stdout,
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) ");
213         proc_prettyfprint_signal (procfs_file ? procfs_file : stdout,
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
258 off_t
259 lseek_with_trace (int fd, off_t offset, int whence, char *file, int line)
260 {
261   off_t ret;
262
263   prepare_to_trace ();
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
279 int
280 open_with_trace (char *filename, int mode, char *file, int line)
281 {
282   int ret;
283
284   prepare_to_trace ();
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
320 int
321 close_with_trace (int fd, char *file, int line)
322 {
323   int ret;
324
325   prepare_to_trace ();
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
346 pid_t
347 wait_with_trace (int *wstat, char *file, int line)
348 {
349   int ret, lstat = 0;
350
351   prepare_to_trace ();
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
381 void
382 procfs_note (const char *msg, const char *file, int line)
383 {
384   prepare_to_trace ();
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
396 void
397 proc_prettyfprint_status (long flags, int why, int what, int thread)
398 {
399   prepare_to_trace ();
400   if (procfs_trace)
401     {
402       if (thread)
403         fprintf (procfs_file ? procfs_file : stdout,
404                  "Thread %d: ", thread);
405
406       proc_prettyfprint_flags (procfs_file ? procfs_file : stdout, 
407                                flags, 0);
408
409       if (flags & (PR_STOPPED | PR_ISTOP))
410         proc_prettyfprint_why (procfs_file ? procfs_file : stdout, 
411                                why, what, 0);
412       if (procfs_file)
413         fflush (procfs_file);
414     }
415 }
416
417 void _initialize_proc_api ();
418 void
419 _initialize_proc_api ()
420 {
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);
427
428   procfs_filename = xstrdup ("procfs_trace");
429   add_setshow_filename_cmd ("procfs-file", no_class, &procfs_filename, _("\
430 Set filename for /proc tracefile."), _("\
431 Show filename for /proc tracefile."), NULL,
432                             set_procfs_file_cmd,
433                             NULL, /* FIXME: i18n: */
434                             &setlist, &showlist);
435 }
This page took 0.05052 seconds and 4 git commands to generate.