]> granicus.if.org Git - strace/blob - process.c
Add capability for Linux to change a vfork call into plain fork, which
[strace] / process.c
1 /*
2  * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3  * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4  * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  *
29  *      $Id$
30  */
31
32 #include "defs.h"
33
34 #include <fcntl.h>
35 #include <sys/stat.h>
36 #include <sys/time.h>
37 #include <sys/wait.h>
38 #include <sys/resource.h>
39 #include <sys/utsname.h>
40 #include <sys/user.h>
41 #include <sys/syscall.h>
42 #include <signal.h>
43 #ifdef SUNOS4
44 #include <machine/reg.h>
45 #endif /* SUNOS4 */
46
47 #if __GLIBC__ == 2 && __GLIBC_MINOR__ >= 1 && (defined(I386) || defined(M68K))
48 # include <sys/reg.h>
49 # define PTRACE_PEEKUSR PTRACE_PEEKUSER
50 # define PTRACE_POKEUSR PTRACE_POKEUSER
51 #endif
52
53 #ifdef LINUX
54 #include <linux/ptrace.h>
55 #endif /* LINUX */
56
57 #ifdef HAVE_PRCTL
58 #include <sys/prctl.h>
59 #endif
60
61 #ifndef WCOREDUMP
62 #define WCOREDUMP(status) ((status) & 0200)
63 #endif
64
65 /* WTA: this has `&& !defined(LINUXSPARC)', this seems unneeded though? */
66 #if defined(HAVE_PRCTL)
67 static struct xlat prctl_options[] = {
68 #ifdef PR_MAXPROCS
69         { PR_MAXPROCS,          "PR_MAXPROCS"           },
70 #endif
71 #ifdef PR_ISBLOCKED
72         { PR_ISBLOCKED,         "PR_ISBLOCKED"          },
73 #endif
74 #ifdef PR_SETSTACKSIZE
75         { PR_SETSTACKSIZE,      "PR_SETSTACKSIZE"       },
76 #endif
77 #ifdef PR_GETSTACKSIZE
78         { PR_GETSTACKSIZE,      "PR_GETSTACKSIZE"       },
79 #endif
80 #ifdef PR_MAXPPROCS
81         { PR_MAXPPROCS,         "PR_MAXPPROCS"          },
82 #endif
83 #ifdef PR_UNBLKONEXEC
84         { PR_UNBLKONEXEC,       "PR_UNBLKONEXEC"        },
85 #endif
86 #ifdef PR_ATOMICSIM
87         { PR_ATOMICSIM,         "PR_ATOMICSIM"          },
88 #endif
89 #ifdef PR_SETEXITSIG
90         { PR_SETEXITSIG,        "PR_SETEXITSIG"         },
91 #endif
92 #ifdef PR_RESIDENT
93         { PR_RESIDENT,          "PR_RESIDENT"           },
94 #endif
95 #ifdef PR_ATTACHADDR
96         { PR_ATTACHADDR,        "PR_ATTACHADDR"         },
97 #endif
98 #ifdef PR_DETACHADDR
99         { PR_DETACHADDR,        "PR_DETACHADDR"         },
100 #endif
101 #ifdef PR_TERMCHILD
102         { PR_TERMCHILD,         "PR_TERMCHILD"          },
103 #endif
104 #ifdef PR_GETSHMASK
105         { PR_GETSHMASK,         "PR_GETSHMASK"          },
106 #endif
107 #ifdef PR_GETNSHARE
108         { PR_GETNSHARE,         "PR_GETNSHARE"          },
109 #endif
110 #if defined(PR_SET_PDEATHSIG)
111         { PR_SET_PDEATHSIG,     "PR_SET_PDEATHSIG"      },
112 #endif
113         { 0,                    NULL                    },
114 };
115
116 int
117 sys_prctl(tcp)
118 struct tcb *tcp;
119 {
120         int i;
121
122         if (entering(tcp)) {
123                 printxval(prctl_options, tcp->u_arg[0], "PR_???");
124                 switch (tcp->u_arg[0]) {
125 #ifdef PR_GETNSHARE
126                 case PR_GETNSHARE:
127                         break;
128 #endif
129                 default:
130                         for (i = 1; i < tcp->u_nargs; i++)
131                                 tprintf(", %#lx", tcp->u_arg[i]);
132                         break;
133                 }
134         }
135         return 0;
136 }
137
138 #endif /* HAVE_PRCTL */
139
140 int
141 sys_gethostid(tcp)
142 struct tcb *tcp;
143 {
144         if (exiting(tcp))
145                 return RVAL_HEX;
146         return 0;
147 }
148
149 int
150 sys_sethostname(tcp)
151 struct tcb *tcp;
152 {
153         if (entering(tcp)) {
154                 printpathn(tcp, tcp->u_arg[0], tcp->u_arg[1]);
155                 tprintf(", %lu", tcp->u_arg[1]);
156         }
157         return 0;
158 }
159
160 int
161 sys_gethostname(tcp)
162 struct tcb *tcp;
163 {
164         if (exiting(tcp)) {
165                 if (syserror(tcp))
166                         tprintf("%#lx", tcp->u_arg[0]);
167                 else
168                         printpath(tcp, tcp->u_arg[0]);
169                 tprintf(", %lu", tcp->u_arg[1]);
170         }
171         return 0;
172 }
173
174 int
175 sys_setdomainname(tcp)
176 struct tcb *tcp;
177 {
178         if (entering(tcp)) {
179                 printpathn(tcp, tcp->u_arg[0], tcp->u_arg[1]);
180                 tprintf(", %lu", tcp->u_arg[1]);
181         }
182         return 0;
183 }
184
185 #if !defined(LINUX)
186
187 int
188 sys_getdomainname(tcp)
189 struct tcb *tcp;
190 {
191         if (exiting(tcp)) {
192                 if (syserror(tcp))
193                         tprintf("%#lx", tcp->u_arg[0]);
194                 else
195                         printpath(tcp, tcp->u_arg[0]);
196                 tprintf(", %lu", tcp->u_arg[1]);
197         }
198         return 0;
199 }
200 #endif /* !LINUX */
201
202 int
203 sys_exit(tcp)
204 struct tcb *tcp;
205 {
206         if (exiting(tcp)) {
207                 fprintf(stderr, "_exit returned!\n");
208                 return -1;
209         }
210         /* special case: we stop tracing this process, finish line now */
211         tprintf("%ld) ", tcp->u_arg[0]);
212         tabto(acolumn);
213         tprintf("= ?");
214         printtrailer(tcp);
215         return 0;
216 }
217
218 int
219 internal_exit(tcp)
220 struct tcb *tcp;
221 {
222         if (entering(tcp))
223                 tcp->flags |= TCB_EXITING;
224         return 0;
225 }
226
227 #ifdef SVR4
228
229 int
230 sys_fork(tcp)
231 struct tcb *tcp;
232 {
233         if (exiting(tcp)) {
234                 if (getrval2(tcp)) {
235                         tcp->auxstr = "child process";
236                         return RVAL_UDECIMAL | RVAL_STR;
237                 }
238         }
239         return 0;
240 }
241
242 int
243 internal_fork(tcp)
244 struct tcb *tcp;
245 {
246         struct tcb *tcpchild;
247
248         if (exiting(tcp)) {
249                 if (getrval2(tcp))
250                         return 0;
251                 if (!followfork)
252                         return 0;
253                 if (nprocs == MAX_PROCS) {
254                         tcp->flags &= ~TCB_FOLLOWFORK;
255                         fprintf(stderr, "sys_fork: tcb table full\n");
256                         return 0;
257                 }
258                 else
259                         tcp->flags |= TCB_FOLLOWFORK;
260                 if (syserror(tcp))
261                         return 0;
262                 if ((tcpchild = alloctcb(tcp->u_rval)) == NULL) {
263                         fprintf(stderr, "sys_fork: tcb table full\n");
264                         return 0;
265                 }
266                 proc_open(tcpchild, 1);
267         }
268         return 0;
269 }
270
271 #else /* !SVR4 */
272
273 int
274 sys_fork(tcp)
275 struct tcb *tcp;
276 {
277         if (exiting(tcp))
278                 return RVAL_UDECIMAL;
279         return 0;
280 }
281
282 int
283 internal_fork(tcp)
284 struct tcb *tcp;
285 {
286         struct tcb *tcpchild;
287         int pid;
288         int dont_follow = 0;
289
290 #ifdef SYS_vfork
291         if (tcp->scno == SYS_vfork) {
292 #if defined(I386) && defined(LINUX)
293                 /* Attempt to make vfork into fork, which we can follow. */
294                 if (!followvfork || 
295                     ptrace(PTRACE_POKEUSR, tcp->pid, 
296                            (void *)(ORIG_EAX * 4), SYS_fork) < 0) 
297                         dont_follow = 1;
298                 
299 #else
300                 dont_follow = 1;
301 #endif
302         }
303 #endif
304         if (entering(tcp)) {
305                 if (!followfork || dont_follow)
306                         return 0;
307                 if (nprocs == MAX_PROCS) {
308                         tcp->flags &= ~TCB_FOLLOWFORK;
309                         fprintf(stderr, "sys_fork: tcb table full\n");
310                         return 0;
311                 }
312                 tcp->flags |= TCB_FOLLOWFORK;
313                 if (setbpt(tcp) < 0)
314                         return 0;
315         }
316         else {
317                 int bpt = tcp->flags & TCB_BPTSET;
318
319                 if (!(tcp->flags & TCB_FOLLOWFORK))
320                         return 0;
321                 if (bpt)
322                         clearbpt(tcp);
323
324                 if (syserror(tcp))
325                         return 0;
326
327                 pid = tcp->u_rval;
328                 if ((tcpchild = alloctcb(pid)) == NULL) {
329                         fprintf(stderr, " [tcb table full]\n");
330                         kill(pid, SIGKILL); /* XXX */
331                         return 0;
332                 }
333 #ifdef LINUX
334                 if (ptrace(PTRACE_ATTACH, pid, (char *) 1, 0) < 0) {
335                         perror("PTRACE_ATTACH");
336                         fprintf(stderr, "Too late?\n");
337                         droptcb(tcpchild);
338                         return 0;
339                 }
340 #endif /* LINUX */
341 #ifdef SUNOS4
342 #ifdef oldway
343                 /* The child must have run before it can be attached. */
344                 {
345                         struct timeval tv;
346                         tv.tv_sec = 0;
347                         tv.tv_usec = 10000;
348                         select(0, NULL, NULL, NULL, &tv);
349                 }
350                 if (ptrace(PTRACE_ATTACH, pid, (char *)1, 0) < 0) {
351                         perror("PTRACE_ATTACH");
352                         fprintf(stderr, "Too late?\n");
353                         droptcb(tcpchild);
354                         return 0;
355                 }
356 #else /* !oldway */
357                 /* Try to catch the new process as soon as possible. */
358                 {
359                         int i;
360                         for (i = 0; i < 1024; i++)
361                                 if (ptrace(PTRACE_ATTACH, pid, (char *) 1, 0) >= 0)
362                                         break;
363                         if (i == 1024) {
364                                 perror("PTRACE_ATTACH");
365                                 fprintf(stderr, "Too late?\n");
366                                 droptcb(tcpchild);
367                                 return 0;
368                         }
369                 }
370 #endif /* !oldway */
371 #endif /* SUNOS4 */
372                 tcpchild->flags |= TCB_ATTACHED;
373                 /* Child has BPT too, must be removed on first occasion */
374                 if (bpt) {
375                         tcpchild->flags |= TCB_BPTSET;
376                         tcpchild->baddr = tcp->baddr;
377                         memcpy(tcpchild->inst, tcp->inst,
378                                 sizeof tcpchild->inst);
379                 }
380                 newoutf(tcpchild);
381                 tcpchild->parent = tcp;
382                 tcp->nchildren++;
383                 if (!qflag)
384                         fprintf(stderr, "Process %d attached\n", pid);
385         }
386         return 0;
387 }
388
389 #endif /* !SVR4 */
390
391 #if defined(SUNOS4) || defined(LINUX)
392
393 int
394 sys_vfork(tcp)
395 struct tcb *tcp;
396 {
397         if (exiting(tcp))
398                 return RVAL_UDECIMAL;
399         return 0;
400 }
401
402 #endif /* SUNOS4 || LINUX */
403
404 #ifndef LINUX
405
406 static char idstr[16];
407
408 int
409 sys_getpid(tcp)
410 struct tcb *tcp;
411 {
412         if (exiting(tcp)) {
413                 sprintf(idstr, "ppid %lu", getrval2(tcp));
414                 tcp->auxstr = idstr;
415                 return RVAL_STR;
416         }
417         return 0;
418 }
419
420 int
421 sys_getuid(tcp)
422 struct tcb *tcp;
423 {
424         if (exiting(tcp)) {
425                 sprintf(idstr, "euid %lu", getrval2(tcp));
426                 tcp->auxstr = idstr;
427                 return RVAL_STR;
428         }
429         return 0;
430 }
431
432 int
433 sys_getgid(tcp)
434 struct tcb *tcp;
435 {
436         if (exiting(tcp)) {
437                 sprintf(idstr, "egid %lu", getrval2(tcp));
438                 tcp->auxstr = idstr;
439                 return RVAL_STR;
440         }
441         return 0;
442 }
443
444 #endif /* !LINUX */
445
446 #ifdef LINUX
447
448 int
449 sys_setuid(tcp)
450 struct tcb *tcp;
451 {
452         if (entering(tcp)) {
453                 tprintf("%u", (uid_t) tcp->u_arg[0]);
454         }
455         return 0;
456 }
457
458 int
459 sys_setgid(tcp)
460 struct tcb *tcp;
461 {
462         if (entering(tcp)) {
463                 tprintf("%u", (gid_t) tcp->u_arg[0]);
464         }
465         return 0;
466 }
467
468 int
469 sys_getresuid(tcp)
470     struct tcb *tcp;
471 {
472         if (exiting(tcp)) {
473                 uid_t res[3];
474                 if (umoven(tcp, tcp->u_arg[0], sizeof(pid_t),
475                                         (char *) &res[0]) < 0
476                                 || umoven(tcp, tcp->u_arg[2], sizeof(pid_t),
477                                         (char *) &res[1]) < 0
478                                 || umoven(tcp, tcp->u_arg[2], sizeof(pid_t),
479                                         (char *) &res[2]) < 0)
480                         return -1;
481                 tprintf("ruid %lu, euid %lu, suid %lu",
482                                 (unsigned long) res[0],
483                                 (unsigned long) res[1],
484                                 (unsigned long) res[2]);
485         }
486         return 0;
487 }
488
489 int
490 sys_getresgid(tcp)
491 struct tcb *tcp;
492 {
493         if (exiting(tcp)) {
494                 uid_t res[3];
495                 if (umoven(tcp, tcp->u_arg[0], sizeof(pid_t),
496                                         (char *) &res[0]) < 0
497                                 || umoven(tcp, tcp->u_arg[2], sizeof(pid_t),
498                                         (char *) &res[1]) < 0
499                                 || umoven(tcp, tcp->u_arg[2], sizeof(pid_t),
500                                         (char *) &res[2]) < 0)
501                         return -1;
502                 tprintf("rgid %lu, egid %lu, sgid %lu",
503                                 (unsigned long) res[0],
504                                 (unsigned long) res[1],
505                                 (unsigned long) res[2]);
506         }
507         return 0;
508 }
509
510 #endif /* LINUX */
511
512 int
513 sys_setreuid(tcp)
514 struct tcb *tcp;
515 {
516         if (entering(tcp)) {
517                 tprintf("%lu, %lu",
518                         (unsigned long) (uid_t) tcp->u_arg[0],
519                         (unsigned long) (uid_t) tcp->u_arg[1]);
520         }
521         return 0;
522 }
523
524 int
525 sys_setregid(tcp)
526 struct tcb *tcp;
527 {
528         if (entering(tcp)) {
529                 tprintf("%lu, %lu",
530                         (unsigned long) (gid_t) tcp->u_arg[0],
531                         (unsigned long) (gid_t) tcp->u_arg[1]);
532         }
533         return 0;
534 }
535
536 #ifdef LINUX
537 int
538 sys_setresuid(tcp)
539      struct tcb *tcp;
540 {
541         if (entering(tcp)) {
542                 tprintf("ruid %u, euid %u, suid %u",
543                                 (uid_t) tcp->u_arg[0],
544                                 (uid_t) tcp->u_arg[1],
545                                 (uid_t) tcp->u_arg[2]);
546         }
547         return 0;
548 }
549 int
550 sys_setresgid(tcp)
551      struct tcb *tcp;
552 {
553         if (entering(tcp)) {
554                 tprintf("rgid %u, egid %u, sgid %u",
555                                 (uid_t) tcp->u_arg[0],
556                                 (uid_t) tcp->u_arg[1],
557                                 (uid_t) tcp->u_arg[2]);
558         }
559         return 0;
560 }
561
562 #endif /* LINUX */
563
564 int
565 sys_setgroups(tcp)
566 struct tcb *tcp;
567 {
568         int i, len;
569         GETGROUPS_T *gidset;
570
571         if (entering(tcp)) {
572                 len = tcp->u_arg[0];
573                 tprintf("%u, ", len);
574                 if (len <= 0) {
575                         tprintf("[]");
576                         return 0;
577                 }
578                 gidset = (GETGROUPS_T *) malloc(len * sizeof(GETGROUPS_T));
579                 if (gidset == NULL) {
580                         fprintf(stderr, "sys_setgroups: out of memory\n");
581                         return -1;
582                 }
583                 if (!verbose(tcp))
584                         tprintf("%#lx", tcp->u_arg[1]);
585                 else if (umoven(tcp, tcp->u_arg[1],
586                     len * sizeof(GETGROUPS_T), (char *) gidset) < 0)
587                         tprintf("[?]");
588                 else {
589                         tprintf("[");
590                         for (i = 0; i < len; i++)
591                                 tprintf("%s%lu", i ? ", " : "",
592                                         (unsigned long) gidset[i]);
593                         tprintf("]");
594                 }
595                 free((char *) gidset);
596         }
597         return 0;
598 }
599
600 int
601 sys_getgroups(tcp)
602 struct tcb *tcp;
603 {
604         int i, len;
605         GETGROUPS_T *gidset;
606
607         if (entering(tcp)) {
608                 len = tcp->u_arg[0];
609                 tprintf("%u, ", len);
610         } else {
611                 len = tcp->u_rval;
612                 if (len <= 0) {
613                         tprintf("[]");
614                         return 0;
615                 }
616                 gidset = (GETGROUPS_T *) malloc(len * sizeof(GETGROUPS_T));
617                 if (gidset == NULL) {
618                         fprintf(stderr, "sys_getgroups: out of memory\n");
619                         return -1;
620                 }
621                 if (!tcp->u_arg[1])
622                         tprintf("NULL");
623                 else if (!verbose(tcp) || tcp->u_arg[0] == 0)
624                         tprintf("%#lx", tcp->u_arg[1]);
625                 else if (umoven(tcp, tcp->u_arg[1],
626                     len * sizeof(GETGROUPS_T), (char *) gidset) < 0)
627                         tprintf("[?]");
628                 else {
629                         tprintf("[");
630                         for (i = 0; i < len; i++)
631                                 tprintf("%s%lu", i ? ", " : "",
632                                         (unsigned long) gidset[i]);
633                         tprintf("]");
634                 }
635                 free((char *)gidset);
636         }
637         return 0;
638 }
639
640 int
641 sys_setpgrp(tcp)
642 struct tcb *tcp;
643 {
644         if (entering(tcp)) {
645 #ifndef SVR4
646                 tprintf("%lu, %lu", tcp->u_arg[0], tcp->u_arg[1]);
647 #endif /* !SVR4 */
648         }
649         return 0;
650 }
651
652 int
653 sys_getpgrp(tcp)
654 struct tcb *tcp;
655 {
656         if (entering(tcp)) {
657 #ifndef SVR4
658                 tprintf("%lu", tcp->u_arg[0]);
659 #endif /* !SVR4 */
660         }
661         return 0;
662 }
663
664 int
665 sys_getsid(tcp)
666 struct tcb *tcp;
667 {
668         if (entering(tcp)) {
669                 tprintf("%lu", tcp->u_arg[0]);
670         }
671         return 0;
672 }
673
674 int
675 sys_setsid(tcp)
676 struct tcb *tcp;
677 {
678         return 0;
679 }
680
681 int
682 sys_getpgid(tcp)
683 struct tcb *tcp;
684 {
685         if (entering(tcp)) {
686                 tprintf("%lu", tcp->u_arg[0]);
687         }
688         return 0;
689 }
690
691 int
692 sys_setpgid(tcp)
693 struct tcb *tcp;
694 {
695         if (entering(tcp)) {
696                 tprintf("%lu, %lu", tcp->u_arg[0], tcp->u_arg[1]);
697         }
698         return 0;
699 }
700
701 void
702 fake_execve(tcp, program, argv, envp)
703 struct tcb *tcp;
704 char *program;
705 char *argv[];
706 char *envp[];
707 {
708         int i;
709
710 #ifdef ARM
711         if (!(qual_flags[SYS_execve - __NR_SYSCALL_BASE] & QUAL_TRACE))
712                 return;
713 #else
714         if (!(qual_flags[SYS_execve] & QUAL_TRACE))
715                 return;
716 #endif /* !ARM */
717         printleader(tcp);
718         tprintf("execve(");
719         string_quote(program);
720         tprintf(", [");
721         for (i = 0; argv[i] != NULL; i++) {
722                 if (i != 0)
723                         tprintf(", ");
724                 string_quote(argv[i]);
725         }
726         for (i = 0; envp[i] != NULL; i++)
727                 ;
728         tprintf("], [/* %d var%s */]) ", i, (i != 1) ? "s" : "");
729         tabto(acolumn);
730         tprintf("= 0");
731         printtrailer(tcp);
732 }
733
734 static void
735 printargv(tcp, addr)
736 struct tcb *tcp;
737 long addr;
738 {
739         char *cp;
740         char *sep;
741         int max = max_strlen / 2;
742
743         for (sep = ""; --max >= 0; sep = ", ") {
744                 if (!abbrev(tcp))
745                         max++;
746                 if (umove(tcp, addr, &cp) < 0) {
747                         tprintf("%#lx", addr);
748                         return;
749                 }
750                 if (cp == 0)
751                         break;
752                 tprintf(sep);
753                 printstr(tcp, (long) cp, -1);
754                 addr += sizeof(char *);
755         }
756         if (cp)
757                 tprintf(", ...");
758 }
759
760 static void
761 printargc(fmt, tcp, addr)
762 char *fmt;
763 struct tcb *tcp;
764 long addr;
765 {
766         int count;
767         char *cp;
768
769         for (count = 0; umove(tcp, addr, &cp) >= 0 && cp != NULL; count++) {
770                 addr += sizeof(char *);
771         }
772         tprintf(fmt, count, count == 1 ? "" : "s");
773 }
774
775 int
776 sys_execv(tcp)
777 struct tcb *tcp;
778 {
779         if (entering(tcp)) {
780                 printpath(tcp, tcp->u_arg[0]);
781                 if (!verbose(tcp))
782                         tprintf(", %#lx", tcp->u_arg[1]);
783 #if 0
784                 else if (abbrev(tcp))
785                         printargc(", [/* %d arg%s */]", tcp, tcp->u_arg[1]);
786 #endif
787                 else {
788                         tprintf(", [");
789                         printargv(tcp, tcp->u_arg[1]);
790                         tprintf("]");
791                 }
792         }
793         return 0;
794 }
795
796 int
797 sys_execve(tcp)
798 struct tcb *tcp;
799 {
800         if (entering(tcp)) {
801                 printpath(tcp, tcp->u_arg[0]);
802                 if (!verbose(tcp))
803                         tprintf(", %#lx", tcp->u_arg[1]);
804 #if 0
805                 else if (abbrev(tcp))
806                         printargc(", [/* %d arg%s */]", tcp, tcp->u_arg[1]);
807 #endif
808                 else {
809                         tprintf(", [");
810                         printargv(tcp, tcp->u_arg[1]);
811                         tprintf("]");
812                 }
813                 if (!verbose(tcp))
814                         tprintf(", %#lx", tcp->u_arg[2]);
815                 else if (abbrev(tcp))
816                         printargc(", [/* %d var%s */]", tcp, tcp->u_arg[2]);
817                 else {
818                         tprintf(", [");
819                         printargv(tcp, tcp->u_arg[2]);
820                         tprintf("]");
821                 }
822         }
823 #ifdef LINUX
824 #if defined(ALPHA) || defined(SPARC) || defined(POWERPC)
825         tcp->flags |= TCB_WAITEXECVE;
826 #endif /* ALPHA || SPARC || POWERPC */
827 #endif /* LINUX */
828         return 0;
829 }
830
831 int
832 internal_exec(tcp)
833 struct tcb *tcp;
834 {
835 #ifdef SUNOS4
836         if (exiting(tcp) && !syserror(tcp) && followfork)
837                 fixvfork(tcp);
838 #endif /* SUNOS4 */
839         return 0;
840 }
841
842 #ifdef LINUX
843 #ifndef __WCLONE
844 #define __WCLONE        0x8000000
845 #endif
846 #endif /* LINUX */
847
848 static struct xlat wait4_options[] = {
849         { WNOHANG,      "WNOHANG"       },
850 #ifndef WSTOPPED
851         { WUNTRACED,    "WUNTRACED"     },
852 #endif
853 #ifdef WEXITED
854         { WEXITED,      "WEXITED"       },
855 #endif
856 #ifdef WTRAPPED
857         { WTRAPPED,     "WTRAPPED"      },
858 #endif
859 #ifdef WSTOPPED
860         { WSTOPPED,     "WSTOPPED"      },
861 #endif
862 #ifdef WCONTINUED
863         { WCONTINUED,   "WCONTINUED"    },
864 #endif
865 #ifdef WNOWAIT
866         { WNOWAIT,      "WNOWAIT"       },
867 #endif
868 #ifdef __WCLONE
869         { __WCLONE,     "__WCLONE"      },
870 #endif
871         { 0,            NULL            },
872 };
873
874 static int
875 printstatus(status)
876 int status;
877 {
878         int exited = 0;
879
880         /*
881          * Here is a tricky presentation problem.  This solution
882          * is still not entirely satisfactory but since there
883          * are no wait status constructors it will have to do.
884          */
885         if (WIFSTOPPED(status))
886                 tprintf("[WIFSTOPPED(s) && WSTOPSIG(s) == %s]",
887                         signalent[WSTOPSIG(status)]);
888         else if WIFSIGNALED(status)
889                 tprintf("[WIFSIGNALED(s) && WTERMSIG(s) == %s%s]",
890                         signalent[WTERMSIG(status)],
891                         WCOREDUMP(status) ? " && WCOREDUMP(s)" : "");
892         else if WIFEXITED(status) {
893                 tprintf("[WIFEXITED(s) && WEXITSTATUS(s) == %d]",
894                         WEXITSTATUS(status));
895                 exited = 1;
896         }
897         else
898                 tprintf("[%#x]", status);
899         return exited;
900 }
901
902 static int
903 printwaitn(tcp, n)
904 struct tcb *tcp;
905 int n;
906 {
907         int status;
908         int exited = 0;
909
910         if (entering(tcp)) {
911                 tprintf("%ld, ", tcp->u_arg[0]);
912         } else {
913                 /* status */
914                 if (!tcp->u_arg[1])
915                         tprintf("NULL");
916                 else if (syserror(tcp) || tcp->u_rval == 0)
917                         tprintf("%#lx", tcp->u_arg[1]);
918                 else if (umove(tcp, tcp->u_arg[1], &status) < 0)
919                         tprintf("[?]");
920                 else
921                         exited = printstatus(status);
922                 /* options */
923                 tprintf(", ");
924                 if (!printflags(wait4_options, tcp->u_arg[2]))
925                         tprintf("0");
926                 if (n == 4) {
927                         tprintf(", ");
928                         /* usage */
929                         if (!tcp->u_arg[3])
930                                 tprintf("NULL");
931 #ifdef LINUX
932                         else if (tcp->u_rval > 0)
933                                 printrusage(tcp, tcp->u_arg[3]);
934 #endif /* LINUX */
935 #ifdef SUNOS4
936                         else if (tcp->u_rval > 0 && exited)
937                                 printrusage(tcp, tcp->u_arg[3]);
938 #endif /* SUNOS4 */
939                         else
940                                 tprintf("%#lx", tcp->u_arg[3]);
941                 }
942         }
943         return 0;
944 }
945
946 int
947 internal_wait(tcp)
948 struct tcb *tcp;
949 {
950         if (entering(tcp)) {
951                 /* WTA: fix bug with hanging children */
952                 if (!(tcp->u_arg[2] & WNOHANG) && tcp->nchildren > 0) {
953                         /* There are traced children */
954                         tcp->flags |= TCB_SUSPENDED;
955                         tcp->waitpid = tcp->u_arg[0];
956                 }
957         }
958         return 0;
959 }
960
961 #ifdef SVR4
962
963 int
964 sys_wait(tcp)
965 struct tcb *tcp;
966 {
967         if (exiting(tcp)) {
968                 /* The library wrapper stuffs this into the user variable. */
969                 if (!syserror(tcp))
970                         printstatus(getrval2(tcp));
971         }
972         return 0;
973 }
974
975 #endif /* SVR4 */
976
977 int
978 sys_waitpid(tcp)
979 struct tcb *tcp;
980 {
981         return printwaitn(tcp, 3);
982 }
983
984 int
985 sys_wait4(tcp)
986 struct tcb *tcp;
987 {
988         return printwaitn(tcp, 4);
989 }
990
991 #ifdef SVR4
992
993 static struct xlat waitid_types[] = {
994         { P_PID,        "P_PID"         },
995         { P_PPID,       "P_PPID"        },
996         { P_PGID,       "P_PGID"        },
997         { P_SID,        "P_SID"         },
998         { P_CID,        "P_CID"         },
999         { P_UID,        "P_UID"         },
1000         { P_GID,        "P_GID"         },
1001         { P_ALL,        "P_ALL"         },
1002 #ifdef P_LWPID
1003         { P_LWPID,      "P_LWPID"       },
1004 #endif
1005         { 0,            NULL            },
1006 };
1007
1008 static struct xlat siginfo_codes[] = {
1009 #ifdef SI_NOINFO
1010         { SI_NOINFO,    "SI_NOINFO"     },
1011 #endif
1012 #ifdef SI_USER
1013         { SI_USER,      "SI_USER"       },
1014 #endif
1015 #ifdef SI_LWP
1016         { SI_LWP,       "SI_LWP"        },
1017 #endif
1018 #ifdef SI_QUEUE
1019         { SI_QUEUE,     "SI_QUEUE"      },
1020 #endif
1021 #ifdef SI_TIMER
1022         { SI_TIMER,     "SI_TIMER"      },
1023 #endif
1024 #ifdef SI_ASYNCIO
1025         { SI_ASYNCIO,   "SI_ASYNCIO"    },
1026 #endif
1027 #ifdef SI_MESGQ
1028         { SI_MESGQ,     "SI_MESGQ"      },
1029 #endif
1030         { 0,            NULL            },
1031 };
1032
1033 static struct xlat sigtrap_codes[] = {
1034         { TRAP_BRKPT,   "TRAP_BRKPT"    },
1035         { TRAP_TRACE,   "TRAP_TRACE"    },
1036         { 0,            NULL            },
1037 };
1038
1039 static struct xlat sigcld_codes[] = {
1040         { CLD_EXITED,   "CLD_EXITED"    },
1041         { CLD_KILLED,   "CLD_KILLED"    },
1042         { CLD_DUMPED,   "CLD_DUMPED"    },
1043         { CLD_TRAPPED,  "CLD_TRAPPED"   },
1044         { CLD_STOPPED,  "CLD_STOPPED"   },
1045         { CLD_CONTINUED,"CLD_CONTINUED" },
1046         { 0,            NULL            },
1047 };
1048
1049 static struct xlat sigpoll_codes[] = {
1050         { POLL_IN,      "POLL_IN"       },
1051         { POLL_OUT,     "POLL_OUT"      },
1052         { POLL_MSG,     "POLL_MSG"      },
1053         { POLL_ERR,     "POLL_ERR"      },
1054         { POLL_PRI,     "POLL_PRI"      },
1055         { POLL_HUP,     "POLL_HUP"      },
1056         { 0,            NULL            },
1057 };
1058
1059 static struct xlat sigprof_codes[] = {
1060 #ifdef PROF_SIG
1061         { PROF_SIG,     "PROF_SIG"      },
1062 #endif
1063         { 0,            NULL            },
1064 };
1065
1066 static struct xlat sigill_codes[] = {
1067         { ILL_ILLOPC,   "ILL_ILLOPC"    },
1068         { ILL_ILLOPN,   "ILL_ILLOPN"    },
1069         { ILL_ILLADR,   "ILL_ILLADR"    },
1070         { ILL_ILLTRP,   "ILL_ILLTRP"    },
1071         { ILL_PRVOPC,   "ILL_PRVOPC"    },
1072         { ILL_PRVREG,   "ILL_PRVREG"    },
1073         { ILL_COPROC,   "ILL_COPROC"    },
1074         { ILL_BADSTK,   "ILL_BADSTK"    },
1075         { 0,            NULL            },
1076 };
1077
1078 static struct xlat sigemt_codes[] = {
1079 #ifdef EMT_TAGOVF
1080         { EMT_TAGOVF,   "EMT_TAGOVF"    },
1081 #endif
1082         { 0,            NULL            },
1083 };
1084
1085 static struct xlat sigfpe_codes[] = {
1086         { FPE_INTDIV,   "FPE_INTDIV"    },
1087         { FPE_INTOVF,   "FPE_INTOVF"    },
1088         { FPE_FLTDIV,   "FPE_FLTDIV"    },
1089         { FPE_FLTOVF,   "FPE_FLTOVF"    },
1090         { FPE_FLTUND,   "FPE_FLTUND"    },
1091         { FPE_FLTRES,   "FPE_FLTRES"    },
1092         { FPE_FLTINV,   "FPE_FLTINV"    },
1093         { FPE_FLTSUB,   "FPE_FLTSUB"    },
1094         { 0,            NULL            },
1095 };
1096
1097 static struct xlat sigsegv_codes[] = {
1098         { SEGV_MAPERR,  "SEGV_MAPERR"   },
1099         { SEGV_ACCERR,  "SEGV_ACCERR"   },
1100         { 0,            NULL            },
1101 };
1102
1103 static struct xlat sigbus_codes[] = {
1104         { BUS_ADRALN,   "BUS_ADRALN"    },
1105         { BUS_ADRERR,   "BUS_ADRERR"    },
1106         { BUS_OBJERR,   "BUS_OBJERR"    },
1107         { 0,            NULL            },
1108 };
1109
1110 void
1111 printsiginfo(sip)
1112 siginfo_t *sip;
1113 {
1114         char *code;
1115
1116         tprintf("{si_signo=");
1117         printsignal(sip->si_signo);
1118         code = xlookup(siginfo_codes, sip->si_code);
1119         if (!code) {
1120                 switch (sip->si_signo) {
1121                 case SIGTRAP:
1122                         code = xlookup(sigtrap_codes, sip->si_code);
1123                         break;
1124                 case SIGCHLD:
1125                         code = xlookup(sigcld_codes, sip->si_code);
1126                         break;
1127                 case SIGPOLL:
1128                         code = xlookup(sigpoll_codes, sip->si_code);
1129                         break;
1130                 case SIGPROF:
1131                         code = xlookup(sigprof_codes, sip->si_code);
1132                         break;
1133                 case SIGILL:
1134                         code = xlookup(sigill_codes, sip->si_code);
1135                         break;
1136                 case SIGEMT:
1137                         code = xlookup(sigemt_codes, sip->si_code);
1138                         break;
1139                 case SIGFPE:
1140                         code = xlookup(sigfpe_codes, sip->si_code);
1141                         break;
1142                 case SIGSEGV:
1143                         code = xlookup(sigsegv_codes, sip->si_code);
1144                         break;
1145                 case SIGBUS:
1146                         code = xlookup(sigbus_codes, sip->si_code);
1147                         break;
1148                 }
1149         }
1150         if (code)
1151                 tprintf(", si_code=%s", code);
1152         else
1153                 tprintf(", si_code=%#x", sip->si_code);
1154 #ifdef SI_NOINFO
1155         if (sip->si_code != SI_NOINFO) {
1156 #endif
1157                 if (sip->si_errno) {
1158                         if (sip->si_errno < 0 || sip->si_errno >= nerrnos)
1159                                 tprintf(", si_errno=%d", sip->si_errno);
1160                         else
1161                                 tprintf(", si_errno=%s",
1162                                         errnoent[sip->si_errno]);
1163                 }
1164                 if (SI_FROMUSER(sip)) {
1165 #ifdef SI_QUEUE
1166                         tprintf(", si_pid=%ld, si_uid=%ld",
1167                                 sip->si_pid, sip->si_uid);
1168                         switch (sip->si_code) {
1169                         case SI_QUEUE:
1170 #ifdef SI_TIMER
1171                         case SI_TIMER:
1172 #endif /* SI_QUEUE */
1173                         case SI_ASYNCIO:
1174 #ifdef SI_MESGQ
1175                         case SI_MESGQ:
1176 #endif /* SI_MESGQ */
1177                                 tprintf(", si_value=%d",
1178                                         sip->si_value.sival_int);
1179                                 break;
1180                         }
1181 #endif /* SI_QUEUE */
1182                 }
1183                 else {
1184                         switch (sip->si_signo) {
1185                         case SIGCHLD:
1186                                 tprintf(", si_pid=%ld, si_status=",
1187                                         sip->si_pid);
1188                                 if (sip->si_code == CLD_EXITED)
1189                                         tprintf("%d", sip->si_status);
1190                                 else
1191                                         printsignal(sip->si_status);
1192                                 break;
1193                         case SIGILL: case SIGFPE:
1194                         case SIGSEGV: case SIGBUS:
1195                                 tprintf(", si_addr=%#lx",
1196                                         (unsigned long) sip->si_addr);
1197                                 break;
1198                         case SIGPOLL:
1199                                 switch (sip->si_code) {
1200                                 case POLL_IN: case POLL_OUT: case POLL_MSG:
1201                                         tprintf(", si_band=%ld",
1202                                                 (long) sip->si_band);
1203                                         break;
1204                                 }
1205                                 break;
1206                         }
1207                 }
1208                 tprintf(", ...");
1209 #ifdef SI_NOINFO
1210         }
1211 #endif
1212         tprintf("}");
1213 }
1214
1215 int
1216 sys_waitid(tcp)
1217 struct tcb *tcp;
1218 {
1219         siginfo_t si;
1220         int exited;
1221
1222         if (entering(tcp)) {
1223                 printxval(waitid_types, tcp->u_arg[0], "P_???");
1224                 tprintf(", %ld, ", tcp->u_arg[1]);
1225                 if (tcp->nchildren > 0) {
1226                         /* There are traced children */
1227                         tcp->flags |= TCB_SUSPENDED;
1228                         tcp->waitpid = tcp->u_arg[0];
1229                 }
1230         }
1231         else {
1232                 /* siginfo */
1233                 exited = 0;
1234                 if (!tcp->u_arg[2])
1235                         tprintf("NULL");
1236                 else if (syserror(tcp))
1237                         tprintf("%#lx", tcp->u_arg[2]);
1238                 else if (umove(tcp, tcp->u_arg[2], &si) < 0)
1239                         tprintf("{???}");
1240                 else
1241                         printsiginfo(&si);
1242                 /* options */
1243                 tprintf(", ");
1244                 if (!printflags(wait4_options, tcp->u_arg[3]))
1245                         tprintf("0");
1246         }
1247         return 0;
1248 }
1249
1250 #endif /* SVR4 */
1251
1252 int
1253 sys_alarm(tcp)
1254 struct tcb *tcp;
1255 {
1256         if (entering(tcp))
1257                 tprintf("%lu", tcp->u_arg[0]);
1258         return 0;
1259 }
1260
1261 int
1262 sys_uname(tcp)
1263 struct tcb *tcp;
1264 {
1265         struct utsname uname;
1266
1267         if (exiting(tcp)) {
1268                 if (syserror(tcp) || !verbose(tcp))
1269                         tprintf("%#lx", tcp->u_arg[0]);
1270                 else if (umove(tcp, tcp->u_arg[0], &uname) < 0)
1271                         tprintf("{...}");
1272                 else if (!abbrev(tcp)) {
1273
1274                         tprintf("{sysname=\"%s\", nodename=\"%s\", ",
1275                                 uname.sysname, uname.nodename);
1276                         tprintf("release=\"%s\", version=\"%s\", ",
1277                                 uname.release, uname.version);
1278                         tprintf("machine=\"%s\"", uname.machine);
1279 #ifdef LINUX
1280 #ifndef __GLIBC__
1281                         tprintf(", domainname=\"%s\"", uname.domainname);
1282 #endif /* __GLIBC__ */
1283 #endif /* LINUX */
1284                         tprintf("}");
1285                 }
1286                 else
1287                         tprintf("{sys=\"%s\", node=\"%s\", ...}",
1288                                 uname.sysname, uname.nodename);
1289         }
1290         return 0;
1291 }
1292
1293 #ifndef SVR4
1294
1295 static struct xlat ptrace_cmds[] = {
1296         { PTRACE_TRACEME,       "PTRACE_TRACEME"        },
1297         { PTRACE_PEEKTEXT,      "PTRACE_PEEKTEXT",      },
1298         { PTRACE_PEEKDATA,      "PTRACE_PEEKDATA",      },
1299         { PTRACE_PEEKUSER,      "PTRACE_PEEKUSER",      },
1300         { PTRACE_POKETEXT,      "PTRACE_POKETEXT",      },
1301         { PTRACE_POKEDATA,      "PTRACE_POKEDATA",      },
1302         { PTRACE_POKEUSER,      "PTRACE_POKEUSER",      },
1303         { PTRACE_CONT,          "PTRACE_CONT"           },
1304         { PTRACE_KILL,          "PTRACE_KILL"           },
1305         { PTRACE_SINGLESTEP,    "PTRACE_SINGLESTEP"     },
1306         { PTRACE_ATTACH,        "PTRACE_ATTACH"         },
1307         { PTRACE_DETACH,        "PTRACE_DETACH"         },
1308 #ifdef SUNOS4
1309         { PTRACE_GETREGS,       "PTRACE_GETREGS"        },
1310         { PTRACE_SETREGS,       "PTRACE_SETREGS"        },
1311         { PTRACE_GETFPREGS,     "PTRACE_GETFPREGS",     },
1312         { PTRACE_SETFPREGS,     "PTRACE_SETFPREGS",     },
1313         { PTRACE_READDATA,      "PTRACE_READDATA"       },
1314         { PTRACE_WRITEDATA,     "PTRACE_WRITEDATA"      },
1315         { PTRACE_READTEXT,      "PTRACE_READTEXT"       },
1316         { PTRACE_WRITETEXT,     "PTRACE_WRITETEXT"      },
1317         { PTRACE_GETFPAREGS,    "PTRACE_GETFPAREGS"     },
1318         { PTRACE_SETFPAREGS,    "PTRACE_SETFPAREGS"     },
1319 #ifdef SPARC
1320         { PTRACE_GETWINDOW,     "PTRACE_GETWINDOW"      },
1321         { PTRACE_SETWINDOW,     "PTRACE_SETWINDOW"      },
1322 #else /* !SPARC */
1323         { PTRACE_22,            "PTRACE_PTRACE_22"      },
1324         { PTRACE_23,            "PTRACE_PTRACE_23"      },
1325 #endif /* !SPARC */
1326 #endif /* SUNOS4 */
1327         { PTRACE_SYSCALL,       "PTRACE_SYSCALL"        },
1328 #ifdef SUNOS4
1329         { PTRACE_DUMPCORE,      "PTRACE_DUMPCORE"       },
1330 #ifdef I386
1331         { PTRACE_SETWRBKPT,     "PTRACE_SETWRBKPT"      },
1332         { PTRACE_SETACBKPT,     "PTRACE_SETACBKPT"      },
1333         { PTRACE_CLRDR7,        "PTRACE_CLRDR7"         },
1334 #else /* !I386 */
1335         { PTRACE_26,            "PTRACE_26"             },
1336         { PTRACE_27,            "PTRACE_27"             },
1337         { PTRACE_28,            "PTRACE_28"             },
1338 #endif /* !I386 */
1339         { PTRACE_GETUCODE,      "PTRACE_GETUCODE"       },
1340 #endif /* SUNOS4 */
1341         { 0,                    NULL                    },
1342 };
1343
1344 #ifndef SUNOS4_KERNEL_ARCH_KLUDGE
1345 static
1346 #endif /* !SUNOS4_KERNEL_ARCH_KLUDGE */
1347 struct xlat struct_user_offsets[] = {
1348 #ifdef LINUX
1349 #ifdef SPARC
1350         /* XXX No support for these offsets yet. */
1351 #elif defined(POWERPC)
1352         { 4*PT_R0,              "4*PT_R0"       },
1353         { 4*PT_R1,              "4*PT_R1"       },
1354         { 4*PT_R2,              "4*PT_R2"       },
1355         { 4*PT_R3,              "4*PT_R3"       },
1356         { 4*PT_R4,              "4*PT_R4"       },
1357         { 4*PT_R5,              "4*PT_R5"       },
1358         { 4*PT_R6,              "4*PT_R6"       },
1359         { 4*PT_R7,              "4*PT_R7"       },
1360         { 4*PT_R8,              "4*PT_R8"       },
1361         { 4*PT_R9,              "4*PT_R9"       },
1362         { 4*PT_R10,             "4*PT_R10"      },
1363         { 4*PT_R11,             "4*PT_R11"      },
1364         { 4*PT_R12,             "4*PT_R12"      },
1365         { 4*PT_R13,             "4*PT_R13"      },
1366         { 4*PT_R14,             "4*PT_R14"      },
1367         { 4*PT_R15,             "4*PT_R15"      },
1368         { 4*PT_R16,             "4*PT_R16"      },
1369         { 4*PT_R17,             "4*PT_R17"      },
1370         { 4*PT_R18,             "4*PT_R18"      },
1371         { 4*PT_R19,             "4*PT_R19"      },
1372         { 4*PT_R20,             "4*PT_R20"      },
1373         { 4*PT_R21,             "4*PT_R21"      },
1374         { 4*PT_R22,             "4*PT_R22"      },
1375         { 4*PT_R23,             "4*PT_R23"      },
1376         { 4*PT_R24,             "4*PT_R24"      },
1377         { 4*PT_R25,             "4*PT_R25"      },
1378         { 4*PT_R26,             "4*PT_R26"      },
1379         { 4*PT_R27,             "4*PT_R27"      },
1380         { 4*PT_R28,             "4*PT_R28"      },
1381         { 4*PT_R29,             "4*PT_R29"      },
1382         { 4*PT_R30,             "4*PT_R30"      },
1383         { 4*PT_R31,             "4*PT_R31"      },
1384         { 4*PT_NIP,             "4*PT_NIP"      },
1385         { 4*PT_MSR,             "4*PT_MSR"      },
1386         { 4*PT_ORIG_R3,  "4*PT_ORIG_R3" },
1387         { 4*PT_CTR,             "4*PT_CTR"      },
1388         { 4*PT_LNK,             "4*PT_LNK"      },
1389         { 4*PT_XER,             "4*PT_XER"      },
1390         { 4*PT_CCR,             "4*PT_CCR"      },
1391         { 4*PT_FPR0,    "4*PT_FPR0"     },
1392 #else   
1393 #ifdef ALPHA
1394         { 0,            "r0"                                    },
1395         { 1,            "r1"                                    },
1396         { 2,            "r2"                                    },
1397         { 3,            "r3"                                    },
1398         { 4,            "r4"                                    },
1399         { 5,            "r5"                                    },
1400         { 6,            "r6"                                    },
1401         { 7,            "r7"                                    },
1402         { 8,            "r8"                                    },
1403         { 9,            "r9"                                    },
1404         { 10,           "r10"                                   },
1405         { 11,           "r11"                                   },
1406         { 12,           "r12"                                   },
1407         { 13,           "r13"                                   },
1408         { 14,           "r14"                                   },
1409         { 15,           "r15"                                   },
1410         { 16,           "r16"                                   },
1411         { 17,           "r17"                                   },
1412         { 18,           "r18"                                   },
1413         { 19,           "r19"                                   },
1414         { 20,           "r20"                                   },
1415         { 21,           "r21"                                   },
1416         { 22,           "r22"                                   },
1417         { 23,           "r23"                                   },
1418         { 24,           "r24"                                   },
1419         { 25,           "r25"                                   },
1420         { 26,           "r26"                                   },
1421         { 27,           "r27"                                   },
1422         { 28,           "r28"                                   },
1423         { 29,           "gp"                                    },
1424         { 30,           "fp"                                    },
1425         { 31,           "zero"                                  },
1426         { 32,           "fp0"                                   },
1427         { 33,           "fp"                                    },
1428         { 34,           "fp2"                                   },
1429         { 35,           "fp3"                                   },
1430         { 36,           "fp4"                                   },
1431         { 37,           "fp5"                                   },
1432         { 38,           "fp6"                                   },
1433         { 39,           "fp7"                                   },
1434         { 40,           "fp8"                                   },
1435         { 41,           "fp9"                                   },
1436         { 42,           "fp10"                                  },
1437         { 43,           "fp11"                                  },
1438         { 44,           "fp12"                                  },
1439         { 45,           "fp13"                                  },
1440         { 46,           "fp14"                                  },
1441         { 47,           "fp15"                                  },
1442         { 48,           "fp16"                                  },
1443         { 49,           "fp17"                                  },
1444         { 50,           "fp18"                                  },
1445         { 51,           "fp19"                                  },
1446         { 52,           "fp20"                                  },
1447         { 53,           "fp21"                                  },
1448         { 54,           "fp22"                                  },
1449         { 55,           "fp23"                                  },
1450         { 56,           "fp24"                                  },
1451         { 57,           "fp25"                                  },
1452         { 58,           "fp26"                                  },
1453         { 59,           "fp27"                                  },
1454         { 60,           "fp28"                                  },
1455         { 61,           "fp29"                                  },
1456         { 62,           "fp30"                                  },
1457         { 63,           "fp31"                                  },
1458         { 64,           "pc"                                    },
1459 #else /* !ALPHA */
1460 #ifdef I386
1461         { 4*EBX,                "4*EBX"                                 },
1462         { 4*ECX,                "4*ECX"                                 },
1463         { 4*EDX,                "4*EDX"                                 },
1464         { 4*ESI,                "4*ESI"                                 },
1465         { 4*EDI,                "4*EDI"                                 },
1466         { 4*EBP,                "4*EBP"                                 },
1467         { 4*EAX,                "4*EAX"                                 },
1468         { 4*DS,                 "4*DS"                                  },
1469         { 4*ES,                 "4*ES"                                  },
1470         { 4*FS,                 "4*FS"                                  },
1471         { 4*GS,                 "4*GS"                                  },
1472         { 4*ORIG_EAX,           "4*ORIG_EAX"                            },
1473         { 4*EIP,                "4*EIP"                                 },
1474         { 4*CS,                 "4*CS"                                  },
1475         { 4*EFL,                "4*EFL"                                 },
1476         { 4*UESP,               "4*UESP"                                },
1477         { 4*SS,                 "4*SS"                                  },
1478 #else /* !I386 */
1479 #ifdef M68K
1480         { 4*PT_D1,              "4*PT_D1"                               },
1481         { 4*PT_D2,              "4*PT_D2"                               },
1482         { 4*PT_D3,              "4*PT_D3"                               },
1483         { 4*PT_D4,              "4*PT_D4"                               },
1484         { 4*PT_D5,              "4*PT_D5"                               },
1485         { 4*PT_D6,              "4*PT_D6"                               },
1486         { 4*PT_D7,              "4*PT_D7"                               },
1487         { 4*PT_A0,              "4*PT_A0"                               },
1488         { 4*PT_A1,              "4*PT_A1"                               },
1489         { 4*PT_A2,              "4*PT_A2"                               },
1490         { 4*PT_A3,              "4*PT_A3"                               },
1491         { 4*PT_A4,              "4*PT_A4"                               },
1492         { 4*PT_A5,              "4*PT_A5"                               },
1493         { 4*PT_A6,              "4*PT_A6"                               },
1494         { 4*PT_D0,              "4*PT_D0"                               },
1495         { 4*PT_USP,             "4*PT_USP"                              },
1496         { 4*PT_ORIG_D0,         "4*PT_ORIG_D0"                          },
1497         { 4*PT_SR,              "4*PT_SR"                               },
1498         { 4*PT_PC,              "4*PT_PC"                               },
1499 #endif /* M68K */
1500 #endif /* !I386 */
1501         { uoff(u_fpvalid),      "offsetof(struct user, u_fpvalid)"      },
1502 #ifdef I386
1503         { uoff(i387),           "offsetof(struct user, i387)"           },
1504 #else /* !I386 */
1505 #ifdef M68K
1506         { uoff(m68kfp),         "offsetof(struct user, m68kfp)"         },
1507 #endif /* M68K */
1508 #endif /* !I386 */
1509         { uoff(u_tsize),        "offsetof(struct user, u_tsize)"        },
1510         { uoff(u_dsize),        "offsetof(struct user, u_dsize)"        },
1511         { uoff(u_ssize),        "offsetof(struct user, u_ssize)"        },
1512         { uoff(start_code),     "offsetof(struct user, start_code)"     },
1513         { uoff(start_stack),    "offsetof(struct user, start_stack)"    },
1514         { uoff(signal),         "offsetof(struct user, signal)"         },
1515         { uoff(reserved),       "offsetof(struct user, reserved)"       },
1516         { uoff(u_ar0),          "offsetof(struct user, u_ar0)"          },
1517 #ifndef ARM
1518         { uoff(u_fpstate),      "offsetof(struct user, u_fpstate)"      },
1519 #endif
1520         { uoff(magic),          "offsetof(struct user, magic)"          },
1521         { uoff(u_comm),         "offsetof(struct user, u_comm)"         },
1522 #ifdef I386
1523         { uoff(u_debugreg),     "offsetof(struct user, u_debugreg)"     },
1524 #endif /* I386 */
1525 #endif /* !ALPHA */
1526 #endif /* !POWERPC/!SPARC */
1527 #endif /* LINUX */
1528 #ifdef SUNOS4
1529         { uoff(u_pcb),          "offsetof(struct user, u_pcb)"          },
1530         { uoff(u_procp),        "offsetof(struct user, u_procp)"        },
1531         { uoff(u_ar0),          "offsetof(struct user, u_ar0)"          },
1532         { uoff(u_comm[0]),      "offsetof(struct user, u_comm[0])"      },
1533         { uoff(u_arg[0]),       "offsetof(struct user, u_arg[0])"       },
1534         { uoff(u_ap),           "offsetof(struct user, u_ap)"           },
1535         { uoff(u_qsave),        "offsetof(struct user, u_qsave)"        },
1536         { uoff(u_rval1),        "offsetof(struct user, u_rval1)"        },
1537         { uoff(u_rval2),        "offsetof(struct user, u_rval2)"        },
1538         { uoff(u_error),        "offsetof(struct user, u_error)"        },
1539         { uoff(u_eosys),        "offsetof(struct user, u_eosys)"        },
1540         { uoff(u_ssave),        "offsetof(struct user, u_ssave)"        },
1541         { uoff(u_signal[0]),    "offsetof(struct user, u_signal)"       },
1542         { uoff(u_sigmask[0]),   "offsetof(struct user, u_sigmask)"      },
1543         { uoff(u_sigonstack),   "offsetof(struct user, u_sigonstack)"   },
1544         { uoff(u_sigintr),      "offsetof(struct user, u_sigintr)"      },
1545         { uoff(u_sigreset),     "offsetof(struct user, u_sigreset)"     },
1546         { uoff(u_oldmask),      "offsetof(struct user, u_oldmask)"      },
1547         { uoff(u_code),         "offsetof(struct user, u_code)"         },
1548         { uoff(u_addr),         "offsetof(struct user, u_addr)"         },
1549         { uoff(u_sigstack),     "offsetof(struct user, u_sigstack)"     },
1550         { uoff(u_ofile),        "offsetof(struct user, u_ofile)"        },
1551         { uoff(u_pofile),       "offsetof(struct user, u_pofile)"       },
1552         { uoff(u_ofile_arr[0]), "offsetof(struct user, u_ofile_arr[0])" },
1553         { uoff(u_pofile_arr[0]),"offsetof(struct user, u_pofile_arr[0])"},
1554         { uoff(u_lastfile),     "offsetof(struct user, u_lastfile)"     },
1555         { uoff(u_cwd),          "offsetof(struct user, u_cwd)"          },
1556         { uoff(u_cdir),         "offsetof(struct user, u_cdir)"         },
1557         { uoff(u_rdir),         "offsetof(struct user, u_rdir)"         },
1558         { uoff(u_cmask),        "offsetof(struct user, u_cmask)"        },
1559         { uoff(u_ru),           "offsetof(struct user, u_ru)"           },
1560         { uoff(u_cru),          "offsetof(struct user, u_cru)"          },
1561         { uoff(u_timer[0]),     "offsetof(struct user, u_timer[0])"     },
1562         { uoff(u_XXX[0]),       "offsetof(struct user, u_XXX[0])"       },
1563         { uoff(u_ioch),         "offsetof(struct user, u_ioch)"         },
1564         { uoff(u_start),        "offsetof(struct user, u_start)"        },
1565         { uoff(u_acflag),       "offsetof(struct user, u_acflag)"       },
1566         { uoff(u_prof.pr_base), "offsetof(struct user, u_prof.pr_base)" },
1567         { uoff(u_prof.pr_size), "offsetof(struct user, u_prof.pr_size)" },
1568         { uoff(u_prof.pr_off),  "offsetof(struct user, u_prof.pr_off)"  },
1569         { uoff(u_prof.pr_scale),"offsetof(struct user, u_prof.pr_scale)"},
1570         { uoff(u_rlimit[0]),    "offsetof(struct user, u_rlimit)"       },
1571         { uoff(u_exdata.Ux_A),  "offsetof(struct user, u_exdata.Ux_A)"  },
1572         { uoff(u_exdata.ux_shell[0]),"offsetof(struct user, u_exdata.ux_shell[0])"},
1573         { uoff(u_lofault),      "offsetof(struct user, u_lofault)"      },
1574 #endif /* SUNOS4 */
1575         { sizeof(struct user),  "sizeof(struct user)"                   },
1576         { 0,                    NULL                                    },
1577 };
1578
1579 int
1580 sys_ptrace(tcp)
1581 struct tcb *tcp;
1582 {
1583         char *cmd;
1584         struct xlat *x;
1585         long addr;
1586
1587         cmd = xlookup(ptrace_cmds, tcp->u_arg[0]);
1588         if (!cmd)
1589                 cmd = "PTRACE_???";
1590         if (entering(tcp)) {
1591                 tprintf("%s, %lu, ", cmd, tcp->u_arg[1]);
1592                 addr = tcp->u_arg[2];
1593                 if (tcp->u_arg[0] == PTRACE_PEEKUSER
1594                         || tcp->u_arg[0] == PTRACE_POKEUSER) {
1595                         for (x = struct_user_offsets; x->str; x++) {
1596                                 if (x->val >= addr)
1597                                         break;
1598                         }
1599                         if (!x->str)
1600                                 tprintf("%#lx, ", addr);
1601                         else if (x->val > addr && x != struct_user_offsets) {
1602                                 x--;
1603                                 tprintf("%s + %ld, ", x->str, addr - x->val);
1604                         }
1605                         else
1606                                 tprintf("%s, ", x->str);
1607                 }
1608                 else
1609                         tprintf("%#lx, ", tcp->u_arg[2]);
1610 #ifdef LINUX
1611                 switch (tcp->u_arg[0]) {
1612                 case PTRACE_PEEKDATA:
1613                 case PTRACE_PEEKTEXT:
1614                 case PTRACE_PEEKUSER:
1615                         break;
1616                 case PTRACE_CONT:
1617                 case PTRACE_SINGLESTEP:
1618                 case PTRACE_SYSCALL:
1619                 case PTRACE_DETACH:
1620                         printsignal(tcp->u_arg[3]);
1621                         break;
1622                 default:
1623                         tprintf("%#lx", tcp->u_arg[3]);
1624                         break;
1625                 }
1626         } else {
1627                 switch (tcp->u_arg[0]) {
1628                 case PTRACE_PEEKDATA:
1629                 case PTRACE_PEEKTEXT:
1630                 case PTRACE_PEEKUSER:
1631                         printnum(tcp, tcp->u_arg[3], "%#x");
1632                         break;
1633                 }
1634         }
1635 #endif /* LINUX */
1636 #ifdef SUNOS4
1637                 if (tcp->u_arg[0] == PTRACE_WRITEDATA ||
1638                         tcp->u_arg[0] == PTRACE_WRITETEXT) {
1639                         tprintf("%lu, ", tcp->u_arg[3]);
1640                         printstr(tcp, tcp->u_arg[4], tcp->u_arg[3]);
1641                 } else if (tcp->u_arg[0] != PTRACE_READDATA &&
1642                                 tcp->u_arg[0] != PTRACE_READTEXT) {
1643                         tprintf("%#lx", tcp->u_arg[3]);
1644                 }
1645         } else {
1646                 if (tcp->u_arg[0] == PTRACE_READDATA ||
1647                         tcp->u_arg[0] == PTRACE_READTEXT) {
1648                         tprintf("%lu, ", tcp->u_arg[3]);
1649                         printstr(tcp, tcp->u_arg[4], tcp->u_arg[3]);
1650                 }
1651         }
1652 #endif /* SUNOS4 */
1653         return 0;
1654 }
1655
1656 #endif /* !SVR4 */