]> granicus.if.org Git - strace/blob - process.c
2003-09-06 Dmitry V. Levin <ldv@altlinux.org>
[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  * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
6  * Copyright (c) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
7  *                     Linux for s390 port by D.J. Barrow
8  *                    <barrow_dj@mail.yahoo.com,djbarrow@de.ibm.com>
9  * Copyright (c) 2000 PocketPenguins Inc.  Linux for Hitachi SuperH
10  *                    port by Greg Banks <gbanks@pocketpenguins.com>
11
12  *
13  * All rights reserved.
14  *
15  * Redistribution and use in source and binary forms, with or without
16  * modification, are permitted provided that the following conditions
17  * are met:
18  * 1. Redistributions of source code must retain the above copyright
19  *    notice, this list of conditions and the following disclaimer.
20  * 2. Redistributions in binary form must reproduce the above copyright
21  *    notice, this list of conditions and the following disclaimer in the
22  *    documentation and/or other materials provided with the distribution.
23  * 3. The name of the author may not be used to endorse or promote products
24  *    derived from this software without specific prior written permission.
25  *
26  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
27  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
28  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
30  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
31  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36  *
37  *      $Id$
38  */
39
40 #include "defs.h"
41
42 #include <fcntl.h>
43 #include <sys/stat.h>
44 #include <sys/time.h>
45 #include <sys/wait.h>
46 #include <sys/resource.h>
47 #include <sys/utsname.h>
48 #include <sys/user.h>
49 #include <sys/syscall.h>
50 #include <signal.h>
51 #ifdef SUNOS4
52 #include <machine/reg.h>
53 #endif /* SUNOS4 */
54
55 #ifdef FREEBSD
56 #include <sys/ptrace.h>
57 #endif
58
59 #if HAVE_ASM_REG_H
60 #ifdef SPARC
61 #  define fpq kernel_fpq
62 #  define fq kernel_fq
63 #  define fpu kernel_fpu
64 #endif
65 #include <asm/reg.h>
66 #ifdef SPARC
67 #  undef fpq
68 #  undef fq
69 #  undef fpu
70 #endif
71 #endif /* HAVE_ASM_REG_H */
72
73 #ifdef HAVE_SYS_REG_H
74 # include <sys/reg.h>
75 #ifndef PTRACE_PEEKUSR
76 # define PTRACE_PEEKUSR PTRACE_PEEKUSER
77 #endif
78 #ifndef PTRACE_POKEUSR
79 # define PTRACE_POKEUSR PTRACE_POKEUSER
80 #endif
81 #endif
82
83 #ifdef HAVE_LINUX_PTRACE_H
84 #undef PTRACE_SYSCALL
85 #include <linux/ptrace.h>
86 #endif
87
88 #ifdef HAVE_LINUX_FUTEX_H
89 #include <linux/futex.h>
90 #endif
91 #if defined LINUX
92 # ifndef FUTEX_WAIT
93 #  define FUTEX_WAIT 0
94 # endif
95 # ifndef FUTEX_WAKE
96 #  define FUTEX_WAKE 1
97 # endif
98 # ifndef FUTEX_FD
99 #  define FUTEX_FD 2
100 # endif
101 # ifndef FUTEX_REQUEUE
102 #  define FUTEX_REQUEUE 3
103 # endif
104 #endif
105
106 #ifdef LINUX
107 #include <asm/posix_types.h>
108 #undef GETGROUPS_T
109 #define GETGROUPS_T __kernel_gid_t
110 #undef GETGROUPS32_T
111 #define GETGROUPS32_T __kernel_gid32_t
112 #endif /* LINUX */
113
114 #if defined(LINUX) && defined(IA64)
115 # include <asm/ptrace_offsets.h>
116 # include <asm/rse.h>
117 #endif
118
119 #ifdef HAVE_PRCTL
120 #include <sys/prctl.h>
121 #endif
122
123 #ifndef WCOREDUMP
124 #define WCOREDUMP(status) ((status) & 0200)
125 #endif
126
127 /* WTA: this was `&& !defined(LINUXSPARC)', this seems unneeded though? */
128 #if defined(HAVE_PRCTL)
129 static struct xlat prctl_options[] = {
130 #ifdef PR_MAXPROCS
131         { PR_MAXPROCS,          "PR_MAXPROCS"           },
132 #endif
133 #ifdef PR_ISBLOCKED
134         { PR_ISBLOCKED,         "PR_ISBLOCKED"          },
135 #endif
136 #ifdef PR_SETSTACKSIZE
137         { PR_SETSTACKSIZE,      "PR_SETSTACKSIZE"       },
138 #endif
139 #ifdef PR_GETSTACKSIZE
140         { PR_GETSTACKSIZE,      "PR_GETSTACKSIZE"       },
141 #endif
142 #ifdef PR_MAXPPROCS
143         { PR_MAXPPROCS,         "PR_MAXPPROCS"          },
144 #endif
145 #ifdef PR_UNBLKONEXEC
146         { PR_UNBLKONEXEC,       "PR_UNBLKONEXEC"        },
147 #endif
148 #ifdef PR_ATOMICSIM
149         { PR_ATOMICSIM,         "PR_ATOMICSIM"          },
150 #endif
151 #ifdef PR_SETEXITSIG
152         { PR_SETEXITSIG,        "PR_SETEXITSIG"         },
153 #endif
154 #ifdef PR_RESIDENT
155         { PR_RESIDENT,          "PR_RESIDENT"           },
156 #endif
157 #ifdef PR_ATTACHADDR
158         { PR_ATTACHADDR,        "PR_ATTACHADDR"         },
159 #endif
160 #ifdef PR_DETACHADDR
161         { PR_DETACHADDR,        "PR_DETACHADDR"         },
162 #endif
163 #ifdef PR_TERMCHILD
164         { PR_TERMCHILD,         "PR_TERMCHILD"          },
165 #endif
166 #ifdef PR_GETSHMASK
167         { PR_GETSHMASK,         "PR_GETSHMASK"          },
168 #endif
169 #ifdef PR_GETNSHARE
170         { PR_GETNSHARE,         "PR_GETNSHARE"          },
171 #endif
172 #if defined(PR_SET_PDEATHSIG)
173         { PR_SET_PDEATHSIG,     "PR_SET_PDEATHSIG"      },
174 #endif
175 #ifdef PR_COREPID
176         { PR_COREPID,           "PR_COREPID"            },
177 #endif
178 #ifdef PR_ATTACHADDRPERM
179         { PR_ATTACHADDRPERM,    "PR_ATTACHADDRPERM"     },
180 #endif
181 #ifdef PR_PTHREADEXIT
182         { PR_PTHREADEXIT,       "PR_PTHREADEXIT"        },
183 #endif
184 #ifdef PR_SET_PDEATHSIG
185         { PR_SET_PDEATHSIG,     "PR_SET_PDEATHSIG"      },
186 #endif
187 #ifdef PR_GET_PDEATHSIG
188         { PR_GET_PDEATHSIG,     "PR_GET_PDEATHSIG"      },
189 #endif
190 #ifdef PR_GET_UNALIGN
191         { PR_GET_UNALIGN,       "PR_GET_UNALIGN"        },
192 #endif
193 #ifdef PR_SET_UNALIGN
194         { PR_SET_UNALIGN,       "PR_SET_UNALIGN"        },
195 #endif
196 #ifdef PR_GET_KEEPCAPS
197         { PR_GET_KEEPCAPS,      "PR_GET_KEEP_CAPS"      },
198 #endif
199 #ifdef PR_SET_KEEPCAPS
200         { PR_SET_KEEPCAPS,      "PR_SET_KEEP_CAPS"      },
201 #endif
202         { 0,                    NULL                    },
203 };
204
205
206 const char *
207 unalignctl_string (unsigned int ctl)
208 {
209         static char buf[16];
210
211         switch (ctl) {
212 #ifdef PR_UNALIGN_NOPRINT
213               case PR_UNALIGN_NOPRINT:
214                 return "NOPRINT";
215 #endif
216 #ifdef PR_UNALIGN_SIGBUS
217               case PR_UNALIGN_SIGBUS:
218                 return "SIGBUS";
219 #endif
220               default:
221                 break;
222         }
223         sprintf(buf, "%x", ctl);
224         return buf;
225 }
226
227
228 int
229 sys_prctl(tcp)
230 struct tcb *tcp;
231 {
232         int i;
233
234         if (entering(tcp)) {
235                 printxval(prctl_options, tcp->u_arg[0], "PR_???");
236                 switch (tcp->u_arg[0]) {
237 #ifdef PR_GETNSHARE
238                 case PR_GETNSHARE:
239                         break;
240 #endif
241 #ifdef PR_SET_DEATHSIG
242                 case PR_GET_PDEATHSIG:
243                         break;
244 #endif
245 #ifdef PR_SET_UNALIGN
246                 case PR_SET_UNALIGN:
247                         tprintf(", %s", unalignctl_string(tcp->u_arg[1]));
248                         break;
249 #endif
250 #ifdef PR_GET_UNALIGN
251                 case PR_GET_UNALIGN:
252                         tprintf(", %#lx", tcp->u_arg[1]);
253                         break;
254 #endif
255                 default:
256                         for (i = 1; i < tcp->u_nargs; i++)
257                                 tprintf(", %#lx", tcp->u_arg[i]);
258                         break;
259                 }
260         } else {
261                 switch (tcp->u_arg[0]) {
262 #ifdef PR_GET_PDEATHSIG
263                 case PR_GET_PDEATHSIG:
264                         for (i=1; i<tcp->u_nargs; i++)
265                                 tprintf(", %#lx", tcp->u_arg[i]);
266                         break;
267 #endif
268 #ifdef PR_SET_UNALIGN
269                 case PR_SET_UNALIGN:
270                         break;
271 #endif
272 #ifdef PR_GET_UNALIGN
273                 case PR_GET_UNALIGN:
274                 {
275                         int ctl;
276
277                         umove(tcp, tcp->u_arg[1], &ctl);
278                         tcp->auxstr = unalignctl_string(ctl);
279                         return RVAL_STR;
280                 }
281 #endif
282                 default:
283                         break;
284                 }
285         }
286         return 0;
287 }
288
289 #endif /* HAVE_PRCTL */
290
291 int
292 sys_gethostid(tcp)
293 struct tcb *tcp;
294 {
295         if (exiting(tcp))
296                 return RVAL_HEX;
297         return 0;
298 }
299
300 int
301 sys_sethostname(tcp)
302 struct tcb *tcp;
303 {
304         if (entering(tcp)) {
305                 printpathn(tcp, tcp->u_arg[0], tcp->u_arg[1]);
306                 tprintf(", %lu", tcp->u_arg[1]);
307         }
308         return 0;
309 }
310
311 int
312 sys_gethostname(tcp)
313 struct tcb *tcp;
314 {
315         if (exiting(tcp)) {
316                 if (syserror(tcp))
317                         tprintf("%#lx", tcp->u_arg[0]);
318                 else
319                         printpath(tcp, tcp->u_arg[0]);
320                 tprintf(", %lu", tcp->u_arg[1]);
321         }
322         return 0;
323 }
324
325 int
326 sys_setdomainname(tcp)
327 struct tcb *tcp;
328 {
329         if (entering(tcp)) {
330                 printpathn(tcp, tcp->u_arg[0], tcp->u_arg[1]);
331                 tprintf(", %lu", tcp->u_arg[1]);
332         }
333         return 0;
334 }
335
336 #if !defined(LINUX)
337
338 int
339 sys_getdomainname(tcp)
340 struct tcb *tcp;
341 {
342         if (exiting(tcp)) {
343                 if (syserror(tcp))
344                         tprintf("%#lx", tcp->u_arg[0]);
345                 else
346                         printpath(tcp, tcp->u_arg[0]);
347                 tprintf(", %lu", tcp->u_arg[1]);
348         }
349         return 0;
350 }
351 #endif /* !LINUX */
352
353 int
354 sys_exit(tcp)
355 struct tcb *tcp;
356 {
357         if (exiting(tcp)) {
358                 fprintf(stderr, "_exit returned!\n");
359                 return -1;
360         }
361         /* special case: we stop tracing this process, finish line now */
362         tprintf("%ld) ", tcp->u_arg[0]);
363         tabto(acolumn);
364         tprintf("= ?");
365         printtrailer(tcp);
366         return 0;
367 }
368
369 int
370 internal_exit(tcp)
371 struct tcb *tcp;
372 {
373         if (entering(tcp)) {
374                 tcp->flags |= TCB_EXITING;
375 #ifdef __NR_exit_group
376                 if (tcp->scno == __NR_exit_group)
377                         tcp->flags |= TCB_GROUP_EXITING;
378 #endif
379         }
380         return 0;
381 }
382
383 /* TCP is creating a child we want to follow.
384    If there will be space in tcbtab for it, set TCB_FOLLOWFORK and return 0.
385    If not, clear TCB_FOLLOWFORK, print an error, and return 1.  */
386 static int
387 fork_tcb(struct tcb *tcp)
388 {
389         if (nprocs == tcbtabsize) {
390                 /* Allocate some more TCBs and expand the table.
391                    We don't want to relocate the TCBs because our
392                    callers have pointers and it would be a pain.
393                    So tcbtab is a table of pointers.  Since we never
394                    free the TCBs, we allocate a single chunk of many.  */
395                 struct tcb **newtab = (struct tcb **)
396                         realloc(tcbtab, 2 * tcbtabsize * sizeof tcbtab[0]);
397                 struct tcb *newtcbs = (struct tcb *) calloc(tcbtabsize,
398                                                             sizeof *newtcbs);
399                 int i;
400                 if (newtab == NULL || newtcbs == NULL) {
401                         if (newtab != NULL)
402                                 free(newtab);
403                         tcp->flags &= ~TCB_FOLLOWFORK;
404                         fprintf(stderr, "sys_fork: tcb table full\n");
405                         return 1;
406                 }
407                 for (i = tcbtabsize; i < 2 * tcbtabsize; ++i)
408                         newtab[i] = &newtcbs[i - tcbtabsize];
409                 tcbtabsize *= 2;
410                 tcbtab = newtab;
411         }
412
413         tcp->flags |= TCB_FOLLOWFORK;
414         return 0;
415 }
416
417 #ifdef USE_PROCFS
418
419 int
420 sys_fork(tcp)
421 struct tcb *tcp;
422 {
423         if (exiting(tcp)) {
424                 if (getrval2(tcp)) {
425                         tcp->auxstr = "child process";
426                         return RVAL_UDECIMAL | RVAL_STR;
427                 }
428         }
429         return 0;
430 }
431
432 #if UNIXWARE > 2
433
434 int
435 sys_rfork(tcp)
436 struct tcb *tcp;
437 {
438         if (entering(tcp)) {
439                 tprintf ("%ld", tcp->u_arg[0]);
440         }
441         else {
442                 if (getrval2(tcp)) {
443                         tcp->auxstr = "child process";
444                         return RVAL_UDECIMAL | RVAL_STR;
445                 }
446         }
447         return 0;
448 }
449
450 #endif
451
452 int
453 internal_fork(tcp)
454 struct tcb *tcp;
455 {
456         struct tcb *tcpchild;
457
458         if (exiting(tcp)) {
459 #ifdef SYS_rfork
460                 if (tcp->scno == SYS_rfork && !(tcp->u_arg[0]&RFPROC))
461                         return 0;
462 #endif
463                 if (getrval2(tcp))
464                         return 0;
465                 if (!followfork)
466                         return 0;
467                 if (fork_tcb(tcp))
468                         return 0;
469                 if (syserror(tcp))
470                         return 0;
471                 if ((tcpchild = alloctcb(tcp->u_rval)) == NULL) {
472                         fprintf(stderr, "sys_fork: tcb table full\n");
473                         return 0;
474                 }
475                 if (proc_open(tcpchild, 2) < 0)
476                         droptcb(tcpchild);
477         }
478         return 0;
479 }
480
481 #else /* !USE_PROCFS */
482
483 #ifdef LINUX
484
485 /* defines copied from linux/sched.h since we can't include that
486  * ourselves (it conflicts with *lots* of libc includes)
487  */
488 #define CSIGNAL         0x000000ff      /* signal mask to be sent at exit */
489 #define CLONE_VM        0x00000100      /* set if VM shared between processes */
490 #define CLONE_FS        0x00000200      /* set if fs info shared between processes */
491 #define CLONE_FILES     0x00000400      /* set if open files shared between processes */
492 #define CLONE_SIGHAND   0x00000800      /* set if signal handlers shared */
493 #define CLONE_IDLETASK  0x00001000      /* kernel-only flag */
494 #define CLONE_PTRACE    0x00002000      /* set if we want to let tracing continue on the child too */
495 #define CLONE_VFORK     0x00004000      /* set if the parent wants the child to wake it up on mm_release */
496 #define CLONE_PARENT    0x00008000      /* set if we want to have the same parent as the cloner */
497 #define CLONE_THREAD    0x00010000      /* Same thread group? */
498 #define CLONE_NEWNS     0x00020000      /* New namespace group? */
499 #define CLONE_SYSVSEM   0x00040000      /* share system V SEM_UNDO semantics */
500 #define CLONE_SETTLS    0x00080000      /* create a new TLS for the child */
501 #define CLONE_PARENT_SETTID     0x00100000      /* set the TID in the parent */
502 #define CLONE_CHILD_CLEARTID    0x00200000      /* clear the TID in the child */
503 #define CLONE_DETACHED          0x00400000      /* parent wants no child-exit signal */
504 #define CLONE_UNTRACED          0x00800000      /* set if the tracing process can't force CLONE_PTRACE on this clone */
505 #define CLONE_CHILD_SETTID      0x01000000      /* set the TID in the child */
506
507 static struct xlat clone_flags[] = {
508     { CLONE_VM,         "CLONE_VM"      },
509     { CLONE_FS,         "CLONE_FS"      },
510     { CLONE_FILES,      "CLONE_FILES"   },
511     { CLONE_SIGHAND,    "CLONE_SIGHAND" },
512     { CLONE_IDLETASK,   "CLONE_IDLETASK"},
513     { CLONE_PTRACE,     "CLONE_PTRACE"  },
514     { CLONE_VFORK,      "CLONE_VFORK"   },
515     { CLONE_PARENT,     "CLONE_PARENT"  },
516     { CLONE_THREAD,     "CLONE_THREAD" },
517     { CLONE_NEWNS,      "CLONE_NEWNS" },
518     { CLONE_SYSVSEM,    "CLONE_SYSVSEM" },
519     { CLONE_SETTLS,     "CLONE_SETTLS" },
520     { CLONE_PARENT_SETTID,"CLONE_PARENT_SETTID" },
521     { CLONE_CHILD_CLEARTID,"CLONE_CHILD_CLEARTID" },
522     { CLONE_DETACHED,   "CLONE_DETACHED" },
523     { CLONE_UNTRACED,   "CLONE_UNTRACED" },
524     { CLONE_CHILD_SETTID,"CLONE_CHILD_SETTID" },
525     { 0,                NULL            },
526 };
527
528 # ifdef I386
529 #  include <asm/ldt.h>
530 extern void print_ldt_entry();
531 # endif
532
533 # if defined IA64
534 #  define ARG_FLAGS     0
535 #  define ARG_STACK     1
536 #  define ARG_STACKSIZE (tcp->scno == SYS_clone2 ? 2 : -1)
537 #  define ARG_PTID      (tcp->scno == SYS_clone2 ? 3 : 2)
538 #  define ARG_CTID      (tcp->scno == SYS_clone2 ? 4 : 3)
539 #  define ARG_TLS       (tcp->scno == SYS_clone2 ? 5 : 4)
540 # elif defined S390 || defined S390X
541 #  define ARG_STACK     0
542 #  define ARG_FLAGS     1
543 #  define ARG_PTID      2
544 #  define ARG_CTID      3
545 #  define ARG_TLS       4
546 # elif defined X86_64 || defined ALPHA
547 #  define ARG_FLAGS     0
548 #  define ARG_STACK     1
549 #  define ARG_PTID      2
550 #  define ARG_CTID      3
551 #  define ARG_TLS       4
552 # else
553 #  define ARG_FLAGS     0
554 #  define ARG_STACK     1
555 #  define ARG_PTID      2
556 #  define ARG_TLS       3
557 #  define ARG_CTID      4
558 # endif
559
560 int
561 sys_clone(tcp)
562 struct tcb *tcp;
563 {
564         if (exiting(tcp)) {
565                 unsigned long flags = tcp->u_arg[ARG_FLAGS];
566                 tprintf("child_stack=%#lx, ", tcp->u_arg[ARG_STACK]);
567 # ifdef ARG_STACKSIZE
568                 if (ARG_STACKSIZE != -1)
569                         tprintf("stack_size=%#lx, ",
570                                 tcp->u_arg[ARG_STACKSIZE]);
571 # endif
572                 tprintf("flags=");
573                 if (printflags(clone_flags, flags &~ CSIGNAL) == 0)
574                         tprintf("0");
575                 if ((flags & CSIGNAL) != 0)
576                         tprintf("|%s", signame(flags & CSIGNAL));
577                 if ((flags & (CLONE_PARENT_SETTID|CLONE_CHILD_SETTID
578                               |CLONE_CHILD_CLEARTID|CLONE_SETTLS)) == 0)
579                         return 0;
580                 if (flags & CLONE_PARENT_SETTID)
581                         tprintf(", parent_tidptr=%#lx", tcp->u_arg[ARG_PTID]);
582                 if (flags & CLONE_SETTLS) {
583 # ifdef I386
584                         struct modify_ldt_ldt_s copy;
585                         if (umove(tcp, tcp->u_arg[ARG_TLS], &copy) != -1) {
586                                 tprintf(", {entry_number:%d, ",
587                                         copy.entry_number);
588                                 if (!verbose(tcp))
589                                         tprintf("...}");
590                                 else
591                                         print_ldt_entry(&copy);
592                         }
593                         else
594 # endif
595                                 tprintf(", tls=%#lx", tcp->u_arg[ARG_TLS]);
596                 }
597                 if (flags & (CLONE_CHILD_SETTID|CLONE_CHILD_CLEARTID))
598                         tprintf(", child_tidptr=%#lx", tcp->u_arg[ARG_CTID]);
599         }
600         return 0;
601 }
602 #endif
603
604 int
605 sys_fork(tcp)
606 struct tcb *tcp;
607 {
608         if (exiting(tcp))
609                 return RVAL_UDECIMAL;
610         return 0;
611 }
612
613 int
614 change_syscall(tcp, new)
615 struct tcb *tcp;
616 int new;
617 {
618 #if defined(LINUX)
619 #if defined(I386)
620         /* Attempt to make vfork into fork, which we can follow. */
621         if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_EAX * 4), new) < 0)
622                 return -1;
623         return 0;
624 #elif defined(X86_64)
625         /* Attempt to make vfork into fork, which we can follow. */
626         if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_RAX * 8), new) < 0)
627                 return -1;
628         return 0;
629 #elif defined(POWERPC)
630         if (ptrace(PTRACE_POKEUSER, tcp->pid,
631                    (char*)(sizeof(unsigned long)*PT_R0), new) < 0)
632                 return -1;
633        return 0;
634 #elif defined(S390) || defined(S390X)
635         /* s390 linux after 2.4.7 has a hook in entry.S to allow this */
636         if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GPR2), new)<0)
637                 return -1;
638         return 0;
639 #elif defined(M68K)
640         if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_ORIG_D0), new)<0)
641                 return -1;
642         return 0;
643 #elif defined(SPARC)
644         struct regs regs;
645         if (ptrace(PTRACE_GETREGS, tcp->pid, (char*)&regs, 0)<0)
646                 return -1;
647         regs.r_g1=new;
648         if (ptrace(PTRACE_SETREGS, tcp->pid, (char*)&regs, 0)<0)
649                 return -1;
650         return 0;
651 #elif defined(MIPS)
652         if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), new)<0)
653                 return -1;
654         return 0;
655 #elif defined(ALPHA)
656         if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), new)<0)
657                 return -1;
658         return 0;
659 #elif defined(IA64)
660         if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R15), new)<0)
661                 return -1;
662         return 0;
663 #elif defined(HPPA)
664         if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR20), new)<0)
665                 return -1;
666         return 0;
667 #elif defined(SH)
668        if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*(REG_REG0+3)), new)<0)
669                return -1;
670        return 0;
671 #elif defined(SH64)
672        /* Top half of reg encodes the no. of args n as 0x1n.
673           Assume 0 args as kernel never actually checks... */
674        if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_SYSCALL),
675                                    0x100000 | new) < 0)
676                        return -1;
677        return 0;
678 #else
679 #warning Do not know how to handle change_syscall for this architecture
680 #endif /* architecture */
681 #endif /* LINUX */
682         return -1;
683 }
684
685 int
686 setarg(tcp, argnum)
687         struct tcb *tcp;
688         int argnum;
689 {
690 #if defined (IA64)
691         {
692                 unsigned long *bsp, *ap;
693
694                 if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) , 0)
695                         return -1;
696
697                 ap = ia64_rse_skip_regs(bsp, argnum);
698                 errno = 0;
699                 ptrace(PTRACE_POKEDATA, tcp->pid, (char *) ap, tcp->u_arg[argnum]);
700                 if (errno)
701                         return -1;
702
703         }
704 #elif defined(I386)
705         {
706                 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*argnum), tcp->u_arg[argnum]);
707                 if (errno)
708                         return -1;
709         }
710 #elif defined(X86_64)
711         {
712                 ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(8*(long)argnum), tcp->u_arg[argnum]);
713                 if (errno)
714                         return -1;
715         }
716 #elif defined(POWERPC)
717 #ifndef PT_ORIG_R3
718 #define PT_ORIG_R3 34
719 #endif
720         {
721                 ptrace(PTRACE_POKEUSER, tcp->pid,
722                        (char*)((argnum==0 ? PT_ORIG_R3 : argnum+PT_R3)*sizeof(unsigned long)),
723                        tcp->u_arg[argnum]);
724                 if (errno)
725                         return -1;
726         }
727 #elif defined(MIPS)
728         {
729                 errno = 0;
730                 if (argnum < 4)
731                         ptrace(PTRACE_POKEUSER, tcp->pid,
732                                (char*)(REG_A0 + argnum), tcp->u_arg[argnum]);
733                 else {
734                         unsigned long *sp;
735
736                         if (upeek(tcp->pid, REG_SP, (long *) &sp) , 0)
737                                 return -1;
738
739                         ptrace(PTRACE_POKEDATA, tcp->pid,
740                                (char*)(sp + argnum - 4), tcp->u_arg[argnum]);
741                 }
742                 if (errno)
743                         return -1;
744         }
745 #elif defined(S390) || defined(S390X)
746         {
747                 if(argnum <= 5)
748                         ptrace(PTRACE_POKEUSER, tcp->pid,
749                                (char *) (argnum==0 ? PT_ORIGGPR2 :
750                                PT_GPR2 + argnum*sizeof(long)),
751                                tcp->u_arg[argnum]);
752                 else
753                         return -E2BIG;
754                 if (errno)
755                         return -1;
756         }
757 #else
758 # warning Sorry, setargs not implemented for this architecture.
759 #endif
760         return 0;
761 }
762
763 #if defined SYS_clone || defined SYS_clone2
764 int
765 internal_clone(tcp)
766 struct tcb *tcp;
767 {
768         struct tcb *tcpchild;
769         int pid;
770         if (entering(tcp)) {
771                 if (!followfork)
772                         return 0;
773                 if (fork_tcb(tcp))
774                         return 0;
775                 if (setbpt(tcp) < 0)
776                         return 0;
777         } else {
778                 int bpt = tcp->flags & TCB_BPTSET;
779
780                 if (!(tcp->flags & TCB_FOLLOWFORK))
781                         return 0;
782
783                 if (syserror(tcp)) {
784                         if (bpt)
785                                 clearbpt(tcp);
786                         return 0;
787                 }
788
789                 pid = tcp->u_rval;
790
791 #ifdef CLONE_PTRACE             /* See new setbpt code.  */
792                 tcpchild = pid2tcb(pid);
793                 if (tcpchild != NULL) {
794                         /* The child already reported its startup trap
795                            before the parent reported its syscall return.  */
796                         if ((tcpchild->flags
797                              & (TCB_STARTUP|TCB_ATTACHED|TCB_SUSPENDED))
798                             != (TCB_STARTUP|TCB_ATTACHED|TCB_SUSPENDED))
799                                 fprintf(stderr, "\
800 [preattached child %d of %d in weird state!]\n",
801                                         pid, tcp->pid);
802                 }
803                 else
804 #endif
805                 if ((tcpchild = alloctcb(pid)) == NULL) {
806                         if (bpt)
807                                 clearbpt(tcp);
808                         fprintf(stderr, " [tcb table full]\n");
809                         kill(pid, SIGKILL); /* XXX */
810                         return 0;
811                 }
812
813 #ifndef CLONE_PTRACE
814                 /* Attach to the new child */
815                 if (ptrace(PTRACE_ATTACH, pid, (char *) 1, 0) < 0) {
816                         if (bpt)
817                                 clearbpt(tcp);
818                         perror("PTRACE_ATTACH");
819                         fprintf(stderr, "Too late?\n");
820                         droptcb(tcpchild);
821                         return 0;
822                 }
823 #endif
824
825                 if (bpt)
826                         clearbpt(tcp);
827
828                 tcpchild->flags |= TCB_ATTACHED;
829                 /* Child has BPT too, must be removed on first occasion.  */
830                 if (bpt) {
831                         tcpchild->flags |= TCB_BPTSET;
832                         tcpchild->baddr = tcp->baddr;
833                         memcpy(tcpchild->inst, tcp->inst,
834                                 sizeof tcpchild->inst);
835                 }
836                 tcpchild->parent = tcp;
837                 tcp->nchildren++;
838                 if (tcpchild->flags & TCB_SUSPENDED) {
839                         /* The child was born suspended, due to our having
840                            forced CLONE_PTRACE.  */
841                         if (bpt)
842                                 clearbpt(tcpchild);
843
844                         tcpchild->flags &= ~(TCB_SUSPENDED|TCB_STARTUP);
845                         if (ptrace(PTRACE_SYSCALL, pid, (char *) 1, 0) < 0) {
846                                 perror("resume: ptrace(PTRACE_SYSCALL, ...)");
847                                 return -1;
848                         }
849
850                         if (!qflag)
851                                 fprintf(stderr, "\
852 Process %u resumed (parent %d ready)\n",
853                                         pid, tcp->pid);
854                 }
855                 else {
856                         newoutf(tcpchild);
857                         if (!qflag)
858                                 fprintf(stderr, "Process %d attached\n", pid);
859                 }
860
861 #ifdef TCB_CLONE_THREAD
862                 {
863                         /*
864                          * Save the flags used in this call,
865                          * in case we point TCP to our parent below.
866                          */
867                         int call_flags = tcp->u_arg[ARG_FLAGS];
868                         if ((tcp->flags & TCB_CLONE_THREAD) &&
869                             tcp->parent != NULL) {
870                                 /* The parent in this clone is itself a
871                                    thread belonging to another process.
872                                    There is no meaning to the parentage
873                                    relationship of the new child with the
874                                    thread, only with the process.  We
875                                    associate the new thread with our
876                                    parent.  Since this is done for every
877                                    new thread, there will never be a
878                                    TCB_CLONE_THREAD process that has
879                                    children.  */
880                                 --tcp->nchildren;
881                                 tcp = tcp->parent;
882                                 tcpchild->parent = tcp;
883                                 ++tcp->nchildren;
884                         }
885                         if (call_flags & CLONE_THREAD) {
886                                 tcpchild->flags |= TCB_CLONE_THREAD;
887                                 ++tcp->nclone_threads;
888                         }
889                         if (call_flags & CLONE_DETACHED) {
890                                 tcpchild->flags |= TCB_CLONE_DETACHED;
891                                 ++tcp->nclone_detached;
892                         }
893                 }
894 #endif
895
896         }
897         return 0;
898 }
899 #endif
900
901 int
902 internal_fork(tcp)
903 struct tcb *tcp;
904 {
905 #ifdef LINUX
906         /* We do special magic with clone for any clone or fork.  */
907         return internal_clone(tcp);
908 #else
909
910         struct tcb *tcpchild;
911         int pid;
912         int dont_follow = 0;
913
914 #ifdef SYS_vfork
915         if (tcp->scno == SYS_vfork) {
916                 /* Attempt to make vfork into fork, which we can follow. */
917                 if (!followvfork ||
918                     change_syscall(tcp, SYS_fork) < 0)
919                         dont_follow = 1;
920         }
921 #endif
922         if (entering(tcp)) {
923                 if (!followfork || dont_follow)
924                         return 0;
925                 if (fork_tcb(tcp))
926                         return 0;
927                 if (setbpt(tcp) < 0)
928                         return 0;
929         }
930         else {
931                 int bpt = tcp->flags & TCB_BPTSET;
932
933                 if (!(tcp->flags & TCB_FOLLOWFORK))
934                         return 0;
935                 if (bpt)
936                         clearbpt(tcp);
937
938                 if (syserror(tcp))
939                         return 0;
940
941                 pid = tcp->u_rval;
942                 if ((tcpchild = alloctcb(pid)) == NULL) {
943                         fprintf(stderr, " [tcb table full]\n");
944                         kill(pid, SIGKILL); /* XXX */
945                         return 0;
946                 }
947 #ifdef LINUX
948 #ifdef HPPA
949                 /* The child must have run before it can be attached. */
950                 /* This must be a bug in the parisc kernel, but I havn't
951                  * identified it yet.  Seems to be an issue associated
952                  * with attaching to a process (which sends it a signal)
953                  * before that process has ever been scheduled.  When
954                  * debugging, I started seeing crashes in
955                  * arch/parisc/kernel/signal.c:do_signal(), apparently
956                  * caused by r8 getting corrupt over the dequeue_signal()
957                  * call.  Didn't make much sense though...
958                  */
959                 {
960                         struct timeval tv;
961                         tv.tv_sec = 0;
962                         tv.tv_usec = 10000;
963                         select(0, NULL, NULL, NULL, &tv);
964                 }
965 #endif
966                 if (ptrace(PTRACE_ATTACH, pid, (char *) 1, 0) < 0) {
967                         perror("PTRACE_ATTACH");
968                         fprintf(stderr, "Too late?\n");
969                         droptcb(tcpchild);
970                         return 0;
971                 }
972 #endif /* LINUX */
973 #ifdef SUNOS4
974 #ifdef oldway
975                 /* The child must have run before it can be attached. */
976                 {
977                         struct timeval tv;
978                         tv.tv_sec = 0;
979                         tv.tv_usec = 10000;
980                         select(0, NULL, NULL, NULL, &tv);
981                 }
982                 if (ptrace(PTRACE_ATTACH, pid, (char *)1, 0) < 0) {
983                         perror("PTRACE_ATTACH");
984                         fprintf(stderr, "Too late?\n");
985                         droptcb(tcpchild);
986                         return 0;
987                 }
988 #else /* !oldway */
989                 /* Try to catch the new process as soon as possible. */
990                 {
991                         int i;
992                         for (i = 0; i < 1024; i++)
993                                 if (ptrace(PTRACE_ATTACH, pid, (char *) 1, 0) >= 0)
994                                         break;
995                         if (i == 1024) {
996                                 perror("PTRACE_ATTACH");
997                                 fprintf(stderr, "Too late?\n");
998                                 droptcb(tcpchild);
999                                 return 0;
1000                         }
1001                 }
1002 #endif /* !oldway */
1003 #endif /* SUNOS4 */
1004                 tcpchild->flags |= TCB_ATTACHED;
1005                 /* Child has BPT too, must be removed on first occasion */
1006                 if (bpt) {
1007                         tcpchild->flags |= TCB_BPTSET;
1008                         tcpchild->baddr = tcp->baddr;
1009                         memcpy(tcpchild->inst, tcp->inst,
1010                                 sizeof tcpchild->inst);
1011                 }
1012                 newoutf(tcpchild);
1013                 tcpchild->parent = tcp;
1014                 tcp->nchildren++;
1015                 if (!qflag)
1016                         fprintf(stderr, "Process %d attached\n", pid);
1017         }
1018         return 0;
1019 #endif
1020 }
1021
1022 #endif /* !USE_PROCFS */
1023
1024 #if defined(SUNOS4) || defined(LINUX) || defined(FREEBSD)
1025
1026 int
1027 sys_vfork(tcp)
1028 struct tcb *tcp;
1029 {
1030         if (exiting(tcp))
1031                 return RVAL_UDECIMAL;
1032         return 0;
1033 }
1034
1035 #endif /* SUNOS4 || LINUX || FREEBSD */
1036
1037 #ifndef LINUX
1038
1039 static char idstr[16];
1040
1041 int
1042 sys_getpid(tcp)
1043 struct tcb *tcp;
1044 {
1045         if (exiting(tcp)) {
1046                 sprintf(idstr, "ppid %lu", getrval2(tcp));
1047                 tcp->auxstr = idstr;
1048                 return RVAL_STR;
1049         }
1050         return 0;
1051 }
1052
1053 int
1054 sys_getuid(tcp)
1055 struct tcb *tcp;
1056 {
1057         if (exiting(tcp)) {
1058                 sprintf(idstr, "euid %lu", getrval2(tcp));
1059                 tcp->auxstr = idstr;
1060                 return RVAL_STR;
1061         }
1062         return 0;
1063 }
1064
1065 int
1066 sys_getgid(tcp)
1067 struct tcb *tcp;
1068 {
1069         if (exiting(tcp)) {
1070                 sprintf(idstr, "egid %lu", getrval2(tcp));
1071                 tcp->auxstr = idstr;
1072                 return RVAL_STR;
1073         }
1074         return 0;
1075 }
1076
1077 #endif /* !LINUX */
1078
1079 #ifdef LINUX
1080
1081 int
1082 sys_setuid(tcp)
1083 struct tcb *tcp;
1084 {
1085         if (entering(tcp)) {
1086                 tprintf("%u", (uid_t) tcp->u_arg[0]);
1087         }
1088         return 0;
1089 }
1090
1091 int
1092 sys_setgid(tcp)
1093 struct tcb *tcp;
1094 {
1095         if (entering(tcp)) {
1096                 tprintf("%u", (gid_t) tcp->u_arg[0]);
1097         }
1098         return 0;
1099 }
1100
1101 int
1102 sys_getresuid(tcp)
1103     struct tcb *tcp;
1104 {
1105         if (exiting(tcp)) {
1106                 __kernel_uid_t uid;
1107                 if (syserror(tcp))
1108                         tprintf("%#lx, %#lx, %#lx", tcp->u_arg[0],
1109                                 tcp->u_arg[1], tcp->u_arg[2]);
1110                 else {
1111                         if (umove(tcp, tcp->u_arg[0], &uid) < 0)
1112                                 tprintf("%#lx, ", tcp->u_arg[0]);
1113                         else
1114                                 tprintf("[%lu], ", (unsigned long) uid);
1115                         if (umove(tcp, tcp->u_arg[1], &uid) < 0)
1116                                 tprintf("%#lx, ", tcp->u_arg[1]);
1117                         else
1118                                 tprintf("[%lu], ", (unsigned long) uid);
1119                         if (umove(tcp, tcp->u_arg[2], &uid) < 0)
1120                                 tprintf("%#lx", tcp->u_arg[2]);
1121                         else
1122                                 tprintf("[%lu]", (unsigned long) uid);
1123                 }
1124         }
1125         return 0;
1126 }
1127
1128 int
1129 sys_getresgid(tcp)
1130 struct tcb *tcp;
1131 {
1132         if (exiting(tcp)) {
1133                 __kernel_gid_t gid;
1134                 if (syserror(tcp))
1135                         tprintf("%#lx, %#lx, %#lx", tcp->u_arg[0],
1136                                 tcp->u_arg[1], tcp->u_arg[2]);
1137                 else {
1138                         if (umove(tcp, tcp->u_arg[0], &gid) < 0)
1139                                 tprintf("%#lx, ", tcp->u_arg[0]);
1140                         else
1141                                 tprintf("[%lu], ", (unsigned long) gid);
1142                         if (umove(tcp, tcp->u_arg[1], &gid) < 0)
1143                                 tprintf("%#lx, ", tcp->u_arg[1]);
1144                         else
1145                                 tprintf("[%lu], ", (unsigned long) gid);
1146                         if (umove(tcp, tcp->u_arg[2], &gid) < 0)
1147                                 tprintf("%#lx", tcp->u_arg[2]);
1148                         else
1149                                 tprintf("[%lu]", (unsigned long) gid);
1150                 }
1151         }
1152         return 0;
1153 }
1154
1155 #endif /* LINUX */
1156
1157 int
1158 sys_setreuid(tcp)
1159 struct tcb *tcp;
1160 {
1161         if (entering(tcp)) {
1162                 printuid("", tcp->u_arg[0]);
1163                 printuid(", ", tcp->u_arg[1]);
1164         }
1165         return 0;
1166 }
1167
1168 int
1169 sys_setregid(tcp)
1170 struct tcb *tcp;
1171 {
1172         if (entering(tcp)) {
1173                 printuid("", tcp->u_arg[0]);
1174                 printuid(", ", tcp->u_arg[1]);
1175         }
1176         return 0;
1177 }
1178
1179 #if defined(LINUX) || defined(FREEBSD)
1180 int
1181 sys_setresuid(tcp)
1182      struct tcb *tcp;
1183 {
1184         if (entering(tcp)) {
1185                 printuid("", tcp->u_arg[0]);
1186                 printuid(", ", tcp->u_arg[1]);
1187                 printuid(", ", tcp->u_arg[2]);
1188         }
1189         return 0;
1190 }
1191 int
1192 sys_setresgid(tcp)
1193      struct tcb *tcp;
1194 {
1195         if (entering(tcp)) {
1196                 printuid("", tcp->u_arg[0]);
1197                 printuid(", ", tcp->u_arg[1]);
1198                 printuid(", ", tcp->u_arg[2]);
1199         }
1200         return 0;
1201 }
1202
1203 #endif /* LINUX || FREEBSD */
1204
1205 int
1206 sys_setgroups(tcp)
1207 struct tcb *tcp;
1208 {
1209         int i, len;
1210         GETGROUPS_T *gidset;
1211
1212         if (entering(tcp)) {
1213                 len = tcp->u_arg[0];
1214                 tprintf("%u, ", len);
1215                 if (len <= 0) {
1216                         tprintf("[]");
1217                         return 0;
1218                 }
1219                 gidset = (GETGROUPS_T *) malloc(len * sizeof(GETGROUPS_T));
1220                 if (gidset == NULL) {
1221                         fprintf(stderr, "sys_setgroups: out of memory\n");
1222                         return -1;
1223                 }
1224                 if (!verbose(tcp))
1225                         tprintf("%#lx", tcp->u_arg[1]);
1226                 else if (umoven(tcp, tcp->u_arg[1],
1227                     len * sizeof(GETGROUPS_T), (char *) gidset) < 0)
1228                         tprintf("[?]");
1229                 else {
1230                         tprintf("[");
1231                         for (i = 0; i < len; i++)
1232                                 tprintf("%s%lu", i ? ", " : "",
1233                                         (unsigned long) gidset[i]);
1234                         tprintf("]");
1235                 }
1236                 free((char *) gidset);
1237         }
1238         return 0;
1239 }
1240
1241 int
1242 sys_getgroups(tcp)
1243 struct tcb *tcp;
1244 {
1245         int i, len;
1246         GETGROUPS_T *gidset;
1247
1248         if (entering(tcp)) {
1249                 len = tcp->u_arg[0];
1250                 tprintf("%u, ", len);
1251         } else {
1252                 len = tcp->u_rval;
1253                 if (len <= 0) {
1254                         tprintf("[]");
1255                         return 0;
1256                 }
1257                 gidset = (GETGROUPS_T *) malloc(len * sizeof(GETGROUPS_T));
1258                 if (gidset == NULL) {
1259                         fprintf(stderr, "sys_getgroups: out of memory\n");
1260                         return -1;
1261                 }
1262                 if (!tcp->u_arg[1])
1263                         tprintf("NULL");
1264                 else if (!verbose(tcp) || tcp->u_arg[0] == 0)
1265                         tprintf("%#lx", tcp->u_arg[1]);
1266                 else if (umoven(tcp, tcp->u_arg[1],
1267                     len * sizeof(GETGROUPS_T), (char *) gidset) < 0)
1268                         tprintf("[?]");
1269                 else {
1270                         tprintf("[");
1271                         for (i = 0; i < len; i++)
1272                                 tprintf("%s%lu", i ? ", " : "",
1273                                         (unsigned long) gidset[i]);
1274                         tprintf("]");
1275                 }
1276                 free((char *)gidset);
1277         }
1278         return 0;
1279 }
1280
1281 #ifdef LINUX
1282 int
1283 sys_setgroups32(tcp)
1284 struct tcb *tcp;
1285 {
1286         int i, len;
1287         GETGROUPS32_T *gidset;
1288
1289         if (entering(tcp)) {
1290                 len = tcp->u_arg[0];
1291                 tprintf("%u, ", len);
1292                 if (len <= 0) {
1293                         tprintf("[]");
1294                         return 0;
1295                 }
1296                 gidset = (GETGROUPS32_T *) malloc(len * sizeof(GETGROUPS32_T));
1297                 if (gidset == NULL) {
1298                         fprintf(stderr, "sys_setgroups32: out of memory\n");
1299                         return -1;
1300                 }
1301                 if (!verbose(tcp))
1302                         tprintf("%#lx", tcp->u_arg[1]);
1303                 else if (umoven(tcp, tcp->u_arg[1],
1304                     len * sizeof(GETGROUPS32_T), (char *) gidset) < 0)
1305                         tprintf("[?]");
1306                 else {
1307                         tprintf("[");
1308                         for (i = 0; i < len; i++)
1309                                 tprintf("%s%lu", i ? ", " : "",
1310                                         (unsigned long) gidset[i]);
1311                         tprintf("]");
1312                 }
1313                 free((char *) gidset);
1314         }
1315         return 0;
1316 }
1317
1318 int
1319 sys_getgroups32(tcp)
1320 struct tcb *tcp;
1321 {
1322         int i, len;
1323         GETGROUPS32_T *gidset;
1324
1325         if (entering(tcp)) {
1326                 len = tcp->u_arg[0];
1327                 tprintf("%u, ", len);
1328         } else {
1329                 len = tcp->u_rval;
1330                 if (len <= 0) {
1331                         tprintf("[]");
1332                         return 0;
1333                 }
1334                 gidset = (GETGROUPS32_T *) malloc(len * sizeof(GETGROUPS32_T));
1335                 if (gidset == NULL) {
1336                         fprintf(stderr, "sys_getgroups32: out of memory\n");
1337                         return -1;
1338                 }
1339                 if (!tcp->u_arg[1])
1340                         tprintf("NULL");
1341                 else if (!verbose(tcp) || tcp->u_arg[0] == 0)
1342                         tprintf("%#lx", tcp->u_arg[1]);
1343                 else if (umoven(tcp, tcp->u_arg[1],
1344                     len * sizeof(GETGROUPS32_T), (char *) gidset) < 0)
1345                         tprintf("[?]");
1346                 else {
1347                         tprintf("[");
1348                         for (i = 0; i < len; i++)
1349                                 tprintf("%s%lu", i ? ", " : "",
1350                                         (unsigned long) gidset[i]);
1351                         tprintf("]");
1352                 }
1353                 free((char *)gidset);
1354         }
1355         return 0;
1356 }
1357 #endif /* LINUX */
1358
1359 int
1360 sys_setpgrp(tcp)
1361 struct tcb *tcp;
1362 {
1363         if (entering(tcp)) {
1364 #ifndef SVR4
1365                 tprintf("%lu, %lu", tcp->u_arg[0], tcp->u_arg[1]);
1366 #endif /* !SVR4 */
1367         }
1368         return 0;
1369 }
1370
1371 int
1372 sys_getpgrp(tcp)
1373 struct tcb *tcp;
1374 {
1375         if (entering(tcp)) {
1376 #ifndef SVR4
1377                 tprintf("%lu", tcp->u_arg[0]);
1378 #endif /* !SVR4 */
1379         }
1380         return 0;
1381 }
1382
1383 int
1384 sys_getsid(tcp)
1385 struct tcb *tcp;
1386 {
1387         if (entering(tcp)) {
1388                 tprintf("%lu", tcp->u_arg[0]);
1389         }
1390         return 0;
1391 }
1392
1393 int
1394 sys_setsid(tcp)
1395 struct tcb *tcp;
1396 {
1397         return 0;
1398 }
1399
1400 int
1401 sys_getpgid(tcp)
1402 struct tcb *tcp;
1403 {
1404         if (entering(tcp)) {
1405                 tprintf("%lu", tcp->u_arg[0]);
1406         }
1407         return 0;
1408 }
1409
1410 int
1411 sys_setpgid(tcp)
1412 struct tcb *tcp;
1413 {
1414         if (entering(tcp)) {
1415                 tprintf("%lu, %lu", tcp->u_arg[0], tcp->u_arg[1]);
1416         }
1417         return 0;
1418 }
1419
1420 #if UNIXWARE >= 2
1421
1422 #include <sys/privilege.h>
1423
1424
1425 static struct xlat procpriv_cmds [] = {
1426         { SETPRV,       "SETPRV"        },
1427         { CLRPRV,       "CLRPRV"        },
1428         { PUTPRV,       "PUTPRV"        },
1429         { GETPRV,       "GETPRV"        },
1430         { CNTPRV,       "CNTPRV"        },
1431         { 0,            NULL            },
1432 };
1433
1434
1435 static struct xlat procpriv_priv [] = {
1436         { P_OWNER,      "P_OWNER"       },
1437         { P_AUDIT,      "P_AUDIT"       },
1438         { P_COMPAT,     "P_COMPAT"      },
1439         { P_DACREAD,    "P_DACREAD"     },
1440         { P_DACWRITE,   "P_DACWRITE"    },
1441         { P_DEV,        "P_DEV"         },
1442         { P_FILESYS,    "P_FILESYS"     },
1443         { P_MACREAD,    "P_MACREAD"     },
1444         { P_MACWRITE,   "P_MACWRITE"    },
1445         { P_MOUNT,      "P_MOUNT"       },
1446         { P_MULTIDIR,   "P_MULTIDIR"    },
1447         { P_SETPLEVEL,  "P_SETPLEVEL"   },
1448         { P_SETSPRIV,   "P_SETSPRIV"    },
1449         { P_SETUID,     "P_SETUID"      },
1450         { P_SYSOPS,     "P_SYSOPS"      },
1451         { P_SETUPRIV,   "P_SETUPRIV"    },
1452         { P_DRIVER,     "P_DRIVER"      },
1453         { P_RTIME,      "P_RTIME"       },
1454         { P_MACUPGRADE, "P_MACUPGRADE"  },
1455         { P_FSYSRANGE,  "P_FSYSRANGE"   },
1456         { P_SETFLEVEL,  "P_SETFLEVEL"   },
1457         { P_AUDITWR,    "P_AUDITWR"     },
1458         { P_TSHAR,      "P_TSHAR"       },
1459         { P_PLOCK,      "P_PLOCK"       },
1460         { P_CORE,       "P_CORE"        },
1461         { P_LOADMOD,    "P_LOADMOD"     },
1462         { P_BIND,       "P_BIND"        },
1463         { P_ALLPRIVS,   "P_ALLPRIVS"    },
1464         { 0,            NULL            },
1465 };
1466
1467
1468 static struct xlat procpriv_type [] = {
1469         { PS_FIX,       "PS_FIX"        },
1470         { PS_INH,       "PS_INH"        },
1471         { PS_MAX,       "PS_MAX"        },
1472         { PS_WKG,       "PS_WKG"        },
1473         { 0,            NULL            },
1474 };
1475
1476
1477 static void
1478 printpriv(tcp, addr, len, opt)
1479 struct tcb *tcp;
1480 long addr;
1481 int len;
1482 struct xlat *opt;
1483 {
1484         priv_t buf [128];
1485         int max = verbose (tcp) ? sizeof buf / sizeof buf [0] : 10;
1486         int dots = len > max;
1487         int i;
1488
1489         if (len > max) len = max;
1490
1491         if (len <= 0 ||
1492             umoven (tcp, addr, len * sizeof buf[0], (char *) buf) < 0)
1493         {
1494                 tprintf ("%#lx", addr);
1495                 return;
1496         }
1497
1498         tprintf ("[");
1499
1500         for (i = 0; i < len; ++i) {
1501                 char *t, *p;
1502
1503                 if (i) tprintf (", ");
1504
1505                 if ((t = xlookup (procpriv_type, buf [i] & PS_TYPE)) &&
1506                     (p = xlookup (procpriv_priv, buf [i] & ~PS_TYPE)))
1507                 {
1508                         tprintf ("%s|%s", t, p);
1509                 }
1510                 else {
1511                         tprintf ("%#lx", buf [i]);
1512                 }
1513         }
1514
1515         if (dots) tprintf (" ...");
1516
1517         tprintf ("]");
1518 }
1519
1520
1521 int
1522 sys_procpriv(tcp)
1523 struct tcb *tcp;
1524 {
1525         if (entering(tcp)) {
1526                 printxval(procpriv_cmds, tcp->u_arg[0], "???PRV");
1527                 switch (tcp->u_arg[0]) {
1528                     case CNTPRV:
1529                         tprintf(", %#lx, %ld", tcp->u_arg[1], tcp->u_arg[2]);
1530                         break;
1531
1532                     case GETPRV:
1533                         break;
1534
1535                     default:
1536                         tprintf (", ");
1537                         printpriv (tcp, tcp->u_arg[1], tcp->u_arg[2]);
1538                         tprintf (", %ld", tcp->u_arg[2]);
1539                 }
1540         }
1541         else if (tcp->u_arg[0] == GETPRV) {
1542                 if (syserror (tcp)) {
1543                         tprintf(", %#lx, %ld", tcp->u_arg[1], tcp->u_arg[2]);
1544                 }
1545                 else {
1546                         tprintf (", ");
1547                         printpriv (tcp, tcp->u_arg[1], tcp->u_rval);
1548                         tprintf (", %ld", tcp->u_arg[2]);
1549                 }
1550         }
1551
1552         return 0;
1553 }
1554
1555 #endif
1556
1557
1558 void
1559 fake_execve(tcp, program, argv, envp)
1560 struct tcb *tcp;
1561 char *program;
1562 char *argv[];
1563 char *envp[];
1564 {
1565         int i;
1566
1567 #ifdef ARM
1568         if (!(qual_flags[SYS_execve - __NR_SYSCALL_BASE] & QUAL_TRACE))
1569                 return;
1570 #else
1571         if (!(qual_flags[SYS_execve] & QUAL_TRACE))
1572                 return;
1573 #endif /* !ARM */
1574         printleader(tcp);
1575         tprintf("execve(");
1576         string_quote(program);
1577         tprintf(", [");
1578         for (i = 0; argv[i] != NULL; i++) {
1579                 if (i != 0)
1580                         tprintf(", ");
1581                 string_quote(argv[i]);
1582         }
1583         for (i = 0; envp[i] != NULL; i++)
1584                 ;
1585         tprintf("], [/* %d var%s */]) ", i, (i != 1) ? "s" : "");
1586         tabto(acolumn);
1587         tprintf("= 0");
1588         printtrailer(tcp);
1589 }
1590
1591 static void
1592 printargv(tcp, addr)
1593 struct tcb *tcp;
1594 long addr;
1595 {
1596         char *cp;
1597         char *sep;
1598         int max = max_strlen / 2;
1599
1600         for (sep = ""; --max >= 0; sep = ", ") {
1601                 if (!abbrev(tcp))
1602                         max++;
1603                 if (umove(tcp, addr, &cp) < 0) {
1604                         tprintf("%#lx", addr);
1605                         return;
1606                 }
1607                 if (cp == 0)
1608                         break;
1609                 tprintf(sep);
1610                 printstr(tcp, (long) cp, -1);
1611                 addr += sizeof(char *);
1612         }
1613         if (cp)
1614                 tprintf(", ...");
1615 }
1616
1617 static void
1618 printargc(fmt, tcp, addr)
1619 char *fmt;
1620 struct tcb *tcp;
1621 long addr;
1622 {
1623         int count;
1624         char *cp;
1625
1626         for (count = 0; umove(tcp, addr, &cp) >= 0 && cp != NULL; count++) {
1627                 addr += sizeof(char *);
1628         }
1629         tprintf(fmt, count, count == 1 ? "" : "s");
1630 }
1631
1632 int
1633 sys_execv(tcp)
1634 struct tcb *tcp;
1635 {
1636         if (entering(tcp)) {
1637                 printpath(tcp, tcp->u_arg[0]);
1638                 if (!verbose(tcp))
1639                         tprintf(", %#lx", tcp->u_arg[1]);
1640 #if 0
1641                 else if (abbrev(tcp))
1642                         printargc(", [/* %d arg%s */]", tcp, tcp->u_arg[1]);
1643 #endif
1644                 else {
1645                         tprintf(", [");
1646                         printargv(tcp, tcp->u_arg[1]);
1647                         tprintf("]");
1648                 }
1649         }
1650         return 0;
1651 }
1652
1653 int
1654 sys_execve(tcp)
1655 struct tcb *tcp;
1656 {
1657         if (entering(tcp)) {
1658                 printpath(tcp, tcp->u_arg[0]);
1659                 if (!verbose(tcp))
1660                         tprintf(", %#lx", tcp->u_arg[1]);
1661 #if 0
1662                 else if (abbrev(tcp))
1663                         printargc(", [/* %d arg%s */]", tcp, tcp->u_arg[1]);
1664 #endif
1665                 else {
1666                         tprintf(", [");
1667                         printargv(tcp, tcp->u_arg[1]);
1668                         tprintf("]");
1669                 }
1670                 if (!verbose(tcp))
1671                         tprintf(", %#lx", tcp->u_arg[2]);
1672                 else if (abbrev(tcp))
1673                         printargc(", [/* %d var%s */]", tcp, tcp->u_arg[2]);
1674                 else {
1675                         tprintf(", [");
1676                         printargv(tcp, tcp->u_arg[2]);
1677                         tprintf("]");
1678                 }
1679         }
1680 #if defined LINUX && defined TCB_WAITEXECVE
1681         tcp->flags |= TCB_WAITEXECVE;
1682 #endif /* LINUX && TCB_WAITEXECVE */
1683         return 0;
1684 }
1685
1686 #if UNIXWARE > 2
1687
1688 int sys_rexecve(tcp)
1689 struct tcb *tcp;
1690 {
1691         if (entering (tcp)) {
1692                 sys_execve (tcp);
1693                 tprintf (", %ld", tcp->u_arg[3]);
1694         }
1695         return 0;
1696 }
1697
1698 #endif
1699
1700 int
1701 internal_exec(tcp)
1702 struct tcb *tcp;
1703 {
1704 #ifdef SUNOS4
1705         if (exiting(tcp) && !syserror(tcp) && followfork)
1706                 fixvfork(tcp);
1707 #endif /* SUNOS4 */
1708         return 0;
1709 }
1710
1711 #ifdef LINUX
1712 #ifndef __WNOTHREAD
1713 #define __WNOTHREAD     0x20000000
1714 #endif
1715 #ifndef __WALL
1716 #define __WALL          0x40000000
1717 #endif
1718 #ifndef __WCLONE
1719 #define __WCLONE        0x80000000
1720 #endif
1721 #endif /* LINUX */
1722
1723 static struct xlat wait4_options[] = {
1724         { WNOHANG,      "WNOHANG"       },
1725 #ifndef WSTOPPED
1726         { WUNTRACED,    "WUNTRACED"     },
1727 #endif
1728 #ifdef WEXITED
1729         { WEXITED,      "WEXITED"       },
1730 #endif
1731 #ifdef WTRAPPED
1732         { WTRAPPED,     "WTRAPPED"      },
1733 #endif
1734 #ifdef WSTOPPED
1735         { WSTOPPED,     "WSTOPPED"      },
1736 #endif
1737 #ifdef WCONTINUED
1738         { WCONTINUED,   "WCONTINUED"    },
1739 #endif
1740 #ifdef WNOWAIT
1741         { WNOWAIT,      "WNOWAIT"       },
1742 #endif
1743 #ifdef __WCLONE
1744         { __WCLONE,     "__WCLONE"      },
1745 #endif
1746 #ifdef __WALL
1747         { __WALL,       "__WALL"        },
1748 #endif
1749 #ifdef __WNOTHREAD
1750         { __WNOTHREAD,  "__WNOTHREAD"   },
1751 #endif
1752         { 0,            NULL            },
1753 };
1754
1755 static int
1756 printstatus(status)
1757 int status;
1758 {
1759         int exited = 0;
1760
1761         /*
1762          * Here is a tricky presentation problem.  This solution
1763          * is still not entirely satisfactory but since there
1764          * are no wait status constructors it will have to do.
1765          */
1766         if (WIFSTOPPED(status))
1767                 tprintf("[WIFSTOPPED(s) && WSTOPSIG(s) == %s]",
1768                         signame(WSTOPSIG(status)));
1769         else if WIFSIGNALED(status)
1770                 tprintf("[WIFSIGNALED(s) && WTERMSIG(s) == %s%s]",
1771                         signame(WTERMSIG(status)),
1772                         WCOREDUMP(status) ? " && WCOREDUMP(s)" : "");
1773         else if WIFEXITED(status) {
1774                 tprintf("[WIFEXITED(s) && WEXITSTATUS(s) == %d]",
1775                         WEXITSTATUS(status));
1776                 exited = 1;
1777         }
1778         else
1779                 tprintf("[%#x]", status);
1780         return exited;
1781 }
1782
1783 static int
1784 printwaitn(tcp, n, bitness)
1785 struct tcb *tcp;
1786 int n;
1787 int bitness;
1788 {
1789         int status;
1790         int exited = 0;
1791
1792         if (entering(tcp)) {
1793                 tprintf("%ld, ", tcp->u_arg[0]);
1794         } else {
1795                 /* status */
1796                 if (!tcp->u_arg[1])
1797                         tprintf("NULL");
1798                 else if (syserror(tcp) || tcp->u_rval == 0)
1799                         tprintf("%#lx", tcp->u_arg[1]);
1800                 else if (umove(tcp, tcp->u_arg[1], &status) < 0)
1801                         tprintf("[?]");
1802                 else
1803                         exited = printstatus(status);
1804                 /* options */
1805                 tprintf(", ");
1806                 if (!printflags(wait4_options, tcp->u_arg[2]))
1807                         tprintf("0");
1808                 if (n == 4) {
1809                         tprintf(", ");
1810                         /* usage */
1811                         if (!tcp->u_arg[3])
1812                                 tprintf("NULL");
1813 #ifdef LINUX
1814                         else if (tcp->u_rval > 0) {
1815 #ifdef LINUX_64BIT
1816                                 if (bitness)
1817                                         printrusage32(tcp, tcp->u_arg[3]);
1818                                 else
1819 #endif
1820                                         printrusage(tcp, tcp->u_arg[3]);
1821                         }
1822 #endif /* LINUX */
1823 #ifdef SUNOS4
1824                         else if (tcp->u_rval > 0 && exited)
1825                                 printrusage(tcp, tcp->u_arg[3]);
1826 #endif /* SUNOS4 */
1827                         else
1828                                 tprintf("%#lx", tcp->u_arg[3]);
1829                 }
1830         }
1831         return 0;
1832 }
1833
1834 int
1835 internal_wait(tcp)
1836 struct tcb *tcp;
1837 {
1838         int got_kids;
1839
1840 #ifdef TCB_CLONE_THREAD
1841         if (tcp->flags & TCB_CLONE_THREAD)
1842                 /* The children we wait for are our parent's children.  */
1843                 got_kids = (tcp->parent->nchildren
1844                             > tcp->parent->nclone_detached);
1845         else
1846                 got_kids = (tcp->nchildren > tcp->nclone_detached);
1847 #else
1848         got_kids = tcp->nchildren > 0;
1849 #endif
1850
1851         if (entering(tcp) && got_kids) {
1852                 /* There are children that this parent should block for.
1853                    But ptrace made us the parent of the traced children
1854                    and the real parent will get ECHILD from the wait call.
1855
1856                    XXX If we attached with strace -f -p PID, then there
1857                    may be untraced dead children the parent could be reaping
1858                    now, but we make him block.  */
1859
1860                 /* ??? WTA: fix bug with hanging children */
1861
1862                 if (!(tcp->u_arg[2] & WNOHANG)) {
1863                         /*
1864                          * There are traced children.  We'll make the parent
1865                          * block to avoid a false ECHILD error due to our
1866                          * ptrace having stolen the children.  However,
1867                          * we shouldn't block if there are zombies to reap.
1868                          * XXX doesn't handle pgrp matches (u_arg[0]==0,<-1)
1869                          */
1870                         struct tcb *child = NULL;
1871                         if (tcp->nzombies > 0 &&
1872                             (tcp->u_arg[0] == -1 ||
1873                              (child = pid2tcb(tcp->u_arg[0])) == NULL))
1874                                 return 0;
1875                         if (tcp->u_arg[0] > 0) {
1876                                 /*
1877                                  * If the parent waits for a specified child
1878                                  * PID, then it must get ECHILD right away
1879                                  * if that PID is not one of its children.
1880                                  * Make sure that the requested PID matches
1881                                  * one of the parent's children that we are
1882                                  * tracing, and don't suspend it otherwise.
1883                                  */
1884                                 if (child == NULL)
1885                                         child = pid2tcb(tcp->u_arg[0]);
1886                                 if (child == NULL || child->parent != (
1887 #ifdef TCB_CLONE_THREAD
1888                                             (tcp->flags & TCB_CLONE_THREAD)
1889                                             ? tcp->parent :
1890 #endif
1891                                             tcp))
1892                                         return 0;
1893                         }
1894                         tcp->flags |= TCB_SUSPENDED;
1895                         tcp->waitpid = tcp->u_arg[0];
1896 #ifdef TCB_CLONE_THREAD
1897                         if (tcp->flags & TCB_CLONE_THREAD)
1898                                 tcp->parent->nclone_waiting++;
1899 #endif
1900                 }
1901         }
1902         if (exiting(tcp) && tcp->u_error == ECHILD && got_kids) {
1903                 if (tcp->u_arg[2] & WNOHANG) {
1904                         /* We must force a fake result of 0 instead of
1905                            the ECHILD error.  */
1906                         extern int force_result();
1907                         return force_result(tcp, 0, 0);
1908                 }
1909         }
1910         else if (exiting(tcp) && tcp->u_error == 0 && tcp->u_rval > 0 &&
1911                  tcp->nzombies > 0 && pid2tcb(tcp->u_rval) == NULL) {
1912                 /*
1913                  * We just reaped a child we don't know about,
1914                  * presumably a zombie we already droptcb'd.
1915                  */
1916                 tcp->nzombies--;
1917         }
1918         return 0;
1919 }
1920
1921 #ifdef SVR4
1922
1923 int
1924 sys_wait(tcp)
1925 struct tcb *tcp;
1926 {
1927         if (exiting(tcp)) {
1928                 /* The library wrapper stuffs this into the user variable. */
1929                 if (!syserror(tcp))
1930                         printstatus(getrval2(tcp));
1931         }
1932         return 0;
1933 }
1934
1935 #endif /* SVR4 */
1936
1937 #ifdef FREEBSD
1938 int
1939 sys_wait(tcp)
1940 struct tcb *tcp;
1941 {
1942         int status;
1943
1944         if (exiting(tcp)) {
1945                 if (!syserror(tcp)) {
1946                         if (umove(tcp, tcp->u_arg[0], &status) < 0)
1947                                 tprintf("%#lx", tcp->u_arg[0]);
1948                         else
1949                                 printstatus(status);
1950                 }
1951         }
1952         return 0;
1953 }
1954 #endif
1955
1956 int
1957 sys_waitpid(tcp)
1958 struct tcb *tcp;
1959 {
1960         return printwaitn(tcp, 3, 0);
1961 }
1962
1963 int
1964 sys_wait4(tcp)
1965 struct tcb *tcp;
1966 {
1967         return printwaitn(tcp, 4, 0);
1968 }
1969
1970 #ifdef ALPHA
1971 int
1972 sys_osf_wait4(tcp)
1973 struct tcb *tcp;
1974 {
1975         return printwaitn(tcp, 4, 1);
1976 }
1977 #endif
1978
1979 #ifdef SVR4
1980
1981 static struct xlat waitid_types[] = {
1982         { P_PID,        "P_PID"         },
1983         { P_PPID,       "P_PPID"        },
1984         { P_PGID,       "P_PGID"        },
1985         { P_SID,        "P_SID"         },
1986         { P_CID,        "P_CID"         },
1987         { P_UID,        "P_UID"         },
1988         { P_GID,        "P_GID"         },
1989         { P_ALL,        "P_ALL"         },
1990 #ifdef P_LWPID
1991         { P_LWPID,      "P_LWPID"       },
1992 #endif
1993         { 0,            NULL            },
1994 };
1995
1996 int
1997 sys_waitid(tcp)
1998 struct tcb *tcp;
1999 {
2000         siginfo_t si;
2001         int exited;
2002
2003         if (entering(tcp)) {
2004                 printxval(waitid_types, tcp->u_arg[0], "P_???");
2005                 tprintf(", %ld, ", tcp->u_arg[1]);
2006                 if (tcp->nchildren > 0) {
2007                         /* There are traced children */
2008                         tcp->flags |= TCB_SUSPENDED;
2009                         tcp->waitpid = tcp->u_arg[0];
2010                 }
2011         }
2012         else {
2013                 /* siginfo */
2014                 exited = 0;
2015                 if (!tcp->u_arg[2])
2016                         tprintf("NULL");
2017                 else if (syserror(tcp))
2018                         tprintf("%#lx", tcp->u_arg[2]);
2019                 else if (umove(tcp, tcp->u_arg[2], &si) < 0)
2020                         tprintf("{???}");
2021                 else
2022                         printsiginfo(&si, verbose (tcp));
2023                 /* options */
2024                 tprintf(", ");
2025                 if (!printflags(wait4_options, tcp->u_arg[3]))
2026                         tprintf("0");
2027         }
2028         return 0;
2029 }
2030
2031 #endif /* SVR4 */
2032
2033 int
2034 sys_alarm(tcp)
2035 struct tcb *tcp;
2036 {
2037         if (entering(tcp))
2038                 tprintf("%lu", tcp->u_arg[0]);
2039         return 0;
2040 }
2041
2042 int
2043 sys_uname(tcp)
2044 struct tcb *tcp;
2045 {
2046         struct utsname uname;
2047
2048         if (exiting(tcp)) {
2049                 if (syserror(tcp) || !verbose(tcp))
2050                         tprintf("%#lx", tcp->u_arg[0]);
2051                 else if (umove(tcp, tcp->u_arg[0], &uname) < 0)
2052                         tprintf("{...}");
2053                 else if (!abbrev(tcp)) {
2054
2055                         tprintf("{sysname=\"%s\", nodename=\"%s\", ",
2056                                 uname.sysname, uname.nodename);
2057                         tprintf("release=\"%s\", version=\"%s\", ",
2058                                 uname.release, uname.version);
2059                         tprintf("machine=\"%s\"", uname.machine);
2060 #ifdef LINUX
2061 #ifndef __GLIBC__
2062                         tprintf(", domainname=\"%s\"", uname.domainname);
2063 #endif /* __GLIBC__ */
2064 #endif /* LINUX */
2065                         tprintf("}");
2066                 }
2067                 else
2068                         tprintf("{sys=\"%s\", node=\"%s\", ...}",
2069                                 uname.sysname, uname.nodename);
2070         }
2071         return 0;
2072 }
2073
2074 #ifndef SVR4
2075
2076 static struct xlat ptrace_cmds[] = {
2077 #ifndef FREEBSD
2078         { PTRACE_TRACEME,       "PTRACE_TRACEME"        },
2079         { PTRACE_PEEKTEXT,      "PTRACE_PEEKTEXT",      },
2080         { PTRACE_PEEKDATA,      "PTRACE_PEEKDATA",      },
2081         { PTRACE_PEEKUSER,      "PTRACE_PEEKUSER",      },
2082         { PTRACE_POKETEXT,      "PTRACE_POKETEXT",      },
2083         { PTRACE_POKEDATA,      "PTRACE_POKEDATA",      },
2084         { PTRACE_POKEUSER,      "PTRACE_POKEUSER",      },
2085         { PTRACE_CONT,          "PTRACE_CONT"           },
2086         { PTRACE_KILL,          "PTRACE_KILL"           },
2087         { PTRACE_SINGLESTEP,    "PTRACE_SINGLESTEP"     },
2088         { PTRACE_ATTACH,        "PTRACE_ATTACH"         },
2089         { PTRACE_DETACH,        "PTRACE_DETACH"         },
2090 #ifdef PTRACE_GETREGS
2091         { PTRACE_GETREGS,       "PTRACE_GETREGS"        },
2092 #endif
2093 #ifdef PTRACE_SETREGS
2094         { PTRACE_SETREGS,       "PTRACE_SETREGS"        },
2095 #endif
2096 #ifdef PTRACE_GETFPREGS
2097         { PTRACE_GETFPREGS,     "PTRACE_GETFPREGS",     },
2098 #endif
2099 #ifdef PTRACE_SETFPREGS
2100         { PTRACE_SETFPREGS,     "PTRACE_SETFPREGS",     },
2101 #endif
2102 #ifdef PTRACE_GETFPXREGS
2103         { PTRACE_GETFPXREGS,    "PTRACE_GETFPXREGS",    },
2104 #endif
2105 #ifdef PTRACE_SETFPXREGS
2106         { PTRACE_SETFPXREGS,    "PTRACE_SETFPXREGS",    },
2107 #endif
2108 #ifdef SUNOS4
2109         { PTRACE_READDATA,      "PTRACE_READDATA"       },
2110         { PTRACE_WRITEDATA,     "PTRACE_WRITEDATA"      },
2111         { PTRACE_READTEXT,      "PTRACE_READTEXT"       },
2112         { PTRACE_WRITETEXT,     "PTRACE_WRITETEXT"      },
2113         { PTRACE_GETFPAREGS,    "PTRACE_GETFPAREGS"     },
2114         { PTRACE_SETFPAREGS,    "PTRACE_SETFPAREGS"     },
2115 #ifdef SPARC
2116         { PTRACE_GETWINDOW,     "PTRACE_GETWINDOW"      },
2117         { PTRACE_SETWINDOW,     "PTRACE_SETWINDOW"      },
2118 #else /* !SPARC */
2119         { PTRACE_22,            "PTRACE_PTRACE_22"      },
2120         { PTRACE_23,            "PTRACE_PTRACE_23"      },
2121 #endif /* !SPARC */
2122 #endif /* SUNOS4 */
2123         { PTRACE_SYSCALL,       "PTRACE_SYSCALL"        },
2124 #ifdef SUNOS4
2125         { PTRACE_DUMPCORE,      "PTRACE_DUMPCORE"       },
2126 #ifdef I386
2127         { PTRACE_SETWRBKPT,     "PTRACE_SETWRBKPT"      },
2128         { PTRACE_SETACBKPT,     "PTRACE_SETACBKPT"      },
2129         { PTRACE_CLRDR7,        "PTRACE_CLRDR7"         },
2130 #else /* !I386 */
2131         { PTRACE_26,            "PTRACE_26"             },
2132         { PTRACE_27,            "PTRACE_27"             },
2133         { PTRACE_28,            "PTRACE_28"             },
2134 #endif /* !I386 */
2135         { PTRACE_GETUCODE,      "PTRACE_GETUCODE"       },
2136 #endif /* SUNOS4 */
2137 #else /* FREEBSD */
2138         { PT_TRACE_ME,          "PT_TRACE_ME"           },
2139         { PT_READ_I,            "PT_READ_I"             },
2140         { PT_READ_D,            "PT_READ_D"             },
2141         { PT_WRITE_I,           "PT_WRITE_I"            },
2142         { PT_WRITE_D,           "PT_WRITE_D"            },
2143 #ifdef PT_READ_U
2144         { PT_READ_U,            "PT_READ_U"             },
2145 #endif
2146         { PT_CONTINUE,          "PT_CONTINUE"           },
2147         { PT_KILL,              "PT_KILL"               },
2148         { PT_STEP,              "PT_STEP"               },
2149         { PT_ATTACH,            "PT_ATTACH"             },
2150         { PT_DETACH,            "PT_DETACH"             },
2151         { PT_GETREGS,           "PT_GETREGS"            },
2152         { PT_SETREGS,           "PT_SETREGS"            },
2153         { PT_GETFPREGS,         "PT_GETFPREGS"          },
2154         { PT_SETFPREGS,         "PT_SETFPREGS"          },
2155         { PT_GETDBREGS,         "PT_GETDBREGS"          },
2156         { PT_SETDBREGS,         "PT_SETDBREGS"          },
2157 #endif /* FREEBSD */
2158         { 0,                    NULL                    },
2159 };
2160
2161 #ifndef FREEBSD
2162 #ifndef SUNOS4_KERNEL_ARCH_KLUDGE
2163 static
2164 #endif /* !SUNOS4_KERNEL_ARCH_KLUDGE */
2165 struct xlat struct_user_offsets[] = {
2166 #ifdef LINUX
2167 #if defined(S390) || defined(S390X)
2168         { PT_PSWMASK,           "psw_mask"                              },
2169         { PT_PSWADDR,           "psw_addr"                              },
2170         { PT_GPR0,              "gpr0"                                  },
2171         { PT_GPR1,              "gpr1"                                  },
2172         { PT_GPR2,              "gpr2"                                  },
2173         { PT_GPR3,              "gpr3"                                  },
2174         { PT_GPR4,              "gpr4"                                  },
2175         { PT_GPR5,              "gpr5"                                  },
2176         { PT_GPR6,              "gpr6"                                  },
2177         { PT_GPR7,              "gpr7"                                  },
2178         { PT_GPR8,              "gpr8"                                  },
2179         { PT_GPR9,              "gpr9"                                  },
2180         { PT_GPR10,             "gpr10"                                 },
2181         { PT_GPR11,             "gpr11"                                 },
2182         { PT_GPR12,             "gpr12"                                 },
2183         { PT_GPR13,             "gpr13"                                 },
2184         { PT_GPR14,             "gpr14"                                 },
2185         { PT_GPR15,             "gpr15"                                 },
2186         { PT_ACR0,              "acr0"                                  },
2187         { PT_ACR1,              "acr1"                                  },
2188         { PT_ACR2,              "acr2"                                  },
2189         { PT_ACR3,              "acr3"                                  },
2190         { PT_ACR4,              "acr4"                                  },
2191         { PT_ACR5,              "acr5"                                  },
2192         { PT_ACR6,              "acr6"                                  },
2193         { PT_ACR7,              "acr7"                                  },
2194         { PT_ACR8,              "acr8"                                  },
2195         { PT_ACR9,              "acr9"                                  },
2196         { PT_ACR10,             "acr10"                                 },
2197         { PT_ACR11,             "acr11"                                 },
2198         { PT_ACR12,             "acr12"                                 },
2199         { PT_ACR13,             "acr13"                                 },
2200         { PT_ACR14,             "acr14"                                 },
2201         { PT_ACR15,             "acr15"                                 },
2202         { PT_ORIGGPR2,          "orig_gpr2"                             },
2203         { PT_FPC,               "fpc"                                   },
2204 #if defined(S390)
2205         { PT_FPR0_HI,           "fpr0.hi"                               },
2206         { PT_FPR0_LO,           "fpr0.lo"                               },
2207         { PT_FPR1_HI,           "fpr1.hi"                               },
2208         { PT_FPR1_LO,           "fpr1.lo"                               },
2209         { PT_FPR2_HI,           "fpr2.hi"                               },
2210         { PT_FPR2_LO,           "fpr2.lo"                               },
2211         { PT_FPR3_HI,           "fpr3.hi"                               },
2212         { PT_FPR3_LO,           "fpr3.lo"                               },
2213         { PT_FPR4_HI,           "fpr4.hi"                               },
2214         { PT_FPR4_LO,           "fpr4.lo"                               },
2215         { PT_FPR5_HI,           "fpr5.hi"                               },
2216         { PT_FPR5_LO,           "fpr5.lo"                               },
2217         { PT_FPR6_HI,           "fpr6.hi"                               },
2218         { PT_FPR6_LO,           "fpr6.lo"                               },
2219         { PT_FPR7_HI,           "fpr7.hi"                               },
2220         { PT_FPR7_LO,           "fpr7.lo"                               },
2221         { PT_FPR8_HI,           "fpr8.hi"                               },
2222         { PT_FPR8_LO,           "fpr8.lo"                               },
2223         { PT_FPR9_HI,           "fpr9.hi"                               },
2224         { PT_FPR9_LO,           "fpr9.lo"                               },
2225         { PT_FPR10_HI,          "fpr10.hi"                              },
2226         { PT_FPR10_LO,          "fpr10.lo"                              },
2227         { PT_FPR11_HI,          "fpr11.hi"                              },
2228         { PT_FPR11_LO,          "fpr11.lo"                              },
2229         { PT_FPR12_HI,          "fpr12.hi"                              },
2230         { PT_FPR12_LO,          "fpr12.lo"                              },
2231         { PT_FPR13_HI,          "fpr13.hi"                              },
2232         { PT_FPR13_LO,          "fpr13.lo"                              },
2233         { PT_FPR14_HI,          "fpr14.hi"                              },
2234         { PT_FPR14_LO,          "fpr14.lo"                              },
2235         { PT_FPR15_HI,          "fpr15.hi"                              },
2236         { PT_FPR15_LO,          "fpr15.lo"                              },
2237 #endif
2238 #if defined(S390X)
2239         { PT_FPR0,              "fpr0"                                  },
2240         { PT_FPR1,              "fpr1"                                  },
2241         { PT_FPR2,              "fpr2"                                  },
2242         { PT_FPR3,              "fpr3"                                  },
2243         { PT_FPR4,              "fpr4"                                  },
2244         { PT_FPR5,              "fpr5"                                  },
2245         { PT_FPR6,              "fpr6"                                  },
2246         { PT_FPR7,              "fpr7"                                  },
2247         { PT_FPR8,              "fpr8"                                  },
2248         { PT_FPR9,              "fpr9"                                  },
2249         { PT_FPR10,             "fpr10"                                 },
2250         { PT_FPR11,             "fpr11"                                 },
2251         { PT_FPR12,             "fpr12"                                 },
2252         { PT_FPR13,             "fpr13"                                 },
2253         { PT_FPR14,             "fpr14"                                 },
2254         { PT_FPR15,             "fpr15"                                 },
2255 #endif
2256         { PT_CR_9,              "cr9"                                   },
2257         { PT_CR_10,             "cr10"                                  },
2258         { PT_CR_11,             "cr11"                                  },
2259         { PT_IEEE_IP,           "ieee_exception_ip"                     },
2260 #endif
2261 #if defined(SPARC)
2262         /* XXX No support for these offsets yet. */
2263 #elif defined(HPPA)
2264         /* XXX No support for these offsets yet. */
2265 #elif defined(POWERPC)
2266 #ifndef PT_ORIG_R3
2267 #define PT_ORIG_R3 34
2268 #endif
2269 #define REGSIZE (sizeof(unsigned long))
2270         { REGSIZE*PT_R0,                "r0"                            },
2271         { REGSIZE*PT_R1,                "r1"                            },
2272         { REGSIZE*PT_R2,                "r2"                            },
2273         { REGSIZE*PT_R3,                "r3"                            },
2274         { REGSIZE*PT_R4,                "r4"                            },
2275         { REGSIZE*PT_R5,                "r5"                            },
2276         { REGSIZE*PT_R6,                "r6"                            },
2277         { REGSIZE*PT_R7,                "r7"                            },
2278         { REGSIZE*PT_R8,                "r8"                            },
2279         { REGSIZE*PT_R9,                "r9"                            },
2280         { REGSIZE*PT_R10,               "r10"                           },
2281         { REGSIZE*PT_R11,               "r11"                           },
2282         { REGSIZE*PT_R12,               "r12"                           },
2283         { REGSIZE*PT_R13,               "r13"                           },
2284         { REGSIZE*PT_R14,               "r14"                           },
2285         { REGSIZE*PT_R15,               "r15"                           },
2286         { REGSIZE*PT_R16,               "r16"                           },
2287         { REGSIZE*PT_R17,               "r17"                           },
2288         { REGSIZE*PT_R18,               "r18"                           },
2289         { REGSIZE*PT_R19,               "r19"                           },
2290         { REGSIZE*PT_R20,               "r20"                           },
2291         { REGSIZE*PT_R21,               "r21"                           },
2292         { REGSIZE*PT_R22,               "r22"                           },
2293         { REGSIZE*PT_R23,               "r23"                           },
2294         { REGSIZE*PT_R24,               "r24"                           },
2295         { REGSIZE*PT_R25,               "r25"                           },
2296         { REGSIZE*PT_R26,               "r26"                           },
2297         { REGSIZE*PT_R27,               "r27"                           },
2298         { REGSIZE*PT_R28,               "r28"                           },
2299         { REGSIZE*PT_R29,               "r29"                           },
2300         { REGSIZE*PT_R30,               "r30"                           },
2301         { REGSIZE*PT_R31,               "r31"                           },
2302         { REGSIZE*PT_NIP,               "NIP"                           },
2303         { REGSIZE*PT_MSR,               "MSR"                           },
2304         { REGSIZE*PT_ORIG_R3,           "ORIG_R3"                       },
2305         { REGSIZE*PT_CTR,               "CTR"                           },
2306         { REGSIZE*PT_LNK,               "LNK"                           },
2307         { REGSIZE*PT_XER,               "XER"                           },
2308         { REGSIZE*PT_CCR,               "CCR"                           },
2309         { REGSIZE*PT_FPR0,              "FPR0"                          },
2310 #undef REGSIZE
2311 #else
2312 #ifdef ALPHA
2313         { 0,                    "r0"                                    },
2314         { 1,                    "r1"                                    },
2315         { 2,                    "r2"                                    },
2316         { 3,                    "r3"                                    },
2317         { 4,                    "r4"                                    },
2318         { 5,                    "r5"                                    },
2319         { 6,                    "r6"                                    },
2320         { 7,                    "r7"                                    },
2321         { 8,                    "r8"                                    },
2322         { 9,                    "r9"                                    },
2323         { 10,                   "r10"                                   },
2324         { 11,                   "r11"                                   },
2325         { 12,                   "r12"                                   },
2326         { 13,                   "r13"                                   },
2327         { 14,                   "r14"                                   },
2328         { 15,                   "r15"                                   },
2329         { 16,                   "r16"                                   },
2330         { 17,                   "r17"                                   },
2331         { 18,                   "r18"                                   },
2332         { 19,                   "r19"                                   },
2333         { 20,                   "r20"                                   },
2334         { 21,                   "r21"                                   },
2335         { 22,                   "r22"                                   },
2336         { 23,                   "r23"                                   },
2337         { 24,                   "r24"                                   },
2338         { 25,                   "r25"                                   },
2339         { 26,                   "r26"                                   },
2340         { 27,                   "r27"                                   },
2341         { 28,                   "r28"                                   },
2342         { 29,                   "gp"                                    },
2343         { 30,                   "fp"                                    },
2344         { 31,                   "zero"                                  },
2345         { 32,                   "fp0"                                   },
2346         { 33,                   "fp"                                    },
2347         { 34,                   "fp2"                                   },
2348         { 35,                   "fp3"                                   },
2349         { 36,                   "fp4"                                   },
2350         { 37,                   "fp5"                                   },
2351         { 38,                   "fp6"                                   },
2352         { 39,                   "fp7"                                   },
2353         { 40,                   "fp8"                                   },
2354         { 41,                   "fp9"                                   },
2355         { 42,                   "fp10"                                  },
2356         { 43,                   "fp11"                                  },
2357         { 44,                   "fp12"                                  },
2358         { 45,                   "fp13"                                  },
2359         { 46,                   "fp14"                                  },
2360         { 47,                   "fp15"                                  },
2361         { 48,                   "fp16"                                  },
2362         { 49,                   "fp17"                                  },
2363         { 50,                   "fp18"                                  },
2364         { 51,                   "fp19"                                  },
2365         { 52,                   "fp20"                                  },
2366         { 53,                   "fp21"                                  },
2367         { 54,                   "fp22"                                  },
2368         { 55,                   "fp23"                                  },
2369         { 56,                   "fp24"                                  },
2370         { 57,                   "fp25"                                  },
2371         { 58,                   "fp26"                                  },
2372         { 59,                   "fp27"                                  },
2373         { 60,                   "fp28"                                  },
2374         { 61,                   "fp29"                                  },
2375         { 62,                   "fp30"                                  },
2376         { 63,                   "fp31"                                  },
2377         { 64,                   "pc"                                    },
2378 #else /* !ALPHA */
2379 #ifdef IA64
2380         { PT_F32, "f32" }, { PT_F33, "f33" }, { PT_F34, "f34" },
2381         { PT_F35, "f35" }, { PT_F36, "f36" }, { PT_F37, "f37" },
2382         { PT_F38, "f38" }, { PT_F39, "f39" }, { PT_F40, "f40" },
2383         { PT_F41, "f41" }, { PT_F42, "f42" }, { PT_F43, "f43" },
2384         { PT_F44, "f44" }, { PT_F45, "f45" }, { PT_F46, "f46" },
2385         { PT_F47, "f47" }, { PT_F48, "f48" }, { PT_F49, "f49" },
2386         { PT_F50, "f50" }, { PT_F51, "f51" }, { PT_F52, "f52" },
2387         { PT_F53, "f53" }, { PT_F54, "f54" }, { PT_F55, "f55" },
2388         { PT_F56, "f56" }, { PT_F57, "f57" }, { PT_F58, "f58" },
2389         { PT_F59, "f59" }, { PT_F60, "f60" }, { PT_F61, "f61" },
2390         { PT_F62, "f62" }, { PT_F63, "f63" }, { PT_F64, "f64" },
2391         { PT_F65, "f65" }, { PT_F66, "f66" }, { PT_F67, "f67" },
2392         { PT_F68, "f68" }, { PT_F69, "f69" }, { PT_F70, "f70" },
2393         { PT_F71, "f71" }, { PT_F72, "f72" }, { PT_F73, "f73" },
2394         { PT_F74, "f74" }, { PT_F75, "f75" }, { PT_F76, "f76" },
2395         { PT_F77, "f77" }, { PT_F78, "f78" }, { PT_F79, "f79" },
2396         { PT_F80, "f80" }, { PT_F81, "f81" }, { PT_F82, "f82" },
2397         { PT_F83, "f83" }, { PT_F84, "f84" }, { PT_F85, "f85" },
2398         { PT_F86, "f86" }, { PT_F87, "f87" }, { PT_F88, "f88" },
2399         { PT_F89, "f89" }, { PT_F90, "f90" }, { PT_F91, "f91" },
2400         { PT_F92, "f92" }, { PT_F93, "f93" }, { PT_F94, "f94" },
2401         { PT_F95, "f95" }, { PT_F96, "f96" }, { PT_F97, "f97" },
2402         { PT_F98, "f98" }, { PT_F99, "f99" }, { PT_F100, "f100" },
2403         { PT_F101, "f101" }, { PT_F102, "f102" }, { PT_F103, "f103" },
2404         { PT_F104, "f104" }, { PT_F105, "f105" }, { PT_F106, "f106" },
2405         { PT_F107, "f107" }, { PT_F108, "f108" }, { PT_F109, "f109" },
2406         { PT_F110, "f110" }, { PT_F111, "f111" }, { PT_F112, "f112" },
2407         { PT_F113, "f113" }, { PT_F114, "f114" }, { PT_F115, "f115" },
2408         { PT_F116, "f116" }, { PT_F117, "f117" }, { PT_F118, "f118" },
2409         { PT_F119, "f119" }, { PT_F120, "f120" }, { PT_F121, "f121" },
2410         { PT_F122, "f122" }, { PT_F123, "f123" }, { PT_F124, "f124" },
2411         { PT_F125, "f125" }, { PT_F126, "f126" }, { PT_F127, "f127" },
2412         /* switch stack: */
2413         { PT_F2, "f2" }, { PT_F3, "f3" }, { PT_F4, "f4" },
2414         { PT_F5, "f5" }, { PT_F10, "f10" }, { PT_F11, "f11" },
2415         { PT_F12, "f12" }, { PT_F13, "f13" }, { PT_F14, "f14" },
2416         { PT_F15, "f15" }, { PT_F16, "f16" }, { PT_F17, "f17" },
2417         { PT_F18, "f18" }, { PT_F19, "f19" }, { PT_F20, "f20" },
2418         { PT_F21, "f21" }, { PT_F22, "f22" }, { PT_F23, "f23" },
2419         { PT_F24, "f24" }, { PT_F25, "f25" }, { PT_F26, "f26" },
2420         { PT_F27, "f27" }, { PT_F28, "f28" }, { PT_F29, "f29" },
2421         { PT_F30, "f30" }, { PT_F31, "f31" }, { PT_R4, "r4" },
2422         { PT_R5, "r5" }, { PT_R6, "r6" }, { PT_R7, "r7" },
2423         { PT_B0, "kb0" },
2424         { PT_B1, "b1" }, { PT_B2, "b2" }, { PT_B3, "b3" },
2425         { PT_B4, "b4" }, { PT_B5, "b5" },
2426         { PT_AR_PFS, "kar.pfs" },
2427         { PT_AR_LC, "ar.lc" }, { PT_AR_UNAT, "kar.unat" },
2428         { PT_AR_RNAT, "kar.rnat" }, { PT_AR_BSPSTORE, "kar.bspstore" },
2429         { PT_PR, "k.pr" },
2430         /* pt_regs */
2431         { PT_CR_IPSR, "cr.ipsr" }, { PT_CR_IIP, "cr.iip" },
2432         /*{ PT_CR_IFS, "cr.ifs" },*/ { PT_AR_UNAT, "ar.unat" },
2433         { PT_AR_PFS, "ar.pfs" }, { PT_AR_RSC, "ar.rsc" },
2434         { PT_AR_RNAT, "ar.rnat" }, { PT_AR_BSPSTORE, "ar.bspstore" },
2435         { PT_PR, "pr" }, { PT_B6, "b6" }, { PT_AR_BSP, "ar.bsp" },
2436         { PT_R1, "r1" }, { PT_R2, "r2" }, { PT_R3, "r3" },
2437         { PT_R12, "r12" }, { PT_R13, "r13" }, { PT_R14, "r14" },
2438         { PT_R15, "r15" }, { PT_R8, "r8" }, { PT_R9, "r9" },
2439         { PT_R10, "r10" }, { PT_R11, "r11" }, { PT_R16, "r16" },
2440         { PT_R17, "r17" }, { PT_R18, "r18" }, { PT_R19, "r19" },
2441         { PT_R20, "r20" }, { PT_R21, "r21" }, { PT_R22, "r22" },
2442         { PT_R23, "r23" }, { PT_R24, "r24" }, { PT_R25, "r25" },
2443         { PT_R26, "r26" }, { PT_R27, "r27" }, { PT_R28, "r28" },
2444         { PT_R29, "r29" }, { PT_R30, "r30" }, { PT_R31, "r31" },
2445         { PT_AR_CCV, "ar.ccv" }, { PT_AR_FPSR, "ar.fpsr" },
2446         { PT_B0, "b0" }, { PT_B7, "b7" }, { PT_F6, "f6" },
2447         { PT_F7, "f7" }, { PT_F8, "f8" }, { PT_F9, "f9" },
2448 #else /* !IA64 */
2449 #ifdef I386
2450         { 4*EBX,                "4*EBX"                                 },
2451         { 4*ECX,                "4*ECX"                                 },
2452         { 4*EDX,                "4*EDX"                                 },
2453         { 4*ESI,                "4*ESI"                                 },
2454         { 4*EDI,                "4*EDI"                                 },
2455         { 4*EBP,                "4*EBP"                                 },
2456         { 4*EAX,                "4*EAX"                                 },
2457         { 4*DS,                 "4*DS"                                  },
2458         { 4*ES,                 "4*ES"                                  },
2459         { 4*FS,                 "4*FS"                                  },
2460         { 4*GS,                 "4*GS"                                  },
2461         { 4*ORIG_EAX,           "4*ORIG_EAX"                            },
2462         { 4*EIP,                "4*EIP"                                 },
2463         { 4*CS,                 "4*CS"                                  },
2464         { 4*EFL,                "4*EFL"                                 },
2465         { 4*UESP,               "4*UESP"                                },
2466         { 4*SS,                 "4*SS"                                  },
2467 #else /* !I386 */
2468 #ifdef X86_64
2469         { 8*RDI,                "8*RDI"                                 },
2470         { 8*RSI,                "8*RSI"                                 },
2471         { 8*RDX,                "8*RDX"                                 },
2472         { 8*R10,                "8*R10" },
2473         { 8*R8,                 "8*R8" },
2474         { 8*R9,                 "8*R9" },
2475         { 8*RBX,                "8*RBX"                                 },
2476         { 8*RCX,                "8*RCX"                                 },
2477         { 8*RBP,                "8*RBP"                                 },
2478         { 8*RAX,                "8*RAX"                                 },
2479 #if 0
2480         { 8*DS,                 "8*DS"                                  },
2481         { 8*ES,                 "8*ES"                                  },
2482         { 8*FS,                 "8*FS"                                  },
2483         { 8*GS,                 "8*GS"                                  },
2484 #endif
2485         { 8*ORIG_RAX,           "8*ORIG_EAX"                            },
2486         { 8*RIP,                "8*RIP"                                 },
2487         { 8*CS,                 "8*CS"                                  },
2488         { 8*EFLAGS,             "8*EFL"                                 },
2489         { 8*RSP,                "8*RSP"                         },
2490         { 8*SS,                 "8*SS"                                  },
2491         { 8*R11,                "8*R11" },
2492         { 8*R12,                "8*R12" },
2493         { 8*R13,                "8*R13" },
2494         { 8*R14,                "8*R14" },
2495         { 8*R15,                "8*R15" },
2496 #endif
2497 #ifdef M68K
2498         { 4*PT_D1,              "4*PT_D1"                               },
2499         { 4*PT_D2,              "4*PT_D2"                               },
2500         { 4*PT_D3,              "4*PT_D3"                               },
2501         { 4*PT_D4,              "4*PT_D4"                               },
2502         { 4*PT_D5,              "4*PT_D5"                               },
2503         { 4*PT_D6,              "4*PT_D6"                               },
2504         { 4*PT_D7,              "4*PT_D7"                               },
2505         { 4*PT_A0,              "4*PT_A0"                               },
2506         { 4*PT_A1,              "4*PT_A1"                               },
2507         { 4*PT_A2,              "4*PT_A2"                               },
2508         { 4*PT_A3,              "4*PT_A3"                               },
2509         { 4*PT_A4,              "4*PT_A4"                               },
2510         { 4*PT_A5,              "4*PT_A5"                               },
2511         { 4*PT_A6,              "4*PT_A6"                               },
2512         { 4*PT_D0,              "4*PT_D0"                               },
2513         { 4*PT_USP,             "4*PT_USP"                              },
2514         { 4*PT_ORIG_D0,         "4*PT_ORIG_D0"                          },
2515         { 4*PT_SR,              "4*PT_SR"                               },
2516         { 4*PT_PC,              "4*PT_PC"                               },
2517 #endif /* M68K */
2518 #endif /* !I386 */
2519 #ifdef SH
2520        { 4*REG_REG0,           "4*REG_REG0"                            },
2521        { 4*(REG_REG0+1),       "4*REG_REG1"                            },
2522        { 4*(REG_REG0+2),       "4*REG_REG2"                            },
2523        { 4*(REG_REG0+3),       "4*REG_REG3"                            },
2524        { 4*(REG_REG0+4),       "4*REG_REG4"                            },
2525        { 4*(REG_REG0+5),       "4*REG_REG5"                            },
2526        { 4*(REG_REG0+6),       "4*REG_REG6"                            },
2527        { 4*(REG_REG0+7),       "4*REG_REG7"                            },
2528        { 4*(REG_REG0+8),       "4*REG_REG8"                            },
2529        { 4*(REG_REG0+9),       "4*REG_REG9"                            },
2530        { 4*(REG_REG0+10),      "4*REG_REG10"                           },
2531        { 4*(REG_REG0+11),      "4*REG_REG11"                           },
2532        { 4*(REG_REG0+12),      "4*REG_REG12"                           },
2533        { 4*(REG_REG0+13),      "4*REG_REG13"                           },
2534        { 4*(REG_REG0+14),      "4*REG_REG14"                           },
2535        { 4*REG_REG15,          "4*REG_REG15"                           },
2536        { 4*REG_PC,             "4*REG_PC"                              },
2537        { 4*REG_PR,             "4*REG_PR"                              },
2538        { 4*REG_SR,             "4*REG_SR"                              },
2539        { 4*REG_GBR,            "4*REG_GBR"                             },
2540        { 4*REG_MACH,           "4*REG_MACH"                            },
2541        { 4*REG_MACL,           "4*REG_MACL"                            },
2542        { 4*REG_SYSCALL,        "4*REG_SYSCALL"                         },
2543        { 4*REG_FPUL,           "4*REG_FPUL"                            },
2544        { 4*REG_FPREG0,         "4*REG_FPREG0"                          },
2545        { 4*(REG_FPREG0+1),     "4*REG_FPREG1"                          },
2546        { 4*(REG_FPREG0+2),     "4*REG_FPREG2"                          },
2547        { 4*(REG_FPREG0+3),     "4*REG_FPREG3"                          },
2548        { 4*(REG_FPREG0+4),     "4*REG_FPREG4"                          },
2549        { 4*(REG_FPREG0+5),     "4*REG_FPREG5"                          },
2550        { 4*(REG_FPREG0+6),     "4*REG_FPREG6"                          },
2551        { 4*(REG_FPREG0+7),     "4*REG_FPREG7"                          },
2552        { 4*(REG_FPREG0+8),     "4*REG_FPREG8"                          },
2553        { 4*(REG_FPREG0+9),     "4*REG_FPREG9"                          },
2554        { 4*(REG_FPREG0+10),    "4*REG_FPREG10"                         },
2555        { 4*(REG_FPREG0+11),    "4*REG_FPREG11"                         },
2556        { 4*(REG_FPREG0+12),    "4*REG_FPREG12"                         },
2557        { 4*(REG_FPREG0+13),    "4*REG_FPREG13"                         },
2558        { 4*(REG_FPREG0+14),    "4*REG_FPREG14"                         },
2559        { 4*REG_FPREG15,        "4*REG_FPREG15"                         },
2560 #ifdef REG_XDREG0
2561        { 4*REG_XDREG0,         "4*REG_XDREG0"                          },
2562        { 4*(REG_XDREG0+2),     "4*REG_XDREG2"                          },
2563        { 4*(REG_XDREG0+4),     "4*REG_XDREG4"                          },
2564        { 4*(REG_XDREG0+6),     "4*REG_XDREG6"                          },
2565        { 4*(REG_XDREG0+8),     "4*REG_XDREG8"                          },
2566        { 4*(REG_XDREG0+10),    "4*REG_XDREG10"                         },
2567        { 4*(REG_XDREG0+12),    "4*REG_XDREG12"                         },
2568        { 4*REG_XDREG14,        "4*REG_XDREG14"                         },
2569 #endif
2570        { 4*REG_FPSCR,          "4*REG_FPSCR"                           },
2571 #endif /* SH */
2572 #ifdef SH64
2573         { 0,                    "PC(L)"                                 },
2574         { 4,                    "PC(U)"                                 },
2575         { 8,                    "SR(L)"                                 },
2576         { 12,                   "SR(U)"                                 },
2577         { 16,                   "syscall no.(L)"                        },
2578         { 20,                   "syscall_no.(U)"                        },
2579         { 24,                   "R0(L)"                                 },
2580         { 28,                   "R0(U)"                                 },
2581         { 32,                   "R1(L)"                                 },
2582         { 36,                   "R1(U)"                                 },
2583         { 40,                   "R2(L)"                                 },
2584         { 44,                   "R2(U)"                                 },
2585         { 48,                   "R3(L)"                                 },
2586         { 52,                   "R3(U)"                                 },
2587         { 56,                   "R4(L)"                                 },
2588         { 60,                   "R4(U)"                                 },
2589         { 64,                   "R5(L)"                                 },
2590         { 68,                   "R5(U)"                                 },
2591         { 72,                   "R6(L)"                                 },
2592         { 76,                   "R6(U)"                                 },
2593         { 80,                   "R7(L)"                                 },
2594         { 84,                   "R7(U)"                                 },
2595         { 88,                   "R8(L)"                                 },
2596         { 92,                   "R8(U)"                                 },
2597         { 96,                   "R9(L)"                                 },
2598         { 100,                  "R9(U)"                                 },
2599         { 104,                  "R10(L)"                                },
2600         { 108,                  "R10(U)"                                },
2601         { 112,                  "R11(L)"                                },
2602         { 116,                  "R11(U)"                                },
2603         { 120,                  "R12(L)"                                },
2604         { 124,                  "R12(U)"                                },
2605         { 128,                  "R13(L)"                                },
2606         { 132,                  "R13(U)"                                },
2607         { 136,                  "R14(L)"                                },
2608         { 140,                  "R14(U)"                                },
2609         { 144,                  "R15(L)"                                },
2610         { 148,                  "R15(U)"                                },
2611         { 152,                  "R16(L)"                                },
2612         { 156,                  "R16(U)"                                },
2613         { 160,                  "R17(L)"                                },
2614         { 164,                  "R17(U)"                                },
2615         { 168,                  "R18(L)"                                },
2616         { 172,                  "R18(U)"                                },
2617         { 176,                  "R19(L)"                                },
2618         { 180,                  "R19(U)"                                },
2619         { 184,                  "R20(L)"                                },
2620         { 188,                  "R20(U)"                                },
2621         { 192,                  "R21(L)"                                },
2622         { 196,                  "R21(U)"                                },
2623         { 200,                  "R22(L)"                                },
2624         { 204,                  "R22(U)"                                },
2625         { 208,                  "R23(L)"                                },
2626         { 212,                  "R23(U)"                                },
2627         { 216,                  "R24(L)"                                },
2628         { 220,                  "R24(U)"                                },
2629         { 224,                  "R25(L)"                                },
2630         { 228,                  "R25(U)"                                },
2631         { 232,                  "R26(L)"                                },
2632         { 236,                  "R26(U)"                                },
2633         { 240,                  "R27(L)"                                },
2634         { 244,                  "R27(U)"                                },
2635         { 248,                  "R28(L)"                                },
2636         { 252,                  "R28(U)"                                },
2637         { 256,                  "R29(L)"                                },
2638         { 260,                  "R29(U)"                                },
2639         { 264,                  "R30(L)"                                },
2640         { 268,                  "R30(U)"                                },
2641         { 272,                  "R31(L)"                                },
2642         { 276,                  "R31(U)"                                },
2643         { 280,                  "R32(L)"                                },
2644         { 284,                  "R32(U)"                                },
2645         { 288,                  "R33(L)"                                },
2646         { 292,                  "R33(U)"                                },
2647         { 296,                  "R34(L)"                                },
2648         { 300,                  "R34(U)"                                },
2649         { 304,                  "R35(L)"                                },
2650         { 308,                  "R35(U)"                                },
2651         { 312,                  "R36(L)"                                },
2652         { 316,                  "R36(U)"                                },
2653         { 320,                  "R37(L)"                                },
2654         { 324,                  "R37(U)"                                },
2655         { 328,                  "R38(L)"                                },
2656         { 332,                  "R38(U)"                                },
2657         { 336,                  "R39(L)"                                },
2658         { 340,                  "R39(U)"                                },
2659         { 344,                  "R40(L)"                                },
2660         { 348,                  "R40(U)"                                },
2661         { 352,                  "R41(L)"                                },
2662         { 356,                  "R41(U)"                                },
2663         { 360,                  "R42(L)"                                },
2664         { 364,                  "R42(U)"                                },
2665         { 368,                  "R43(L)"                                },
2666         { 372,                  "R43(U)"                                },
2667         { 376,                  "R44(L)"                                },
2668         { 380,                  "R44(U)"                                },
2669         { 384,                  "R45(L)"                                },
2670         { 388,                  "R45(U)"                                },
2671         { 392,                  "R46(L)"                                },
2672         { 396,                  "R46(U)"                                },
2673         { 400,                  "R47(L)"                                },
2674         { 404,                  "R47(U)"                                },
2675         { 408,                  "R48(L)"                                },
2676         { 412,                  "R48(U)"                                },
2677         { 416,                  "R49(L)"                                },
2678         { 420,                  "R49(U)"                                },
2679         { 424,                  "R50(L)"                                },
2680         { 428,                  "R50(U)"                                },
2681         { 432,                  "R51(L)"                                },
2682         { 436,                  "R51(U)"                                },
2683         { 440,                  "R52(L)"                                },
2684         { 444,                  "R52(U)"                                },
2685         { 448,                  "R53(L)"                                },
2686         { 452,                  "R53(U)"                                },
2687         { 456,                  "R54(L)"                                },
2688         { 460,                  "R54(U)"                                },
2689         { 464,                  "R55(L)"                                },
2690         { 468,                  "R55(U)"                                },
2691         { 472,                  "R56(L)"                                },
2692         { 476,                  "R56(U)"                                },
2693         { 480,                  "R57(L)"                                },
2694         { 484,                  "R57(U)"                                },
2695         { 488,                  "R58(L)"                                },
2696         { 492,                  "R58(U)"                                },
2697         { 496,                  "R59(L)"                                },
2698         { 500,                  "R59(U)"                                },
2699         { 504,                  "R60(L)"                                },
2700         { 508,                  "R60(U)"                                },
2701         { 512,                  "R61(L)"                                },
2702         { 516,                  "R61(U)"                                },
2703         { 520,                  "R62(L)"                                },
2704         { 524,                  "R62(U)"                                },
2705         { 528,                  "TR0(L)"                                },
2706         { 532,                  "TR0(U)"                                },
2707         { 536,                  "TR1(L)"                                },
2708         { 540,                  "TR1(U)"                                },
2709         { 544,                  "TR2(L)"                                },
2710         { 548,                  "TR2(U)"                                },
2711         { 552,                  "TR3(L)"                                },
2712         { 556,                  "TR3(U)"                                },
2713         { 560,                  "TR4(L)"                                },
2714         { 564,                  "TR4(U)"                                },
2715         { 568,                  "TR5(L)"                                },
2716         { 572,                  "TR5(U)"                                },
2717         { 576,                  "TR6(L)"                                },
2718         { 580,                  "TR6(U)"                                },
2719         { 584,                  "TR7(L)"                                },
2720         { 588,                  "TR7(U)"                                },
2721         /* This entry is in case pt_regs contains dregs (depends on
2722            the kernel build options). */
2723         { uoff(regs),           "offsetof(struct user, regs)"           },
2724         { uoff(fpu),            "offsetof(struct user, fpu)"            },
2725 #endif
2726 #ifdef ARM
2727         { uoff(regs.ARM_r0),    "r0"                                    },
2728         { uoff(regs.ARM_r1),    "r1"                                    },
2729         { uoff(regs.ARM_r2),    "r2"                                    },
2730         { uoff(regs.ARM_r3),    "r3"                                    },
2731         { uoff(regs.ARM_r4),    "r4"                                    },
2732         { uoff(regs.ARM_r5),    "r5"                                    },
2733         { uoff(regs.ARM_r6),    "r6"                                    },
2734         { uoff(regs.ARM_r7),    "r7"                                    },
2735         { uoff(regs.ARM_r8),    "r8"                                    },
2736         { uoff(regs.ARM_r9),    "r9"                                    },
2737         { uoff(regs.ARM_r10),   "r10"                                   },
2738         { uoff(regs.ARM_fp),    "fp"                                    },
2739         { uoff(regs.ARM_ip),    "ip"                                    },
2740         { uoff(regs.ARM_sp),    "sp"                                    },
2741         { uoff(regs.ARM_lr),    "lr"                                    },
2742         { uoff(regs.ARM_pc),    "pc"                                    },
2743         { uoff(regs.ARM_cpsr),  "cpsr"                                  },
2744 #endif
2745
2746 #if !defined(S390) && !defined(S390X) && !defined(MIPS)
2747         { uoff(u_fpvalid),      "offsetof(struct user, u_fpvalid)"      },
2748 #endif
2749 #if  defined(I386) || defined(X86_64)
2750         { uoff(i387),           "offsetof(struct user, i387)"           },
2751 #else /* !I386 */
2752 #ifdef M68K
2753         { uoff(m68kfp),         "offsetof(struct user, m68kfp)"         },
2754 #endif /* M68K */
2755 #endif /* !I386 */
2756         { uoff(u_tsize),        "offsetof(struct user, u_tsize)"        },
2757         { uoff(u_dsize),        "offsetof(struct user, u_dsize)"        },
2758         { uoff(u_ssize),        "offsetof(struct user, u_ssize)"        },
2759         { uoff(start_code),     "offsetof(struct user, start_code)"     },
2760 #ifdef SH64
2761         { uoff(start_data),     "offsetof(struct user, start_data)"     },
2762 #endif
2763         { uoff(start_stack),    "offsetof(struct user, start_stack)"    },
2764         { uoff(signal),         "offsetof(struct user, signal)"         },
2765 #if !defined(S390) && !defined(S390X) && !defined(MIPS) && !defined(SH) && !defined(SH64)
2766         { uoff(reserved),       "offsetof(struct user, reserved)"       },
2767 #endif
2768         { uoff(u_ar0),          "offsetof(struct user, u_ar0)"          },
2769 #if !defined(ARM) && !defined(MIPS) && !defined(S390) && !defined(S390X)
2770         { uoff(u_fpstate),      "offsetof(struct user, u_fpstate)"      },
2771 #endif
2772         { uoff(magic),          "offsetof(struct user, magic)"          },
2773         { uoff(u_comm),         "offsetof(struct user, u_comm)"         },
2774 #if defined(I386) || defined(X86_64)
2775         { uoff(u_debugreg),     "offsetof(struct user, u_debugreg)"     },
2776 #endif /* I386 */
2777 #endif /* !IA64 */
2778 #endif /* !ALPHA */
2779 #endif /* !POWERPC/!SPARC */
2780 #endif /* LINUX */
2781 #ifdef SUNOS4
2782         { uoff(u_pcb),          "offsetof(struct user, u_pcb)"          },
2783         { uoff(u_procp),        "offsetof(struct user, u_procp)"        },
2784         { uoff(u_ar0),          "offsetof(struct user, u_ar0)"          },
2785         { uoff(u_comm[0]),      "offsetof(struct user, u_comm[0])"      },
2786         { uoff(u_arg[0]),       "offsetof(struct user, u_arg[0])"       },
2787         { uoff(u_ap),           "offsetof(struct user, u_ap)"           },
2788         { uoff(u_qsave),        "offsetof(struct user, u_qsave)"        },
2789         { uoff(u_rval1),        "offsetof(struct user, u_rval1)"        },
2790         { uoff(u_rval2),        "offsetof(struct user, u_rval2)"        },
2791         { uoff(u_error),        "offsetof(struct user, u_error)"        },
2792         { uoff(u_eosys),        "offsetof(struct user, u_eosys)"        },
2793         { uoff(u_ssave),        "offsetof(struct user, u_ssave)"        },
2794         { uoff(u_signal[0]),    "offsetof(struct user, u_signal)"       },
2795         { uoff(u_sigmask[0]),   "offsetof(struct user, u_sigmask)"      },
2796         { uoff(u_sigonstack),   "offsetof(struct user, u_sigonstack)"   },
2797         { uoff(u_sigintr),      "offsetof(struct user, u_sigintr)"      },
2798         { uoff(u_sigreset),     "offsetof(struct user, u_sigreset)"     },
2799         { uoff(u_oldmask),      "offsetof(struct user, u_oldmask)"      },
2800         { uoff(u_code),         "offsetof(struct user, u_code)"         },
2801         { uoff(u_addr),         "offsetof(struct user, u_addr)"         },
2802         { uoff(u_sigstack),     "offsetof(struct user, u_sigstack)"     },
2803         { uoff(u_ofile),        "offsetof(struct user, u_ofile)"        },
2804         { uoff(u_pofile),       "offsetof(struct user, u_pofile)"       },
2805         { uoff(u_ofile_arr[0]), "offsetof(struct user, u_ofile_arr[0])" },
2806         { uoff(u_pofile_arr[0]),"offsetof(struct user, u_pofile_arr[0])"},
2807         { uoff(u_lastfile),     "offsetof(struct user, u_lastfile)"     },
2808         { uoff(u_cwd),          "offsetof(struct user, u_cwd)"          },
2809         { uoff(u_cdir),         "offsetof(struct user, u_cdir)"         },
2810         { uoff(u_rdir),         "offsetof(struct user, u_rdir)"         },
2811         { uoff(u_cmask),        "offsetof(struct user, u_cmask)"        },
2812         { uoff(u_ru),           "offsetof(struct user, u_ru)"           },
2813         { uoff(u_cru),          "offsetof(struct user, u_cru)"          },
2814         { uoff(u_timer[0]),     "offsetof(struct user, u_timer[0])"     },
2815         { uoff(u_XXX[0]),       "offsetof(struct user, u_XXX[0])"       },
2816         { uoff(u_ioch),         "offsetof(struct user, u_ioch)"         },
2817         { uoff(u_start),        "offsetof(struct user, u_start)"        },
2818         { uoff(u_acflag),       "offsetof(struct user, u_acflag)"       },
2819         { uoff(u_prof.pr_base), "offsetof(struct user, u_prof.pr_base)" },
2820         { uoff(u_prof.pr_size), "offsetof(struct user, u_prof.pr_size)" },
2821         { uoff(u_prof.pr_off),  "offsetof(struct user, u_prof.pr_off)"  },
2822         { uoff(u_prof.pr_scale),"offsetof(struct user, u_prof.pr_scale)"},
2823         { uoff(u_rlimit[0]),    "offsetof(struct user, u_rlimit)"       },
2824         { uoff(u_exdata.Ux_A),  "offsetof(struct user, u_exdata.Ux_A)"  },
2825         { uoff(u_exdata.ux_shell[0]),"offsetof(struct user, u_exdata.ux_shell[0])"},
2826         { uoff(u_lofault),      "offsetof(struct user, u_lofault)"      },
2827 #endif /* SUNOS4 */
2828 #ifndef HPPA
2829         { sizeof(struct user),  "sizeof(struct user)"                   },
2830 #endif
2831         { 0,                    NULL                                    },
2832 };
2833 #endif
2834
2835 int
2836 sys_ptrace(tcp)
2837 struct tcb *tcp;
2838 {
2839         struct xlat *x;
2840         long addr;
2841
2842         if (entering(tcp)) {
2843                 printxval(ptrace_cmds, tcp->u_arg[0],
2844 #ifndef FREEBSD
2845                           "PTRACE_???"
2846 #else
2847                           "PT_???"
2848 #endif
2849                         );
2850                 tprintf(", %lu, ", tcp->u_arg[1]);
2851                 addr = tcp->u_arg[2];
2852 #ifndef FREEBSD
2853                 if (tcp->u_arg[0] == PTRACE_PEEKUSER
2854                         || tcp->u_arg[0] == PTRACE_POKEUSER) {
2855                         for (x = struct_user_offsets; x->str; x++) {
2856                                 if (x->val >= addr)
2857                                         break;
2858                         }
2859                         if (!x->str)
2860                                 tprintf("%#lx, ", addr);
2861                         else if (x->val > addr && x != struct_user_offsets) {
2862                                 x--;
2863                                 tprintf("%s + %ld, ", x->str, addr - x->val);
2864                         }
2865                         else
2866                                 tprintf("%s, ", x->str);
2867                 }
2868                 else
2869 #endif
2870                         tprintf("%#lx, ", tcp->u_arg[2]);
2871 #ifdef LINUX
2872                 switch (tcp->u_arg[0]) {
2873                 case PTRACE_PEEKDATA:
2874                 case PTRACE_PEEKTEXT:
2875                 case PTRACE_PEEKUSER:
2876                         break;
2877                 case PTRACE_CONT:
2878                 case PTRACE_SINGLESTEP:
2879                 case PTRACE_SYSCALL:
2880                 case PTRACE_DETACH:
2881                         printsignal(tcp->u_arg[3]);
2882                         break;
2883                 default:
2884                         tprintf("%#lx", tcp->u_arg[3]);
2885                         break;
2886                 }
2887         } else {
2888                 switch (tcp->u_arg[0]) {
2889                 case PTRACE_PEEKDATA:
2890                 case PTRACE_PEEKTEXT:
2891                 case PTRACE_PEEKUSER:
2892                         printnum(tcp, tcp->u_arg[3], "%#lx");
2893                         break;
2894                 }
2895         }
2896 #endif /* LINUX */
2897 #ifdef SUNOS4
2898                 if (tcp->u_arg[0] == PTRACE_WRITEDATA ||
2899                         tcp->u_arg[0] == PTRACE_WRITETEXT) {
2900                         tprintf("%lu, ", tcp->u_arg[3]);
2901                         printstr(tcp, tcp->u_arg[4], tcp->u_arg[3]);
2902                 } else if (tcp->u_arg[0] != PTRACE_READDATA &&
2903                                 tcp->u_arg[0] != PTRACE_READTEXT) {
2904                         tprintf("%#lx", tcp->u_arg[3]);
2905                 }
2906         } else {
2907                 if (tcp->u_arg[0] == PTRACE_READDATA ||
2908                         tcp->u_arg[0] == PTRACE_READTEXT) {
2909                         tprintf("%lu, ", tcp->u_arg[3]);
2910                         printstr(tcp, tcp->u_arg[4], tcp->u_arg[3]);
2911                 }
2912         }
2913 #endif /* SUNOS4 */
2914 #ifdef FREEBSD
2915                 tprintf("%lu", tcp->u_arg[3]);
2916         }
2917 #endif /* FREEBSD */
2918         return 0;
2919 }
2920
2921 #endif /* !SVR4 */
2922
2923 #ifdef LINUX
2924 static struct xlat futexops[] = {
2925         { FUTEX_WAIT,   "FUTEX_WAIT" },
2926         { FUTEX_WAKE,   "FUTEX_WAKE" },
2927         { FUTEX_FD,     "FUTEX_FD" },
2928         { FUTEX_REQUEUE,"FUTEX_REQUEUE" },
2929         { 0,            NULL }
2930 };
2931
2932 int
2933 sys_futex(tcp)
2934 struct tcb *tcp;
2935 {
2936     if (entering(tcp)) {
2937         tprintf("%p, ", (void *) tcp->u_arg[0]);
2938         printxval(futexops, tcp->u_arg[1], "FUTEX_???");
2939         tprintf(", %ld", tcp->u_arg[2]);
2940         if (tcp->u_arg[1] == FUTEX_WAIT) {
2941                 tprintf(", ");
2942                 printtv(tcp, tcp->u_arg[3]);
2943         } else if (tcp->u_arg[1] == FUTEX_REQUEUE)
2944                 tprintf(", %ld, %p", tcp->u_arg[3], (void *) tcp->u_arg[4]);
2945     }
2946     return 0;
2947 }
2948
2949 static void
2950 print_affinitylist(list, len)
2951 unsigned long *list;
2952 unsigned int len;
2953 {
2954     int first = 1;
2955     tprintf(" {");
2956     while (len >= sizeof (unsigned long)) {
2957         tprintf("%s %lx", first ? "" : ",", *list++);
2958         first = 0;
2959         len -= sizeof (unsigned long);
2960     }
2961     tprintf(" }");
2962 }
2963
2964 int
2965 sys_sched_setaffinity(tcp)
2966 struct tcb *tcp;
2967 {
2968     if (entering(tcp)) {
2969         tprintf("%ld, %lu, ", tcp->u_arg[0], tcp->u_arg[1]);
2970         print_affinitylist((unsigned long *) tcp->u_arg[2], tcp->u_arg[1]);
2971     }
2972     return 0;
2973 }
2974
2975 int
2976 sys_sched_getaffinity(tcp)
2977 struct tcb *tcp;
2978 {
2979     if (entering(tcp)) {
2980         tprintf("%ld, %lu, ", tcp->u_arg[0], tcp->u_arg[1]);
2981     } else {
2982         print_affinitylist((unsigned long *) tcp->u_arg[2], tcp->u_rval);
2983     }
2984     return 0;
2985 }
2986 #endif