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