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