]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/proc-api.c
Update copyright year range in header of all files managed by GDB
[thirdparty/binutils-gdb.git] / gdb / proc-api.c
CommitLineData
44122162 1/* Machine independent support for Solaris /proc (process file system) for GDB.
2555fe1a 2
1d506c26 3 Copyright (C) 1999-2024 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
JM
31#include <sys/types.h>
32#include <sys/procfs.h>
ef0f16cc
TT
33#include <sys/proc.h>
34#include <sys/user.h>
35#include <fcntl.h>
268a13a5 36#include "gdbsupport/gdb_wait.h"
0fda6bd2
JM
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
0df8b418 43 their symbolic names and to a string that describes their specific use. */
0fda6bd2
JM
44
45struct trans {
46 long value; /* The numeric value */
995816ba
PA
47 const char *name; /* The equivalent symbolic value */
48 const char *desc; /* Short description of value */
0fda6bd2
JM
49};
50
491144b5 51static bool procfs_trace = false;
0fda6bd2 52static FILE *procfs_file = NULL;
e0700ba4 53static std::string procfs_filename = "procfs_trace";
0fda6bd2 54
103b3ef5
MS
55static void
56prepare_to_trace (void)
57{
58 if (procfs_trace) /* if procfs tracing turned on */
59 if (procfs_file == NULL) /* if output file not yet open */
e0700ba4 60 procfs_file = fopen (procfs_filename.c_str (), "a"); /* open output file */
103b3ef5
MS
61}
62
0fda6bd2 63static void
eb4c3f4a
TT
64set_procfs_trace_cmd (const char *args,
65 int from_tty, struct cmd_list_element *c)
0fda6bd2
JM
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
eb4c3f4a
TT
74set_procfs_file_cmd (const char *args,
75 int from_tty, struct cmd_list_element *c)
0fda6bd2
JM
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
0fda6bd2 84static struct trans rw_table[] = {
0fda6bd2 85 { PCAGENT, "PCAGENT", "create agent lwp with regs from argument" },
0fda6bd2 86 { PCCFAULT, "PCCFAULT", "clear current fault" },
0fda6bd2 87 { PCCSIG, "PCCSIG", "clear current signal" },
0fda6bd2
JM
88 { PCDSTOP, "PCDSTOP", "post stop request" },
89 { PCKILL, "PCKILL", "post a signal" },
90 { PCNICE, "PCNICE", "set nice priority" },
0fda6bd2
JM
91 { PCREAD, "PCREAD", "read from the address space" },
92 { PCWRITE, "PCWRITE", "write to the address space" },
0fda6bd2 93 { PCRUN, "PCRUN", "make process/lwp runnable" },
0fda6bd2 94 { PCSASRS, "PCSASRS", "set ancillary state registers" },
0fda6bd2 95 { PCSCRED, "PCSCRED", "set process credentials" },
0fda6bd2
JM
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" },
0fda6bd2 106 { PCSVADDR, "PCSVADDR", "set pc virtual address" },
0fda6bd2 107 { PCSXREG, "PCSXREG", "set extra registers" },
0fda6bd2 108 { PCTWSTOP, "PCTWSTOP", "wait for stop, with timeout arg" },
0fda6bd2 109 { PCUNKILL, "PCUNKILL", "delete a pending signal" },
0fda6bd2 110 { PCUNSET, "PCUNSET", "unset modes" },
0fda6bd2 111 { PCWATCH, "PCWATCH", "set/unset watched memory area" },
0fda6bd2
JM
112 { PCWSTOP, "PCWSTOP", "wait for process/lwp to stop, no timeout" },
113 { 0, NULL, NULL }
114};
115
116static off_t lseek_offset;
117
118int
fba45db2 119write_with_trace (int fd, void *varg, size_t len, char *file, int line)
0fda6bd2 120{
1e52e2eb 121 int i = ARRAY_SIZE (rw_table) - 1;
0fda6bd2 122 int ret;
37de36c6 123 procfs_ctl_t *arg = (procfs_ctl_t *) varg;
0fda6bd2 124
103b3ef5 125 prepare_to_trace ();
0fda6bd2
JM
126 if (procfs_trace)
127 {
37de36c6 128 procfs_ctl_t opcode = arg[0];
0fda6bd2
JM
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" :
0fda6bd2 142 arg[1] == PR_ASYNC ? "PR_ASYNC" :
0fda6bd2
JM
143 "<unknown flag>",
144 info_verbose ? rw_table[i].desc : "");
145 break;
0fda6bd2 146 case PCUNSET:
0fda6bd2
JM
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" :
0fda6bd2 151 arg[1] == PR_ASYNC ? "PR_ASYNC" :
0fda6bd2
JM
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
dda83cd7 190 : 0,
0fda6bd2
JM
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 {
37de36c6 219 if (rw_table[i].name)
0fda6bd2
JM
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,
b943d152
MS
228 "write (<unknown>, %lud bytes at 0x%08lx) \n",
229 (unsigned long) len, (unsigned long) lseek_offset);
0fda6bd2
JM
230 else
231 fprintf (procfs_file ? procfs_file : stdout,
b943d152
MS
232 "write (<unknown>, %lud bytes) \n",
233 (unsigned long) len);
0fda6bd2
JM
234 }
235 break;
236 }
237 }
238 if (procfs_file)
239 fflush (procfs_file);
240 }
103b3ef5 241 errno = 0;
b943d152 242 ret = write (fd, (void *) arg, len);
0fda6bd2
JM
243 if (procfs_trace && ret != len)
244 {
245 fprintf (procfs_file ? procfs_file : stdout,
103b3ef5 246 "[write (%s) FAILED! (%s)]\n",
0fda6bd2 247 rw_table[i].name != NULL ?
103b3ef5
MS
248 rw_table[i].name : "<unknown>",
249 safe_strerror (errno));
0fda6bd2
JM
250 if (procfs_file)
251 fflush (procfs_file);
252 }
253
254 lseek_offset = -1;
255 return ret;
256}
257
258off_t
fba45db2 259lseek_with_trace (int fd, off_t offset, int whence, char *file, int line)
0fda6bd2
JM
260{
261 off_t ret;
262
103b3ef5
MS
263 prepare_to_trace ();
264 errno = 0;
0fda6bd2
JM
265 ret = lseek (fd, offset, whence);
266 lseek_offset = ret;
103b3ef5 267 if (procfs_trace && (ret == -1 || errno != 0))
0fda6bd2 268 {
0fda6bd2 269 fprintf (procfs_file ? procfs_file : stdout,
103b3ef5
MS
270 "[lseek (0x%08lx) FAILED! (%s)]\n",
271 (unsigned long) offset, safe_strerror (errno));
0fda6bd2
JM
272 if (procfs_file)
273 fflush (procfs_file);
274 }
275
276 return ret;
277}
278
0fda6bd2 279int
fba45db2 280open_with_trace (char *filename, int mode, char *file, int line)
0fda6bd2 281{
103b3ef5 282 int ret;
0fda6bd2 283
103b3ef5
MS
284 prepare_to_trace ();
285 errno = 0;
286 ret = open (filename, mode);
0fda6bd2
JM
287 if (procfs_trace)
288 {
0fda6bd2
JM
289 if (info_verbose)
290 fprintf (procfs_file ? procfs_file : stdout,
291 "%s:%d -- ", file, line);
103b3ef5
MS
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 }
0fda6bd2
JM
313 if (procfs_file)
314 fflush (procfs_file);
315 }
316
317 return ret;
318}
319
320int
fba45db2 321close_with_trace (int fd, char *file, int line)
0fda6bd2 322{
103b3ef5 323 int ret;
0fda6bd2 324
103b3ef5
MS
325 prepare_to_trace ();
326 errno = 0;
327 ret = close (fd);
0fda6bd2
JM
328 if (procfs_trace)
329 {
0fda6bd2
JM
330 if (info_verbose)
331 fprintf (procfs_file ? procfs_file : stdout,
332 "%s:%d -- ", file, line);
103b3ef5
MS
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);
0fda6bd2
JM
339 if (procfs_file)
340 fflush (procfs_file);
341 }
342
343 return ret;
344}
345
103b3ef5 346pid_t
fba45db2 347wait_with_trace (int *wstat, char *file, int line)
0fda6bd2
JM
348{
349 int ret, lstat = 0;
350
103b3ef5 351 prepare_to_trace ();
0fda6bd2
JM
352 if (procfs_trace)
353 {
0fda6bd2
JM
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 }
103b3ef5 362 errno = 0;
0fda6bd2
JM
363 ret = wait (&lstat);
364 if (procfs_trace)
365 {
103b3ef5
MS
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);
0fda6bd2
JM
372 if (procfs_file)
373 fflush (procfs_file);
374 }
375 if (wstat)
376 *wstat = lstat;
377
378 return ret;
379}
380
381void
995816ba 382procfs_note (const char *msg, const char *file, int line)
0fda6bd2 383{
103b3ef5 384 prepare_to_trace ();
0fda6bd2
JM
385 if (procfs_trace)
386 {
0fda6bd2
JM
387 if (info_verbose)
388 fprintf (procfs_file ? procfs_file : stdout,
389 "%s:%d -- ", file, line);
e34e1a85 390 fprintf (procfs_file ? procfs_file : stdout, "%s", msg);
0fda6bd2
JM
391 if (procfs_file)
392 fflush (procfs_file);
393 }
394}
395
396void
fba45db2 397proc_prettyfprint_status (long flags, int why, int what, int thread)
0fda6bd2 398{
103b3ef5 399 prepare_to_trace ();
0fda6bd2
JM
400 if (procfs_trace)
401 {
0fda6bd2
JM
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
6c265988 417void _initialize_proc_api ();
0fda6bd2 418void
6c265988 419_initialize_proc_api ()
0fda6bd2 420{
54433e38
MK
421 add_setshow_boolean_cmd ("procfs-trace", no_class, &procfs_trace, _("\
422Set tracing for /proc api calls."), _("\
423Show tracing for /proc api calls."), NULL,
5bf193a2
AC
424 set_procfs_trace_cmd,
425 NULL, /* FIXME: i18n: */
426 &setlist, &showlist);
0fda6bd2 427
54433e38
MK
428 add_setshow_filename_cmd ("procfs-file", no_class, &procfs_filename, _("\
429Set filename for /proc tracefile."), _("\
430Show filename for /proc tracefile."), NULL,
f397e303
AC
431 set_procfs_file_cmd,
432 NULL, /* FIXME: i18n: */
433 &setlist, &showlist);
0fda6bd2 434}