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