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