]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blame - gdb/proc-api.c
Update year range in copyright notice of all files owned by the GDB project.
[thirdparty/binutils-gdb.git] / gdb / proc-api.c
CommitLineData
0fda6bd2 1/* Machine independent support for SVR4 /proc (process file system) for GDB.
2555fe1a 2
32d0add0 3 Copyright (C) 1999-2015 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
25 * (ioctl or read/write calls).
26 *
27 */
28
29#include "defs.h"
30#include "gdbcmd.h"
8e40d292 31#include "completer.h"
0fda6bd2
JM
32
33#if defined (NEW_PROC_API)
34#define _STRUCTURED_PROC 1
35#endif
36
0fda6bd2
JM
37#include <sys/types.h>
38#include <sys/procfs.h>
8dd72958 39#ifdef HAVE_SYS_PROC_H
0fda6bd2 40#include <sys/proc.h> /* for struct proc */
8dd72958 41#endif
6e8cb14a 42#ifdef HAVE_SYS_USER_H
0fda6bd2 43#include <sys/user.h> /* for struct user */
6e8cb14a 44#endif
0df8b418 45#include <fcntl.h> /* for O_RDWR etc. */
2555fe1a 46#include "gdb_wait.h"
0fda6bd2
JM
47
48#include "proc-utils.h"
49
50/* Much of the information used in the /proc interface, particularly for
51 printing status information, is kept as tables of structures of the
52 following form. These tables can be used to map numeric values to
0df8b418 53 their symbolic names and to a string that describes their specific use. */
0fda6bd2
JM
54
55struct trans {
56 long value; /* The numeric value */
57 char *name; /* The equivalent symbolic value */
58 char *desc; /* Short description of value */
59};
60
103b3ef5 61static int procfs_trace = 0;
0fda6bd2
JM
62static FILE *procfs_file = NULL;
63static char *procfs_filename = "procfs_trace";
64
103b3ef5
MS
65static void
66prepare_to_trace (void)
67{
68 if (procfs_trace) /* if procfs tracing turned on */
69 if (procfs_file == NULL) /* if output file not yet open */
70 if (procfs_filename != NULL) /* if output filename known */
71 procfs_file = fopen (procfs_filename, "a"); /* open output file */
72}
73
0fda6bd2 74static void
fba45db2 75set_procfs_trace_cmd (char *args, int from_tty, struct cmd_list_element *c)
0fda6bd2
JM
76{
77#if 0 /* not sure what I might actually need to do here, if anything */
78 if (procfs_file)
79 fflush (procfs_file);
80#endif
81}
82
83static void
fba45db2 84set_procfs_file_cmd (char *args, int from_tty, struct cmd_list_element *c)
0fda6bd2
JM
85{
86 /* Just changed the filename for procfs tracing.
87 If a file was already open, close it. */
88 if (procfs_file)
89 fclose (procfs_file);
90 procfs_file = NULL;
91}
92
93
94#ifndef NEW_PROC_API
95
96static struct trans ioctl_table[] = {
97#ifdef PIOCACINFO /* irix */
98 { PIOCACINFO, "PIOCACINFO", "get process account info" },
99#endif
100 { PIOCACTION, "PIOCACTION", "get signal action structs" },
101#ifdef PIOCARGUMENTS /* osf */
102 { PIOCARGUMENTS, "PIOCARGUMENTS", "command line args" },
103#endif
104#ifdef PIOCAUXV /* solaris aux vectors */
105 { PIOCAUXV, "PIOCAUXV", "get aux vector" },
106 { PIOCNAUXV, "PIOCNAUXV", "get number of aux vector entries" },
107#endif /* AUXV */
108 { PIOCCFAULT, "PIOCCFAULT", "clear current fault" },
109 { PIOCCRED, "PIOCCRED", "get process credentials" },
110#ifdef PIOCENEVCTRS /* irix event counters */
111 { PIOCENEVCTRS, "PIOCENEVCTRS", "acquire and start event counters" },
112 { PIOCGETEVCTRL, "PIOCGETEVCTRL", "get control info of event counters" },
113 { PIOCGETEVCTRS, "PIOCGETEVCTRS", "dump event counters" },
114 { PIOCGETPREVCTRS, "PIOCGETPREVCTRS", "dump event counters & prusage info" },
115 { PIOCRELEVCTRS, "PIOCRELEVCTRS", "release/stop event counters" },
116 { PIOCSETEVCTRL, "PIOCSETEVCTRL", "set control info of event counters" },
117 { PIOCGETPTIMER, "PIOCGETPTIMER", "get process timers" },
118#endif /* irix event counters */
119 { PIOCGENTRY, "PIOCGENTRY", "get traced syscall entry set" },
6e8cb14a 120#if defined (PIOCGETPR)
0fda6bd2 121 { PIOCGETPR, "PIOCGETPR", "read struct proc" },
6e8cb14a
AC
122#endif
123#if defined (PIOCGETU)
0fda6bd2 124 { PIOCGETU, "PIOCGETU", "read user area" },
6e8cb14a 125#endif
0fda6bd2
JM
126#if defined (PIOCGETUTK) && (defined(KERNEL) || defined(SHOW_UTT)) /* osf */
127 { PIOCGETUTK, "PIOCGETUTK", "get the utask struct" },
128#endif
129 { PIOCGEXIT, "PIOCGEXIT", "get traced syscall exit set" },
130 { PIOCGFAULT, "PIOCGFAULT", "get traced fault set" },
131#ifdef PIOCGFPCR /* osf */
132 { PIOCGFPCR, "PIOCGFPCR", "get FP control register" },
133 { PIOCSFPCR, "PIOCSFPCR", "set FP conrtol register" },
134#endif
135 { PIOCGFPREG, "PIOCGFPREG", "get floating point registers" },
136 { PIOCGHOLD, "PIOCGHOLD", "get held signal set" },
137 { PIOCGREG, "PIOCGREG", "get general registers" },
138 { PIOCGROUPS, "PIOCGROUPS", "get supplementary groups" },
139#ifdef PIOCGSPCACT /* osf */
140 { PIOCGSPCACT, "PIOCGSPCACT", "get special action" },
141 { PIOCSSPCACT, "PIOCSSPCACT", "set special action" },
142#endif
143 { PIOCGTRACE, "PIOCGTRACE", "get traced signal set" },
144#ifdef PIOCGWATCH /* irix watchpoints */
145 { PIOCGWATCH, "PIOCGWATCH", "get watchpoint" },
146 { PIOCSWATCH, "PIOCSWATCH", "set watchpoint" },
147 { PIOCNWATCH, "PIOCNWATCH", "get number of watchpoints" },
148#endif /* irix watchpoints */
149#ifdef PIOCGWIN /* solaris sparc */
150 { PIOCGWIN, "PIOCGWIN", "get gwindows_t" },
151#endif
152#ifdef PIOCGXREG /* solaris sparc extra regs */
153 { PIOCGXREGSIZE, "PIOCXREGSIZE", "get extra register state size" },
154 { PIOCGXREG, "PIOCGXREG", "get extra register state" },
155 { PIOCSXREG, "PIOCSXREG", "set extra register state" },
156#endif /* XREG */
157 { PIOCKILL, "PIOCKILL", "send signal" },
158#ifdef PIOCLDT /* solaris i386 */
159 { PIOCLDT, "PIOCLDT", "get LDT" },
160 { PIOCNLDT, "PIOCNLDT", "get number of LDT entries" },
161#endif
05b4bd79 162#ifdef PIOCLSTATUS /* solaris */
0fda6bd2
JM
163 { PIOCLSTATUS, "PIOCLSTATUS", "get status of all lwps" },
164 { PIOCLUSAGE, "PIOCLUSAGE", "get resource usage of all lwps" },
165 { PIOCOPENLWP, "PIOCOPENLWP", "get lwp file descriptor" },
166 { PIOCLWPIDS, "PIOCLWPIDS", "get lwp identifiers" },
167#endif /* LWP */
168 { PIOCMAP, "PIOCMAP", "get memory map information" },
169 { PIOCMAXSIG, "PIOCMAXSIG", "get max signal number" },
170 { PIOCNICE, "PIOCNICE", "set nice priority" },
171 { PIOCNMAP, "PIOCNMAP", "get number of memory mappings" },
172 { PIOCOPENM, "PIOCOPENM", "open mapped object for reading" },
173#ifdef PIOCOPENMOBS /* osf */
174 { PIOCOPENMOBS, "PIOCOPENMOBS", "open mapped object" },
175#endif
176#ifdef PIOCOPENPD /* solaris */
177 { PIOCOPENPD, "PIOCOPENPD", "get page data file descriptor" },
178#endif
179 { PIOCPSINFO, "PIOCPSINFO", "get ps(1) information" },
180 { PIOCRESET, "PIOCRESET", "reset process flags" },
181 { PIOCRFORK, "PIOCRFORK", "reset inherit-on-fork flag" },
182 { PIOCRRLC, "PIOCRRLC", "reset run-on-last-close flag" },
183 { PIOCRUN, "PIOCRUN", "make process runnable" },
184#ifdef PIOCSAVECCNTRS /* irix */
185 { PIOCSAVECCNTRS, "PIOCSAVECCNTRS", "parent gets child cntrs" },
186#endif
187 { PIOCSENTRY, "PIOCSENTRY", "set traced syscall entry set" },
188 { PIOCSET, "PIOCSET", "set process flags" },
189 { PIOCSEXIT, "PIOCSEXIT", "set traced syscall exit set" },
190 { PIOCSFAULT, "PIOCSFAULT", "set traced fault set" },
191 { PIOCSFORK, "PIOCSFORK", "set inherit-on-fork flag" },
192 { PIOCSFPREG, "PIOCSFPREG", "set floating point registers" },
193 { PIOCSHOLD, "PIOCSHOLD", "set held signal set" },
194 { PIOCSREG, "PIOCSREG", "set general registers" },
195 { PIOCSRLC, "PIOCSRLC", "set run-on-last-close flag" },
196 { PIOCSSIG, "PIOCSSIG", "set current signal" },
197 { PIOCSTATUS, "PIOCSTATUS", "get process status" },
198 { PIOCSTOP, "PIOCSTOP", "post stop request" },
199 { PIOCSTRACE, "PIOCSTRACE", "set traced signal set" },
200 { PIOCUNKILL, "PIOCUNKILL", "delete a signal" },
201#ifdef PIOCUSAGE /* solaris */
202 { PIOCUSAGE, "PIOCUSAGE", "get resource usage" },
203#endif
204 { PIOCWSTOP, "PIOCWSTOP", "wait for process to stop" },
205
206#ifdef PIOCNTHR /* osf threads */
207 { PIOCNTHR, "PIOCNTHR", "get thread count" },
208 { PIOCRTINH, "PIOCRTINH", "reset inherit-on-thread-creation" },
209 { PIOCSTINH, "PIOCSTINH", "set inherit-on-thread-creation" },
210 { PIOCTLIST, "PIOCTLIST", "get thread ids" },
211 { PIOCXPTH, "PIOCXPTH", "translate port to thread handle" },
212 { PIOCTRUN, "PIOCTRUN", "make thread runnable" },
213 { PIOCTSTATUS, "PIOCTSTATUS", "get thread status" },
214 { PIOCTSTOP, "PIOCTSTOP", "stop a thread" },
215 /* ... TGTRACE TSTRACE TSSIG TKILL TUNKILL TCFAULT TGFAULT TSFAULT
216 TGFPREG TSFPREG TGREG TSREG TACTION TTERM TABRUN TGENTRY TSENTRY
217 TGEXIT TSEXIT TSHOLD ... thread functions */
218#endif /* osf threads */
219 { -1, NULL, NULL }
220};
221
222int
fba45db2 223ioctl_with_trace (int fd, long opcode, void *ptr, char *file, int line)
0fda6bd2 224{
8e40d292
EZ
225 int i = 0;
226 int ret;
227 int arg1;
0fda6bd2 228
103b3ef5
MS
229 prepare_to_trace ();
230
0fda6bd2
JM
231 if (procfs_trace)
232 {
0fda6bd2
JM
233 for (i = 0; ioctl_table[i].name != NULL; i++)
234 if (ioctl_table[i].value == opcode)
235 break;
236
237 if (info_verbose)
238 fprintf (procfs_file ? procfs_file : stdout,
239 "%s:%d -- ", file, line);
240 switch (opcode) {
241 case PIOCSET:
242 arg1 = ptr ? *(long *) ptr : 0;
243 fprintf (procfs_file ? procfs_file : stdout,
244 "ioctl (PIOCSET, %s) %s\n",
245 arg1 == PR_FORK ? "PR_FORK" :
246 arg1 == PR_RLC ? "PR_RLC" :
247#ifdef PR_ASYNC
248 arg1 == PR_ASYNC ? "PR_ASYNC" :
249#endif
250 "<unknown flag>",
251 info_verbose ? ioctl_table[i].desc : "");
252 break;
253 case PIOCRESET:
254 arg1 = ptr ? *(long *) ptr : 0;
255 fprintf (procfs_file ? procfs_file : stdout,
256 "ioctl (PIOCRESET, %s) %s\n",
257 arg1 == PR_FORK ? "PR_FORK" :
258 arg1 == PR_RLC ? "PR_RLC" :
259#ifdef PR_ASYNC
260 arg1 == PR_ASYNC ? "PR_ASYNC" :
261#endif
262 "<unknown flag>",
263 info_verbose ? ioctl_table[i].desc : "");
264 break;
265 case PIOCSTRACE:
266 fprintf (procfs_file ? procfs_file : stdout,
267 "ioctl (PIOCSTRACE) ");
268 proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout,
269 (sigset_t *) ptr, 0);
270 break;
271 case PIOCSFAULT:
272 fprintf (procfs_file ? procfs_file : stdout,
273 "ioctl (%s) ",
274 opcode == PIOCSFAULT ? "PIOCSFAULT" : "PIOCGFAULT");
275 proc_prettyfprint_faultset (procfs_file ? procfs_file : stdout,
276 (fltset_t *) ptr, 0);
277 break;
278 case PIOCSENTRY:
279 fprintf (procfs_file ? procfs_file : stdout,
280 "ioctl (%s) ",
281 opcode == PIOCSENTRY ? "PIOCSENTRY" : "PIOCGENTRY");
282 proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout,
283 (sysset_t *) ptr, 0);
284 break;
285 case PIOCSEXIT:
286 fprintf (procfs_file ? procfs_file : stdout,
287 "ioctl (%s) ",
288 opcode == PIOCSEXIT ? "PIOCSEXIT" : "PIOCGEXIT");
289 proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout,
290 (sysset_t *) ptr, 0);
291 break;
292 case PIOCSHOLD:
293 fprintf (procfs_file ? procfs_file : stdout,
294 "ioctl (%s) ",
295 opcode == PIOCSHOLD ? "PIOCSHOLD" : "PIOCGHOLD");
296 proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout,
297 (sigset_t *) ptr, 0);
298 break;
299 case PIOCSSIG:
300 fprintf (procfs_file ? procfs_file : stdout,
301 "ioctl (PIOCSSIG) ");
302 proc_prettyfprint_signal (procfs_file ? procfs_file : stdout,
303 ptr ? ((siginfo_t *) ptr)->si_signo : 0,
304 0);
305 fprintf (procfs_file ? procfs_file : stdout, "\n");
306 break;
307 case PIOCRUN:
308 fprintf (procfs_file ? procfs_file : stdout,
309 "ioctl (PIOCRUN) ");
310
311 arg1 = ptr ? *(long *) ptr : 0;
312 if (arg1 & PRCSIG)
313 fprintf (procfs_file ? procfs_file : stdout, "clearSig ");
314 if (arg1 & PRCFAULT)
315 fprintf (procfs_file ? procfs_file : stdout, "clearFlt ");
316 if (arg1 & PRSTRACE)
317 fprintf (procfs_file ? procfs_file : stdout, "setTrace ");
318 if (arg1 & PRSHOLD)
319 fprintf (procfs_file ? procfs_file : stdout, "setHold ");
320 if (arg1 & PRSFAULT)
321 fprintf (procfs_file ? procfs_file : stdout, "setFlt ");
322 if (arg1 & PRSVADDR)
323 fprintf (procfs_file ? procfs_file : stdout, "setVaddr ");
324 if (arg1 & PRSTEP)
325 fprintf (procfs_file ? procfs_file : stdout, "step ");
326 if (arg1 & PRSABORT)
327 fprintf (procfs_file ? procfs_file : stdout, "syscallAbort ");
328 if (arg1 & PRSTOP)
329 fprintf (procfs_file ? procfs_file : stdout, "stopReq ");
330
331 fprintf (procfs_file ? procfs_file : stdout, "\n");
332 break;
333 case PIOCKILL:
334 fprintf (procfs_file ? procfs_file : stdout,
335 "ioctl (PIOCKILL) ");
336 proc_prettyfprint_signal (procfs_file ? procfs_file : stdout,
337 ptr ? *(long *) ptr : 0, 0);
338 fprintf (procfs_file ? procfs_file : stdout, "\n");
339 break;
340#ifdef PIOCSSPCACT
341 case PIOCSSPCACT:
342 fprintf (procfs_file ? procfs_file : stdout,
343 "ioctl (PIOCSSPCACT) ");
344 arg1 = ptr ? *(long *) ptr : 0;
345 if (arg1 & PRFS_STOPFORK)
346 fprintf (procfs_file ? procfs_file : stdout, "stopFork ");
347 if (arg1 & PRFS_STOPEXEC)
348 fprintf (procfs_file ? procfs_file : stdout, "stopExec ");
349 if (arg1 & PRFS_STOPTERM)
350 fprintf (procfs_file ? procfs_file : stdout, "stopTerm ");
351 if (arg1 & PRFS_STOPTCR)
352 fprintf (procfs_file ? procfs_file : stdout, "stopThreadCreate ");
353 if (arg1 & PRFS_STOPTTERM)
354 fprintf (procfs_file ? procfs_file : stdout, "stopThreadTerm ");
355 if (arg1 & PRFS_KOLC)
356 fprintf (procfs_file ? procfs_file : stdout, "killOnLastClose ");
357 fprintf (procfs_file ? procfs_file : stdout, "\n");
358 break;
359#endif /* PIOCSSPCACT */
360 default:
361 if (ioctl_table[i].name)
362 fprintf (procfs_file ? procfs_file : stdout,
363 "ioctl (%s) %s\n",
364 ioctl_table[i].name,
365 info_verbose ? ioctl_table[i].desc : "");
366 else
367 fprintf (procfs_file ? procfs_file : stdout,
368 "ioctl (<unknown %ld (0x%lx)) \n", opcode, opcode);
369 break;
370 }
371 if (procfs_file)
372 fflush (procfs_file);
373 }
103b3ef5 374 errno = 0;
0fda6bd2
JM
375 ret = ioctl (fd, opcode, ptr);
376 if (procfs_trace && ret < 0)
377 {
378 fprintf (procfs_file ? procfs_file : stdout,
103b3ef5 379 "[ioctl (%s) FAILED! (%s)]\n",
0fda6bd2 380 ioctl_table[i].name != NULL ?
103b3ef5
MS
381 ioctl_table[i].name : "<unknown>",
382 safe_strerror (errno));
0fda6bd2
JM
383 if (procfs_file)
384 fflush (procfs_file);
385 }
386
387 return ret;
388}
389
390#else /* NEW_PROC_API */
391
392static struct trans rw_table[] = {
393#ifdef PCAGENT /* solaris */
394 { PCAGENT, "PCAGENT", "create agent lwp with regs from argument" },
395#endif
396 { PCCFAULT, "PCCFAULT", "clear current fault" },
397#ifdef PCCSIG /* solaris */
398 { PCCSIG, "PCCSIG", "clear current signal" },
399#endif
640b227f 400#ifdef PCDSTOP /* solaris */
0fda6bd2 401 { PCDSTOP, "PCDSTOP", "post stop request" },
640b227f 402#endif
0fda6bd2 403 { PCKILL, "PCKILL", "post a signal" },
640b227f 404#ifdef PCNICE /* solaris */
0fda6bd2 405 { PCNICE, "PCNICE", "set nice priority" },
640b227f 406#endif
0fda6bd2
JM
407#ifdef PCREAD /* solaris */
408 { PCREAD, "PCREAD", "read from the address space" },
409 { PCWRITE, "PCWRITE", "write to the address space" },
0fda6bd2
JM
410#endif
411 { PCRUN, "PCRUN", "make process/lwp runnable" },
412#ifdef PCSASRS /* solaris 2.7 only */
413 { PCSASRS, "PCSASRS", "set ancillary state registers" },
414#endif
415#ifdef PCSCRED /* solaris */
416 { PCSCRED, "PCSCRED", "set process credentials" },
417#endif
418 { PCSENTRY, "PCSENTRY", "set traced syscall entry set" },
419 { PCSET, "PCSET", "set modes" },
420 { PCSEXIT, "PCSEXIT", "set traced syscall exit set" },
421 { PCSFAULT, "PCSFAULT", "set traced fault set" },
422 { PCSFPREG, "PCSFPREG", "set floating point registers" },
151fefe2 423#ifdef PCSHOLD /* solaris */
0fda6bd2 424 { PCSHOLD, "PCSHOLD", "set signal mask" },
640b227f 425#endif
0fda6bd2
JM
426 { PCSREG, "PCSREG", "set general registers" },
427 { PCSSIG, "PCSSIG", "set current signal" },
428 { PCSTOP, "PCSTOP", "post stop request and wait" },
429 { PCSTRACE, "PCSTRACE", "set traced signal set" },
430#ifdef PCSVADDR /* solaris */
431 { PCSVADDR, "PCSVADDR", "set pc virtual address" },
432#endif
433#ifdef PCSXREG /* solaris sparc only */
434 { PCSXREG, "PCSXREG", "set extra registers" },
435#endif
436#ifdef PCTWSTOP /* solaris */
437 { PCTWSTOP, "PCTWSTOP", "wait for stop, with timeout arg" },
438#endif
640b227f 439#ifdef PCUNKILL /* solaris */
0fda6bd2 440 { PCUNKILL, "PCUNKILL", "delete a pending signal" },
640b227f 441#endif
0fda6bd2
JM
442#ifdef PCUNSET /* solaris */
443 { PCUNSET, "PCUNSET", "unset modes" },
444#endif
445#ifdef PCWATCH /* solaris */
446 { PCWATCH, "PCWATCH", "set/unset watched memory area" },
447#endif
448 { PCWSTOP, "PCWSTOP", "wait for process/lwp to stop, no timeout" },
449 { 0, NULL, NULL }
450};
451
452static off_t lseek_offset;
453
454int
fba45db2 455write_with_trace (int fd, void *varg, size_t len, char *file, int line)
0fda6bd2 456{
1e52e2eb 457 int i = ARRAY_SIZE (rw_table) - 1;
0fda6bd2 458 int ret;
37de36c6 459 procfs_ctl_t *arg = (procfs_ctl_t *) varg;
0fda6bd2 460
103b3ef5 461 prepare_to_trace ();
0fda6bd2
JM
462 if (procfs_trace)
463 {
37de36c6 464 procfs_ctl_t opcode = arg[0];
0fda6bd2
JM
465 for (i = 0; rw_table[i].name != NULL; i++)
466 if (rw_table[i].value == opcode)
467 break;
468
469 if (info_verbose)
470 fprintf (procfs_file ? procfs_file : stdout,
471 "%s:%d -- ", file, line);
472 switch (opcode) {
473 case PCSET:
474 fprintf (procfs_file ? procfs_file : stdout,
475 "write (PCSET, %s) %s\n",
476 arg[1] == PR_FORK ? "PR_FORK" :
477 arg[1] == PR_RLC ? "PR_RLC" :
478#ifdef PR_ASYNC
479 arg[1] == PR_ASYNC ? "PR_ASYNC" :
480#endif
481 "<unknown flag>",
482 info_verbose ? rw_table[i].desc : "");
483 break;
484#ifdef PCUNSET
485 case PCUNSET:
486#endif
487#ifdef PCRESET
37de36c6 488#if PCRESET != PCUNSET
0fda6bd2 489 case PCRESET:
37de36c6 490#endif
0fda6bd2
JM
491#endif
492 fprintf (procfs_file ? procfs_file : stdout,
493 "write (PCRESET, %s) %s\n",
494 arg[1] == PR_FORK ? "PR_FORK" :
495 arg[1] == PR_RLC ? "PR_RLC" :
496#ifdef PR_ASYNC
497 arg[1] == PR_ASYNC ? "PR_ASYNC" :
498#endif
499 "<unknown flag>",
500 info_verbose ? rw_table[i].desc : "");
501 break;
502 case PCSTRACE:
503 fprintf (procfs_file ? procfs_file : stdout,
504 "write (PCSTRACE) ");
505 proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout,
506 (sigset_t *) &arg[1], 0);
507 break;
508 case PCSFAULT:
509 fprintf (procfs_file ? procfs_file : stdout,
510 "write (PCSFAULT) ");
511 proc_prettyfprint_faultset (procfs_file ? procfs_file : stdout,
512 (fltset_t *) &arg[1], 0);
513 break;
514 case PCSENTRY:
515 fprintf (procfs_file ? procfs_file : stdout,
516 "write (PCSENTRY) ");
517 proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout,
518 (sysset_t *) &arg[1], 0);
519 break;
520 case PCSEXIT:
521 fprintf (procfs_file ? procfs_file : stdout,
522 "write (PCSEXIT) ");
523 proc_prettyfprint_syscalls (procfs_file ? procfs_file : stdout,
524 (sysset_t *) &arg[1], 0);
525 break;
640b227f 526#ifdef PCSHOLD
0fda6bd2
JM
527 case PCSHOLD:
528 fprintf (procfs_file ? procfs_file : stdout,
529 "write (PCSHOLD) ");
530 proc_prettyfprint_signalset (procfs_file ? procfs_file : stdout,
531 (sigset_t *) &arg[1], 0);
532 break;
640b227f 533#endif
0fda6bd2
JM
534 case PCSSIG:
535 fprintf (procfs_file ? procfs_file : stdout,
536 "write (PCSSIG) ");
537 proc_prettyfprint_signal (procfs_file ? procfs_file : stdout,
538 arg[1] ? ((siginfo_t *) &arg[1])->si_signo
539 : 0,
540 0);
541 fprintf (procfs_file ? procfs_file : stdout, "\n");
542 break;
543 case PCRUN:
544 fprintf (procfs_file ? procfs_file : stdout,
545 "write (PCRUN) ");
546 if (arg[1] & PRCSIG)
547 fprintf (procfs_file ? procfs_file : stdout, "clearSig ");
548 if (arg[1] & PRCFAULT)
549 fprintf (procfs_file ? procfs_file : stdout, "clearFlt ");
550 if (arg[1] & PRSTEP)
551 fprintf (procfs_file ? procfs_file : stdout, "step ");
640b227f 552#ifdef PRSABORT
0fda6bd2
JM
553 if (arg[1] & PRSABORT)
554 fprintf (procfs_file ? procfs_file : stdout, "syscallAbort ");
640b227f
JB
555#endif
556#ifdef PRSTOP
0fda6bd2
JM
557 if (arg[1] & PRSTOP)
558 fprintf (procfs_file ? procfs_file : stdout, "stopReq ");
640b227f 559#endif
0fda6bd2
JM
560
561 fprintf (procfs_file ? procfs_file : stdout, "\n");
562 break;
563 case PCKILL:
564 fprintf (procfs_file ? procfs_file : stdout,
565 "write (PCKILL) ");
566 proc_prettyfprint_signal (procfs_file ? procfs_file : stdout,
567 arg[1], 0);
568 fprintf (procfs_file ? procfs_file : stdout, "\n");
569 break;
570 default:
571 {
37de36c6 572 if (rw_table[i].name)
0fda6bd2
JM
573 fprintf (procfs_file ? procfs_file : stdout,
574 "write (%s) %s\n",
575 rw_table[i].name,
576 info_verbose ? rw_table[i].desc : "");
577 else
578 {
579 if (lseek_offset != -1)
580 fprintf (procfs_file ? procfs_file : stdout,
b943d152
MS
581 "write (<unknown>, %lud bytes at 0x%08lx) \n",
582 (unsigned long) len, (unsigned long) lseek_offset);
0fda6bd2
JM
583 else
584 fprintf (procfs_file ? procfs_file : stdout,
b943d152
MS
585 "write (<unknown>, %lud bytes) \n",
586 (unsigned long) len);
0fda6bd2
JM
587 }
588 break;
589 }
590 }
591 if (procfs_file)
592 fflush (procfs_file);
593 }
103b3ef5 594 errno = 0;
b943d152 595 ret = write (fd, (void *) arg, len);
0fda6bd2
JM
596 if (procfs_trace && ret != len)
597 {
598 fprintf (procfs_file ? procfs_file : stdout,
103b3ef5 599 "[write (%s) FAILED! (%s)]\n",
0fda6bd2 600 rw_table[i].name != NULL ?
103b3ef5
MS
601 rw_table[i].name : "<unknown>",
602 safe_strerror (errno));
0fda6bd2
JM
603 if (procfs_file)
604 fflush (procfs_file);
605 }
606
607 lseek_offset = -1;
608 return ret;
609}
610
611off_t
fba45db2 612lseek_with_trace (int fd, off_t offset, int whence, char *file, int line)
0fda6bd2
JM
613{
614 off_t ret;
615
103b3ef5
MS
616 prepare_to_trace ();
617 errno = 0;
0fda6bd2
JM
618 ret = lseek (fd, offset, whence);
619 lseek_offset = ret;
103b3ef5 620 if (procfs_trace && (ret == -1 || errno != 0))
0fda6bd2 621 {
0fda6bd2 622 fprintf (procfs_file ? procfs_file : stdout,
103b3ef5
MS
623 "[lseek (0x%08lx) FAILED! (%s)]\n",
624 (unsigned long) offset, safe_strerror (errno));
0fda6bd2
JM
625 if (procfs_file)
626 fflush (procfs_file);
627 }
628
629 return ret;
630}
631
632#endif /* NEW_PROC_API */
633
634int
fba45db2 635open_with_trace (char *filename, int mode, char *file, int line)
0fda6bd2 636{
103b3ef5 637 int ret;
0fda6bd2 638
103b3ef5
MS
639 prepare_to_trace ();
640 errno = 0;
641 ret = open (filename, mode);
0fda6bd2
JM
642 if (procfs_trace)
643 {
0fda6bd2
JM
644 if (info_verbose)
645 fprintf (procfs_file ? procfs_file : stdout,
646 "%s:%d -- ", file, line);
103b3ef5
MS
647
648 if (errno)
649 {
650 fprintf (procfs_file ? procfs_file : stdout,
651 "[open FAILED! (%s) line %d]\\n",
652 safe_strerror (errno), line);
653 }
654 else
655 {
656 fprintf (procfs_file ? procfs_file : stdout,
657 "%d = open (%s, ", ret, filename);
658 if (mode == O_RDONLY)
659 fprintf (procfs_file ? procfs_file : stdout, "O_RDONLY) %d\n",
660 line);
661 else if (mode == O_WRONLY)
662 fprintf (procfs_file ? procfs_file : stdout, "O_WRONLY) %d\n",
663 line);
664 else if (mode == O_RDWR)
665 fprintf (procfs_file ? procfs_file : stdout, "O_RDWR) %d\n",
666 line);
667 }
0fda6bd2
JM
668 if (procfs_file)
669 fflush (procfs_file);
670 }
671
672 return ret;
673}
674
675int
fba45db2 676close_with_trace (int fd, char *file, int line)
0fda6bd2 677{
103b3ef5 678 int ret;
0fda6bd2 679
103b3ef5
MS
680 prepare_to_trace ();
681 errno = 0;
682 ret = close (fd);
0fda6bd2
JM
683 if (procfs_trace)
684 {
0fda6bd2
JM
685 if (info_verbose)
686 fprintf (procfs_file ? procfs_file : stdout,
687 "%s:%d -- ", file, line);
103b3ef5
MS
688 if (errno)
689 fprintf (procfs_file ? procfs_file : stdout,
690 "[close FAILED! (%s)]\n", safe_strerror (errno));
691 else
692 fprintf (procfs_file ? procfs_file : stdout,
693 "%d = close (%d)\n", ret, fd);
0fda6bd2
JM
694 if (procfs_file)
695 fflush (procfs_file);
696 }
697
698 return ret;
699}
700
103b3ef5 701pid_t
fba45db2 702wait_with_trace (int *wstat, char *file, int line)
0fda6bd2
JM
703{
704 int ret, lstat = 0;
705
103b3ef5 706 prepare_to_trace ();
0fda6bd2
JM
707 if (procfs_trace)
708 {
0fda6bd2
JM
709 if (info_verbose)
710 fprintf (procfs_file ? procfs_file : stdout,
711 "%s:%d -- ", file, line);
712 fprintf (procfs_file ? procfs_file : stdout,
713 "wait (line %d) ", line);
714 if (procfs_file)
715 fflush (procfs_file);
716 }
103b3ef5 717 errno = 0;
0fda6bd2
JM
718 ret = wait (&lstat);
719 if (procfs_trace)
720 {
103b3ef5
MS
721 if (errno)
722 fprintf (procfs_file ? procfs_file : stdout,
723 "[wait FAILED! (%s)]\n", safe_strerror (errno));
724 else
725 fprintf (procfs_file ? procfs_file : stdout,
726 "returned pid %d, status 0x%x\n", ret, lstat);
0fda6bd2
JM
727 if (procfs_file)
728 fflush (procfs_file);
729 }
730 if (wstat)
731 *wstat = lstat;
732
733 return ret;
734}
735
736void
fba45db2 737procfs_note (char *msg, char *file, int line)
0fda6bd2 738{
103b3ef5 739 prepare_to_trace ();
0fda6bd2
JM
740 if (procfs_trace)
741 {
0fda6bd2
JM
742 if (info_verbose)
743 fprintf (procfs_file ? procfs_file : stdout,
744 "%s:%d -- ", file, line);
e34e1a85 745 fprintf (procfs_file ? procfs_file : stdout, "%s", msg);
0fda6bd2
JM
746 if (procfs_file)
747 fflush (procfs_file);
748 }
749}
750
751void
fba45db2 752proc_prettyfprint_status (long flags, int why, int what, int thread)
0fda6bd2 753{
103b3ef5 754 prepare_to_trace ();
0fda6bd2
JM
755 if (procfs_trace)
756 {
0fda6bd2
JM
757 if (thread)
758 fprintf (procfs_file ? procfs_file : stdout,
759 "Thread %d: ", thread);
760
761 proc_prettyfprint_flags (procfs_file ? procfs_file : stdout,
762 flags, 0);
763
764 if (flags & (PR_STOPPED | PR_ISTOP))
765 proc_prettyfprint_why (procfs_file ? procfs_file : stdout,
766 why, what, 0);
767 if (procfs_file)
768 fflush (procfs_file);
769 }
770}
771
772
a0911fd0
MR
773/* Provide a prototype to silence -Wmissing-prototypes. */
774extern void _initialize_proc_api (void);
775
0fda6bd2 776void
fba45db2 777_initialize_proc_api (void)
0fda6bd2
JM
778{
779 struct cmd_list_element *c;
780
54433e38
MK
781 add_setshow_boolean_cmd ("procfs-trace", no_class, &procfs_trace, _("\
782Set tracing for /proc api calls."), _("\
783Show tracing for /proc api calls."), NULL,
5bf193a2
AC
784 set_procfs_trace_cmd,
785 NULL, /* FIXME: i18n: */
786 &setlist, &showlist);
0fda6bd2 787
54433e38
MK
788 add_setshow_filename_cmd ("procfs-file", no_class, &procfs_filename, _("\
789Set filename for /proc tracefile."), _("\
790Show filename for /proc tracefile."), NULL,
f397e303
AC
791 set_procfs_file_cmd,
792 NULL, /* FIXME: i18n: */
793 &setlist, &showlist);
0fda6bd2 794}