gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gdb / proc-api.c
CommitLineData
44122162 1/* Machine independent support for Solaris /proc (process file system) for GDB.
2555fe1a 2
b811d2c2 3 Copyright (C) 1999-2020 Free Software Foundation, Inc.
2555fe1a 4
0fda6bd2
JM
5 Written by Michael Snyder at Cygnus Solutions.
6 Based on work by Fred Fish, Stu Grossman, Geoff Noer, and others.
7
a9762ec7
JB
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/>. */
0fda6bd2
JM
22
23/*
24 * Pretty-print trace of api calls to the /proc api
0fda6bd2
JM
25 */
26
27#include "defs.h"
28#include "gdbcmd.h"
8e40d292 29#include "completer.h"
0fda6bd2 30
0fda6bd2 31#define _STRUCTURED_PROC 1
0fda6bd2 32
0fda6bd2
JM
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 */
0df8b418 37#include <fcntl.h> /* for O_RDWR etc. */
268a13a5 38#include "gdbsupport/gdb_wait.h"
0fda6bd2
JM
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
0df8b418 45 their symbolic names and to a string that describes their specific use. */
0fda6bd2
JM
46
47struct trans {
48 long value; /* The numeric value */
995816ba
PA
49 const char *name; /* The equivalent symbolic value */
50 const char *desc; /* Short description of value */
0fda6bd2
JM
51};
52
491144b5 53static bool procfs_trace = false;
0fda6bd2 54static FILE *procfs_file = NULL;
3e83a920 55static char *procfs_filename;
0fda6bd2 56
103b3ef5
MS
57static void
58prepare_to_trace (void)
59{
60 if (procfs_trace) /* if procfs tracing turned on */
61 if (procfs_file == NULL) /* if output file not yet open */
3e83a920 62 procfs_file = fopen (procfs_filename, "a"); /* open output file */
103b3ef5
MS
63}
64
0fda6bd2 65static void
eb4c3f4a
TT
66set_procfs_trace_cmd (const char *args,
67 int from_tty, struct cmd_list_element *c)
0fda6bd2
JM
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
75static void
eb4c3f4a
TT
76set_procfs_file_cmd (const char *args,
77 int from_tty, struct cmd_list_element *c)
0fda6bd2
JM
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
0fda6bd2 86static struct trans rw_table[] = {
0fda6bd2 87 { PCAGENT, "PCAGENT", "create agent lwp with regs from argument" },
0fda6bd2 88 { PCCFAULT, "PCCFAULT", "clear current fault" },
0fda6bd2 89 { PCCSIG, "PCCSIG", "clear current signal" },
0fda6bd2
JM
90 { PCDSTOP, "PCDSTOP", "post stop request" },
91 { PCKILL, "PCKILL", "post a signal" },
92 { PCNICE, "PCNICE", "set nice priority" },
0fda6bd2
JM
93 { PCREAD, "PCREAD", "read from the address space" },
94 { PCWRITE, "PCWRITE", "write to the address space" },
0fda6bd2 95 { PCRUN, "PCRUN", "make process/lwp runnable" },
0fda6bd2 96 { PCSASRS, "PCSASRS", "set ancillary state registers" },
0fda6bd2 97 { PCSCRED, "PCSCRED", "set process credentials" },
0fda6bd2
JM
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" },
0fda6bd2 108 { PCSVADDR, "PCSVADDR", "set pc virtual address" },
0fda6bd2 109 { PCSXREG, "PCSXREG", "set extra registers" },
0fda6bd2 110 { PCTWSTOP, "PCTWSTOP", "wait for stop, with timeout arg" },
0fda6bd2 111 { PCUNKILL, "PCUNKILL", "delete a pending signal" },
0fda6bd2 112 { PCUNSET, "PCUNSET", "unset modes" },
0fda6bd2 113 { PCWATCH, "PCWATCH", "set/unset watched memory area" },
0fda6bd2
JM
114 { PCWSTOP, "PCWSTOP", "wait for process/lwp to stop, no timeout" },
115 { 0, NULL, NULL }
116};
117
118static off_t lseek_offset;
119
120int
fba45db2 121write_with_trace (int fd, void *varg, size_t len, char *file, int line)
0fda6bd2 122{
1e52e2eb 123 int i = ARRAY_SIZE (rw_table) - 1;
0fda6bd2 124 int ret;
37de36c6 125 procfs_ctl_t *arg = (procfs_ctl_t *) varg;
0fda6bd2 126
103b3ef5 127 prepare_to_trace ();
0fda6bd2
JM
128 if (procfs_trace)
129 {
37de36c6 130 procfs_ctl_t opcode = arg[0];
0fda6bd2
JM
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" :
0fda6bd2 144 arg[1] == PR_ASYNC ? "PR_ASYNC" :
0fda6bd2
JM
145 "<unknown flag>",
146 info_verbose ? rw_table[i].desc : "");
147 break;
0fda6bd2 148 case PCUNSET:
0fda6bd2
JM
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" :
0fda6bd2 153 arg[1] == PR_ASYNC ? "PR_ASYNC" :
0fda6bd2
JM
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) ");
160 proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout,
161 (sigset_t *) &arg[1], 0);
162 break;
163 case PCSFAULT:
164 fprintf (procfs_file ? procfs_file : stdout,
165 "write (PCSFAULT) ");
166 proc_prettyfprint_faultset (procfs_file ? procfs_file : stdout,
167 (fltset_t *) &arg[1], 0);
168 break;
169 case PCSENTRY:
170 fprintf (procfs_file ? procfs_file : stdout,
171 "write (PCSENTRY) ");
172 proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout,
173 (sysset_t *) &arg[1], 0);
174 break;
175 case PCSEXIT:
176 fprintf (procfs_file ? procfs_file : stdout,
177 "write (PCSEXIT) ");
178 proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout,
179 (sysset_t *) &arg[1], 0);
180 break;
181 case PCSHOLD:
182 fprintf (procfs_file ? procfs_file : stdout,
183 "write (PCSHOLD) ");
184 proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout,
185 (sigset_t *) &arg[1], 0);
186 break;
187 case PCSSIG:
188 fprintf (procfs_file ? procfs_file : stdout,
189 "write (PCSSIG) ");
190 proc_prettyfprint_signal (procfs_file ? procfs_file : stdout,
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) ");
215 proc_prettyfprint_signal (procfs_file ? procfs_file : stdout,
216 arg[1], 0);
217 fprintf (procfs_file ? procfs_file : stdout, "\n");
218 break;
219 default:
220 {
37de36c6 221 if (rw_table[i].name)
0fda6bd2
JM
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,
b943d152
MS
230 "write (<unknown>, %lud bytes at 0x%08lx) \n",
231 (unsigned long) len, (unsigned long) lseek_offset);
0fda6bd2
JM
232 else
233 fprintf (procfs_file ? procfs_file : stdout,
b943d152
MS
234 "write (<unknown>, %lud bytes) \n",
235 (unsigned long) len);
0fda6bd2
JM
236 }
237 break;
238 }
239 }
240 if (procfs_file)
241 fflush (procfs_file);
242 }
103b3ef5 243 errno = 0;
b943d152 244 ret = write (fd, (void *) arg, len);
0fda6bd2
JM
245 if (procfs_trace && ret != len)
246 {
247 fprintf (procfs_file ? procfs_file : stdout,
103b3ef5 248 "[write (%s) FAILED! (%s)]\n",
0fda6bd2 249 rw_table[i].name != NULL ?
103b3ef5
MS
250 rw_table[i].name : "<unknown>",
251 safe_strerror (errno));
0fda6bd2
JM
252 if (procfs_file)
253 fflush (procfs_file);
254 }
255
256 lseek_offset = -1;
257 return ret;
258}
259
260off_t
fba45db2 261lseek_with_trace (int fd, off_t offset, int whence, char *file, int line)
0fda6bd2
JM
262{
263 off_t ret;
264
103b3ef5
MS
265 prepare_to_trace ();
266 errno = 0;
0fda6bd2
JM
267 ret = lseek (fd, offset, whence);
268 lseek_offset = ret;
103b3ef5 269 if (procfs_trace && (ret == -1 || errno != 0))
0fda6bd2 270 {
0fda6bd2 271 fprintf (procfs_file ? procfs_file : stdout,
103b3ef5
MS
272 "[lseek (0x%08lx) FAILED! (%s)]\n",
273 (unsigned long) offset, safe_strerror (errno));
0fda6bd2
JM
274 if (procfs_file)
275 fflush (procfs_file);
276 }
277
278 return ret;
279}
280
0fda6bd2 281int
fba45db2 282open_with_trace (char *filename, int mode, char *file, int line)
0fda6bd2 283{
103b3ef5 284 int ret;
0fda6bd2 285
103b3ef5
MS
286 prepare_to_trace ();
287 errno = 0;
288 ret = open (filename, mode);
0fda6bd2
JM
289 if (procfs_trace)
290 {
0fda6bd2
JM
291 if (info_verbose)
292 fprintf (procfs_file ? procfs_file : stdout,
293 "%s:%d -- ", file, line);
103b3ef5
MS
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 }
0fda6bd2
JM
315 if (procfs_file)
316 fflush (procfs_file);
317 }
318
319 return ret;
320}
321
322int
fba45db2 323close_with_trace (int fd, char *file, int line)
0fda6bd2 324{
103b3ef5 325 int ret;
0fda6bd2 326
103b3ef5
MS
327 prepare_to_trace ();
328 errno = 0;
329 ret = close (fd);
0fda6bd2
JM
330 if (procfs_trace)
331 {
0fda6bd2
JM
332 if (info_verbose)
333 fprintf (procfs_file ? procfs_file : stdout,
334 "%s:%d -- ", file, line);
103b3ef5
MS
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);
0fda6bd2
JM
341 if (procfs_file)
342 fflush (procfs_file);
343 }
344
345 return ret;
346}
347
103b3ef5 348pid_t
fba45db2 349wait_with_trace (int *wstat, char *file, int line)
0fda6bd2
JM
350{
351 int ret, lstat = 0;
352
103b3ef5 353 prepare_to_trace ();
0fda6bd2
JM
354 if (procfs_trace)
355 {
0fda6bd2
JM
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 }
103b3ef5 364 errno = 0;
0fda6bd2
JM
365 ret = wait (&lstat);
366 if (procfs_trace)
367 {
103b3ef5
MS
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);
0fda6bd2
JM
374 if (procfs_file)
375 fflush (procfs_file);
376 }
377 if (wstat)
378 *wstat = lstat;
379
380 return ret;
381}
382
383void
995816ba 384procfs_note (const char *msg, const char *file, int line)
0fda6bd2 385{
103b3ef5 386 prepare_to_trace ();
0fda6bd2
JM
387 if (procfs_trace)
388 {
0fda6bd2
JM
389 if (info_verbose)
390 fprintf (procfs_file ? procfs_file : stdout,
391 "%s:%d -- ", file, line);
e34e1a85 392 fprintf (procfs_file ? procfs_file : stdout, "%s", msg);
0fda6bd2
JM
393 if (procfs_file)
394 fflush (procfs_file);
395 }
396}
397
398void
fba45db2 399proc_prettyfprint_status (long flags, int why, int what, int thread)
0fda6bd2 400{
103b3ef5 401 prepare_to_trace ();
0fda6bd2
JM
402 if (procfs_trace)
403 {
0fda6bd2
JM
404 if (thread)
405 fprintf (procfs_file ? procfs_file : stdout,
406 "Thread %d: ", thread);
407
408 proc_prettyfprint_flags (procfs_file ? procfs_file : stdout,
409 flags, 0);
410
411 if (flags & (PR_STOPPED | PR_ISTOP))
412 proc_prettyfprint_why (procfs_file ? procfs_file : stdout,
413 why, what, 0);
414 if (procfs_file)
415 fflush (procfs_file);
416 }
417}
418
6c265988 419void _initialize_proc_api ();
0fda6bd2 420void
6c265988 421_initialize_proc_api ()
0fda6bd2 422{
54433e38
MK
423 add_setshow_boolean_cmd ("procfs-trace", no_class, &procfs_trace, _("\
424Set tracing for /proc api calls."), _("\
425Show tracing for /proc api calls."), NULL,
5bf193a2
AC
426 set_procfs_trace_cmd,
427 NULL, /* FIXME: i18n: */
428 &setlist, &showlist);
0fda6bd2 429
3e83a920 430 procfs_filename = xstrdup ("procfs_trace");
54433e38
MK
431 add_setshow_filename_cmd ("procfs-file", no_class, &procfs_filename, _("\
432Set filename for /proc tracefile."), _("\
433Show filename for /proc tracefile."), NULL,
f397e303
AC
434 set_procfs_file_cmd,
435 NULL, /* FIXME: i18n: */
436 &setlist, &showlist);
0fda6bd2 437}
This page took 1.932876 seconds and 4 git commands to generate.