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