]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/proc-api.c
gdb: update is_addr_in_objfile to support "dynamic" objfiles
[thirdparty/binutils-gdb.git] / gdb / proc-api.c
CommitLineData
44122162 1/* Machine independent support for Solaris /proc (process file system) for GDB.
2555fe1a 2
d01e8234 3 Copyright (C) 1999-2025 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)
a5cbe675 133 fprintf (procfs_file ? procfs_file : stdout,
0fda6bd2
JM
134 "%s:%d -- ", file, line);
135 switch (opcode) {
136 case PCSET:
a5cbe675
SM
137 fprintf (procfs_file ? procfs_file : stdout,
138 "write (PCSET, %s) %s\n",
0fda6bd2
JM
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:
a5cbe675
SM
146 fprintf (procfs_file ? procfs_file : stdout,
147 "write (PCRESET, %s) %s\n",
0fda6bd2
JM
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:
a5cbe675 155 fprintf (procfs_file ? procfs_file : stdout,
0fda6bd2
JM
156 "write (PCSTRACE) ");
157 proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout,
158 (sigset_t *) &arg[1], 0);
159 break;
160 case PCSFAULT:
a5cbe675 161 fprintf (procfs_file ? procfs_file : stdout,
0fda6bd2
JM
162 "write (PCSFAULT) ");
163 proc_prettyfprint_faultset (procfs_file ? procfs_file : stdout,
164 (fltset_t *) &arg[1], 0);
165 break;
166 case PCSENTRY:
a5cbe675 167 fprintf (procfs_file ? procfs_file : stdout,
0fda6bd2
JM
168 "write (PCSENTRY) ");
169 proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout,
170 (sysset_t *) &arg[1], 0);
171 break;
172 case PCSEXIT:
a5cbe675 173 fprintf (procfs_file ? procfs_file : stdout,
0fda6bd2
JM
174 "write (PCSEXIT) ");
175 proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout,
176 (sysset_t *) &arg[1], 0);
177 break;
178 case PCSHOLD:
a5cbe675 179 fprintf (procfs_file ? procfs_file : stdout,
0fda6bd2
JM
180 "write (PCSHOLD) ");
181 proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout,
182 (sigset_t *) &arg[1], 0);
183 break;
184 case PCSSIG:
a5cbe675 185 fprintf (procfs_file ? procfs_file : stdout,
0fda6bd2
JM
186 "write (PCSSIG) ");
187 proc_prettyfprint_signal (procfs_file ? procfs_file : stdout,
a5cbe675
SM
188 arg[1] ? ((siginfo_t *) &arg[1])->si_signo
189 : 0,
0fda6bd2
JM
190 0);
191 fprintf (procfs_file ? procfs_file : stdout, "\n");
192 break;
193 case PCRUN:
a5cbe675 194 fprintf (procfs_file ? procfs_file : stdout,
0fda6bd2
JM
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 ");
a5cbe675 206
0fda6bd2
JM
207 fprintf (procfs_file ? procfs_file : stdout, "\n");
208 break;
209 case PCKILL:
a5cbe675 210 fprintf (procfs_file ? procfs_file : stdout,
0fda6bd2
JM
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)
a5cbe675
SM
219 fprintf (procfs_file ? procfs_file : stdout,
220 "write (%s) %s\n",
221 rw_table[i].name,
0fda6bd2
JM
222 info_verbose ? rw_table[i].desc : "");
223 else
224 {
225 if (lseek_offset != -1)
a5cbe675
SM
226 fprintf (procfs_file ? procfs_file : stdout,
227 "write (<unknown>, %lud bytes at 0x%08lx) \n",
b943d152 228 (unsigned long) len, (unsigned long) lseek_offset);
0fda6bd2 229 else
a5cbe675
SM
230 fprintf (procfs_file ? procfs_file : stdout,
231 "write (<unknown>, %lud bytes) \n",
b943d152 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 {
a5cbe675 244 fprintf (procfs_file ? procfs_file : stdout,
103b3ef5 245 "[write (%s) FAILED! (%s)]\n",
a5cbe675
SM
246 rw_table[i].name != NULL ?
247 rw_table[i].name : "<unknown>",
103b3ef5 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 {
a5cbe675
SM
268 fprintf (procfs_file ? procfs_file : stdout,
269 "[lseek (0x%08lx) FAILED! (%s)]\n",
103b3ef5 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 288 if (info_verbose)
a5cbe675 289 fprintf (procfs_file ? procfs_file : stdout,
0fda6bd2 290 "%s:%d -- ", file, line);
103b3ef5
MS
291
292 if (errno)
293 {
a5cbe675
SM
294 fprintf (procfs_file ? procfs_file : stdout,
295 "[open FAILED! (%s) line %d]\\n",
103b3ef5
MS
296 safe_strerror (errno), line);
297 }
298 else
299 {
a5cbe675 300 fprintf (procfs_file ? procfs_file : stdout,
103b3ef5
MS
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 329 if (info_verbose)
a5cbe675 330 fprintf (procfs_file ? procfs_file : stdout,
0fda6bd2 331 "%s:%d -- ", file, line);
103b3ef5 332 if (errno)
a5cbe675 333 fprintf (procfs_file ? procfs_file : stdout,
103b3ef5
MS
334 "[close FAILED! (%s)]\n", safe_strerror (errno));
335 else
a5cbe675 336 fprintf (procfs_file ? procfs_file : stdout,
103b3ef5 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 353 if (info_verbose)
a5cbe675 354 fprintf (procfs_file ? procfs_file : stdout,
0fda6bd2 355 "%s:%d -- ", file, line);
a5cbe675 356 fprintf (procfs_file ? procfs_file : stdout,
0fda6bd2
JM
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 365 if (errno)
a5cbe675 366 fprintf (procfs_file ? procfs_file : stdout,
103b3ef5
MS
367 "[wait FAILED! (%s)]\n", safe_strerror (errno));
368 else
a5cbe675 369 fprintf (procfs_file ? procfs_file : stdout,
103b3ef5 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 386 if (info_verbose)
a5cbe675 387 fprintf (procfs_file ? procfs_file : stdout,
0fda6bd2 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
a5cbe675 405 proc_prettyfprint_flags (procfs_file ? procfs_file : stdout,
0fda6bd2
JM
406 flags, 0);
407
408 if (flags & (PR_STOPPED | PR_ISTOP))
a5cbe675 409 proc_prettyfprint_why (procfs_file ? procfs_file : stdout,
0fda6bd2
JM
410 why, what, 0);
411 if (procfs_file)
412 fflush (procfs_file);
413 }
414}
415
5fe70629 416INIT_GDB_FILE (proc_api)
0fda6bd2 417{
54433e38
MK
418 add_setshow_boolean_cmd ("procfs-trace", no_class, &procfs_trace, _("\
419Set tracing for /proc api calls."), _("\
420Show tracing for /proc api calls."), NULL,
5bf193a2
AC
421 set_procfs_trace_cmd,
422 NULL, /* FIXME: i18n: */
423 &setlist, &showlist);
0fda6bd2 424
54433e38
MK
425 add_setshow_filename_cmd ("procfs-file", no_class, &procfs_filename, _("\
426Set filename for /proc tracefile."), _("\
427Show filename for /proc tracefile."), NULL,
f397e303
AC
428 set_procfs_file_cmd,
429 NULL, /* FIXME: i18n: */
430 &setlist, &showlist);
0fda6bd2 431}