]> granicus.if.org Git - strace/blobdiff - process.c
2005-05-31 Dmitry V. Levin <ldv@altlinux.org>
[strace] / process.c
index bcea3d48b2858e830120ca6d1d2254e9df9d9884..bc116a4778077e8f0d70fbad517cb6d0ea5d6d7a 100644 (file)
--- a/process.c
+++ b/process.c
@@ -2,6 +2,14 @@
  * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
  * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
  * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
+ * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
+ * Copyright (c) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *                     Linux for s390 port by D.J. Barrow
+ *                    <barrow_dj@mail.yahoo.com,djbarrow@de.ibm.com>
+ * Copyright (c) 2000 PocketPenguins Inc.  Linux for Hitachi SuperH
+ *                    port by Greg Banks <gbanks@pocketpenguins.com>
+
+ *
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
 #include <machine/reg.h>
 #endif /* SUNOS4 */
 
-#if __GLIBC__ == 2 && __GLIBC_MINOR__ >= 1 && (defined(I386) || defined(M68K))
+#ifdef FREEBSD
+#include <sys/ptrace.h>
+#endif
+
+#if HAVE_ASM_REG_H
+#if defined (SPARC) || defined (SPARC64)
+#  define fpq kernel_fpq
+#  define fq kernel_fq
+#  define fpu kernel_fpu
+#endif /* SPARC || SPARC64 */
+#include <asm/reg.h>
+#if defined (SPARC) || defined (SPARC64)
+#  undef fpq
+#  undef fq
+#  undef fpu
+#endif /* SPARC || SPARC64 */
+#endif /* HAVE_ASM_REG_H */
+
+#ifdef HAVE_SYS_REG_H
 # include <sys/reg.h>
+#ifndef PTRACE_PEEKUSR
 # define PTRACE_PEEKUSR PTRACE_PEEKUSER
+#endif
+#ifndef PTRACE_POKEUSR
 # define PTRACE_POKEUSR PTRACE_POKEUSER
 #endif
+#endif
 
-#ifdef LINUX
+#ifdef HAVE_LINUX_PTRACE_H
+#undef PTRACE_SYSCALL
+# ifdef HAVE_STRUCT_IA64_FPREG
+#  define ia64_fpreg XXX_ia64_fpreg
+# endif
+# ifdef HAVE_STRUCT_PT_ALL_USER_REGS
+#  define pt_all_user_regs XXX_pt_all_user_regs
+# endif
 #include <linux/ptrace.h>
+# undef ia64_fpreg
+# undef pt_all_user_regs
+#endif
+
+#if defined (LINUX) && defined (SPARC64)
+# define r_pc r_tpc
+# undef PTRACE_GETREGS
+# define PTRACE_GETREGS PTRACE_GETREGS64
+# undef PTRACE_SETREGS
+# define PTRACE_SETREGS PTRACE_SETREGS64
+#endif /* LINUX && SPARC64 */
+
+#ifdef HAVE_LINUX_FUTEX_H
+#include <linux/futex.h>
+#endif
+#if defined LINUX
+# ifndef FUTEX_WAIT
+#  define FUTEX_WAIT 0
+# endif
+# ifndef FUTEX_WAKE
+#  define FUTEX_WAKE 1
+# endif
+# ifndef FUTEX_FD
+#  define FUTEX_FD 2
+# endif
+# ifndef FUTEX_REQUEUE
+#  define FUTEX_REQUEUE 3
+# endif
+#endif
+
+#ifdef LINUX
+#include <sched.h>
+#include <asm/posix_types.h>
+#undef GETGROUPS_T
+#define GETGROUPS_T __kernel_gid_t
+#undef GETGROUPS32_T
+#define GETGROUPS32_T __kernel_gid32_t
 #endif /* LINUX */
 
+#if defined(LINUX) && defined(IA64)
+# include <asm/ptrace_offsets.h>
+# include <asm/rse.h>
+#endif
+
 #ifdef HAVE_PRCTL
 #include <sys/prctl.h>
 #endif
 #define WCOREDUMP(status) ((status) & 0200)
 #endif
 
-/* WTA: this has `&& !defined(LINUXSPARC)', this seems unneeded though? */
+/* WTA: this was `&& !defined(LINUXSPARC)', this seems unneeded though? */
 #if defined(HAVE_PRCTL)
-static struct xlat prctl_options[] = {
+static const struct xlat prctl_options[] = {
 #ifdef PR_MAXPROCS
        { PR_MAXPROCS,          "PR_MAXPROCS"           },
 #endif
@@ -109,10 +188,60 @@ static struct xlat prctl_options[] = {
 #endif
 #if defined(PR_SET_PDEATHSIG)
        { PR_SET_PDEATHSIG,     "PR_SET_PDEATHSIG"      },
+#endif
+#ifdef PR_COREPID
+       { PR_COREPID,           "PR_COREPID"            },
+#endif
+#ifdef PR_ATTACHADDRPERM
+       { PR_ATTACHADDRPERM,    "PR_ATTACHADDRPERM"     },
+#endif
+#ifdef PR_PTHREADEXIT
+       { PR_PTHREADEXIT,       "PR_PTHREADEXIT"        },
+#endif
+#ifdef PR_SET_PDEATHSIG
+       { PR_SET_PDEATHSIG,     "PR_SET_PDEATHSIG"      },
+#endif
+#ifdef PR_GET_PDEATHSIG
+       { PR_GET_PDEATHSIG,     "PR_GET_PDEATHSIG"      },
+#endif
+#ifdef PR_GET_UNALIGN
+       { PR_GET_UNALIGN,       "PR_GET_UNALIGN"        },
+#endif
+#ifdef PR_SET_UNALIGN
+       { PR_SET_UNALIGN,       "PR_SET_UNALIGN"        },
+#endif
+#ifdef PR_GET_KEEPCAPS
+       { PR_GET_KEEPCAPS,      "PR_GET_KEEP_CAPS"      },
+#endif
+#ifdef PR_SET_KEEPCAPS
+       { PR_SET_KEEPCAPS,      "PR_SET_KEEP_CAPS"      },
 #endif
        { 0,                    NULL                    },
 };
 
+
+const char *
+unalignctl_string (unsigned int ctl)
+{
+       static char buf[16];
+
+       switch (ctl) {
+#ifdef PR_UNALIGN_NOPRINT
+             case PR_UNALIGN_NOPRINT:
+               return "NOPRINT";
+#endif
+#ifdef PR_UNALIGN_SIGBUS
+             case PR_UNALIGN_SIGBUS:
+               return "SIGBUS";
+#endif
+             default:
+               break;
+       }
+       sprintf(buf, "%x", ctl);
+       return buf;
+}
+
+
 int
 sys_prctl(tcp)
 struct tcb *tcp;
@@ -125,12 +254,51 @@ struct tcb *tcp;
 #ifdef PR_GETNSHARE
                case PR_GETNSHARE:
                        break;
+#endif
+#ifdef PR_SET_DEATHSIG
+               case PR_GET_PDEATHSIG:
+                       break;
+#endif
+#ifdef PR_SET_UNALIGN
+               case PR_SET_UNALIGN:
+                       tprintf(", %s", unalignctl_string(tcp->u_arg[1]));
+                       break;
+#endif
+#ifdef PR_GET_UNALIGN
+               case PR_GET_UNALIGN:
+                       tprintf(", %#lx", tcp->u_arg[1]);
+                       break;
 #endif
                default:
                        for (i = 1; i < tcp->u_nargs; i++)
                                tprintf(", %#lx", tcp->u_arg[i]);
                        break;
                }
+       } else {
+               switch (tcp->u_arg[0]) {
+#ifdef PR_GET_PDEATHSIG
+               case PR_GET_PDEATHSIG:
+                       for (i=1; i<tcp->u_nargs; i++)
+                               tprintf(", %#lx", tcp->u_arg[i]);
+                       break;
+#endif
+#ifdef PR_SET_UNALIGN
+               case PR_SET_UNALIGN:
+                       break;
+#endif
+#ifdef PR_GET_UNALIGN
+               case PR_GET_UNALIGN:
+               {
+                       int ctl;
+
+                       umove(tcp, tcp->u_arg[1], &ctl);
+                       tcp->auxstr = unalignctl_string(ctl);
+                       return RVAL_STR;
+               }
+#endif
+               default:
+                       break;
+               }
        }
        return 0;
 }
@@ -219,12 +387,40 @@ int
 internal_exit(tcp)
 struct tcb *tcp;
 {
-       if (entering(tcp))
+       if (entering(tcp)) {
                tcp->flags |= TCB_EXITING;
+#ifdef __NR_exit_group
+# ifdef IA64
+               if (ia32) {
+                       if (tcp->scno == 252)
+                               tcp->flags |= TCB_GROUP_EXITING;
+               } else
+# endif
+               if (tcp->scno == __NR_exit_group)
+                       tcp->flags |= TCB_GROUP_EXITING;
+#endif
+       }
        return 0;
 }
 
-#ifdef SVR4
+/* TCP is creating a child we want to follow.
+   If there will be space in tcbtab for it, set TCB_FOLLOWFORK and return 0.
+   If not, clear TCB_FOLLOWFORK, print an error, and return 1.  */
+static int
+fork_tcb(struct tcb *tcp)
+{
+       if (nprocs == tcbtabsize) {
+               if (expand_tcbtab()) {
+                       tcp->flags &= ~TCB_FOLLOWFORK;
+                       fprintf(stderr, "sys_fork: tcb table full\n");
+               }
+       }
+
+       tcp->flags |= TCB_FOLLOWFORK;
+       return 0;
+}
+
+#ifdef USE_PROCFS
 
 int
 sys_fork(tcp)
@@ -239,6 +435,26 @@ struct tcb *tcp;
        return 0;
 }
 
+#if UNIXWARE > 2
+
+int
+sys_rfork(tcp)
+struct tcb *tcp;
+{
+       if (entering(tcp)) {
+               tprintf ("%ld", tcp->u_arg[0]);
+       }
+       else {
+               if (getrval2(tcp)) {
+                       tcp->auxstr = "child process";
+                       return RVAL_UDECIMAL | RVAL_STR;
+               }
+       }
+       return 0;
+}
+
+#endif
+
 int
 internal_fork(tcp)
 struct tcb *tcp;
@@ -246,29 +462,152 @@ struct tcb *tcp;
        struct tcb *tcpchild;
 
        if (exiting(tcp)) {
+#ifdef SYS_rfork
+               if (tcp->scno == SYS_rfork && !(tcp->u_arg[0]&RFPROC))
+                       return 0;
+#endif
                if (getrval2(tcp))
                        return 0;
                if (!followfork)
                        return 0;
-               if (nprocs == MAX_PROCS) {
-                       tcp->flags &= ~TCB_FOLLOWFORK;
-                       fprintf(stderr, "sys_fork: tcb table full\n");
+               if (fork_tcb(tcp))
                        return 0;
-               }
-               else
-                       tcp->flags |= TCB_FOLLOWFORK;
                if (syserror(tcp))
                        return 0;
                if ((tcpchild = alloctcb(tcp->u_rval)) == NULL) {
                        fprintf(stderr, "sys_fork: tcb table full\n");
                        return 0;
                }
-               proc_open(tcpchild, 1);
+               if (proc_open(tcpchild, 2) < 0)
+                       droptcb(tcpchild);
        }
        return 0;
 }
 
-#else /* !SVR4 */
+#else /* !USE_PROCFS */
+
+#ifdef LINUX
+
+/* defines copied from linux/sched.h since we can't include that
+ * ourselves (it conflicts with *lots* of libc includes)
+ */
+#define CSIGNAL         0x000000ff      /* signal mask to be sent at exit */
+#define CLONE_VM        0x00000100      /* set if VM shared between processes */
+#define CLONE_FS        0x00000200      /* set if fs info shared between processes */
+#define CLONE_FILES     0x00000400      /* set if open files shared between processes */
+#define CLONE_SIGHAND   0x00000800      /* set if signal handlers shared */
+#define CLONE_IDLETASK  0x00001000      /* kernel-only flag */
+#define CLONE_PTRACE    0x00002000      /* set if we want to let tracing continue on the child too */
+#define CLONE_VFORK     0x00004000      /* set if the parent wants the child to wake it up on mm_release */
+#define CLONE_PARENT    0x00008000      /* set if we want to have the same parent as the cloner */
+#define CLONE_THREAD   0x00010000      /* Same thread group? */
+#define CLONE_NEWNS    0x00020000      /* New namespace group? */
+#define CLONE_SYSVSEM  0x00040000      /* share system V SEM_UNDO semantics */
+#define CLONE_SETTLS   0x00080000      /* create a new TLS for the child */
+#define CLONE_PARENT_SETTID    0x00100000      /* set the TID in the parent */
+#define CLONE_CHILD_CLEARTID   0x00200000      /* clear the TID in the child */
+#define CLONE_DETACHED         0x00400000      /* parent wants no child-exit signal */
+#define CLONE_UNTRACED         0x00800000      /* set if the tracing process can't force CLONE_PTRACE on this clone */
+#define CLONE_CHILD_SETTID     0x01000000      /* set the TID in the child */
+
+static const struct xlat clone_flags[] = {
+    { CLONE_VM,                "CLONE_VM"      },
+    { CLONE_FS,                "CLONE_FS"      },
+    { CLONE_FILES,     "CLONE_FILES"   },
+    { CLONE_SIGHAND,   "CLONE_SIGHAND" },
+    { CLONE_IDLETASK,  "CLONE_IDLETASK"},
+    { CLONE_PTRACE,    "CLONE_PTRACE"  },
+    { CLONE_VFORK,     "CLONE_VFORK"   },
+    { CLONE_PARENT,    "CLONE_PARENT"  },
+    { CLONE_THREAD,    "CLONE_THREAD" },
+    { CLONE_NEWNS,     "CLONE_NEWNS" },
+    { CLONE_SYSVSEM,   "CLONE_SYSVSEM" },
+    { CLONE_SETTLS,    "CLONE_SETTLS" },
+    { CLONE_PARENT_SETTID,"CLONE_PARENT_SETTID" },
+    { CLONE_CHILD_CLEARTID,"CLONE_CHILD_CLEARTID" },
+    { CLONE_DETACHED,  "CLONE_DETACHED" },
+    { CLONE_UNTRACED,  "CLONE_UNTRACED" },
+    { CLONE_CHILD_SETTID,"CLONE_CHILD_SETTID" },
+    { 0,               NULL            },
+};
+
+# ifdef I386
+#  include <asm/ldt.h>
+#   ifdef HAVE_STRUCT_USER_DESC
+#    define modify_ldt_ldt_s user_desc
+#   endif
+extern void print_ldt_entry();
+# endif
+
+# if defined IA64
+#  define ARG_FLAGS    0
+#  define ARG_STACK    1
+#  define ARG_STACKSIZE        (tcp->scno == SYS_clone2 ? 2 : -1)
+#  define ARG_PTID     (tcp->scno == SYS_clone2 ? 3 : 2)
+#  define ARG_CTID     (tcp->scno == SYS_clone2 ? 4 : 3)
+#  define ARG_TLS      (tcp->scno == SYS_clone2 ? 5 : 4)
+# elif defined S390 || defined S390X
+#  define ARG_STACK    0
+#  define ARG_FLAGS    1
+#  define ARG_PTID     2
+#  define ARG_CTID     3
+#  define ARG_TLS      4
+# elif defined X86_64 || defined ALPHA
+#  define ARG_FLAGS    0
+#  define ARG_STACK    1
+#  define ARG_PTID     2
+#  define ARG_CTID     3
+#  define ARG_TLS      4
+# else
+#  define ARG_FLAGS    0
+#  define ARG_STACK    1
+#  define ARG_PTID     2
+#  define ARG_TLS      3
+#  define ARG_CTID     4
+# endif
+
+int
+sys_clone(tcp)
+struct tcb *tcp;
+{
+       if (exiting(tcp)) {
+               unsigned long flags = tcp->u_arg[ARG_FLAGS];
+               tprintf("child_stack=%#lx, ", tcp->u_arg[ARG_STACK]);
+# ifdef ARG_STACKSIZE
+               if (ARG_STACKSIZE != -1)
+                       tprintf("stack_size=%#lx, ",
+                               tcp->u_arg[ARG_STACKSIZE]);
+# endif
+               tprintf("flags=");
+               printflags(clone_flags, flags &~ CSIGNAL, NULL);
+               if ((flags & CSIGNAL) != 0)
+                       tprintf("|%s", signame(flags & CSIGNAL));
+               if ((flags & (CLONE_PARENT_SETTID|CLONE_CHILD_SETTID
+                             |CLONE_CHILD_CLEARTID|CLONE_SETTLS)) == 0)
+                       return 0;
+               if (flags & CLONE_PARENT_SETTID)
+                       tprintf(", parent_tidptr=%#lx", tcp->u_arg[ARG_PTID]);
+               if (flags & CLONE_SETTLS) {
+# ifdef I386
+                       struct modify_ldt_ldt_s copy;
+                       if (umove(tcp, tcp->u_arg[ARG_TLS], &copy) != -1) {
+                               tprintf(", {entry_number:%d, ",
+                                       copy.entry_number);
+                               if (!verbose(tcp))
+                                       tprintf("...}");
+                               else
+                                       print_ldt_entry(&copy);
+                       }
+                       else
+# endif
+                               tprintf(", tls=%#lx", tcp->u_arg[ARG_TLS]);
+               }
+               if (flags & (CLONE_CHILD_SETTID|CLONE_CHILD_CLEARTID))
+                       tprintf(", child_tidptr=%#lx", tcp->u_arg[ARG_CTID]);
+       }
+       return 0;
+}
+#endif
 
 int
 sys_fork(tcp)
@@ -279,46 +618,334 @@ struct tcb *tcp;
        return 0;
 }
 
+int
+change_syscall(tcp, new)
+struct tcb *tcp;
+int new;
+{
+#if defined(LINUX)
+#if defined(I386)
+       /* Attempt to make vfork into fork, which we can follow. */
+       if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_EAX * 4), new) < 0)
+               return -1;
+       return 0;
+#elif defined(X86_64)
+       /* Attempt to make vfork into fork, which we can follow. */
+       if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(ORIG_RAX * 8), new) < 0)
+               return -1;
+       return 0;
+#elif defined(POWERPC)
+       if (ptrace(PTRACE_POKEUSER, tcp->pid,
+                  (char*)(sizeof(unsigned long)*PT_R0), new) < 0)
+               return -1;
+       return 0;
+#elif defined(S390) || defined(S390X)
+       /* s390 linux after 2.4.7 has a hook in entry.S to allow this */
+       if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GPR2), new)<0)
+               return -1;
+       return 0;
+#elif defined(M68K)
+       if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_ORIG_D0), new)<0)
+               return -1;
+       return 0;
+#elif defined(SPARC) || defined(SPARC64)
+       struct regs regs;
+       if (ptrace(PTRACE_GETREGS, tcp->pid, (char*)&regs, 0)<0)
+               return -1;
+       regs.r_g1=new;
+       if (ptrace(PTRACE_SETREGS, tcp->pid, (char*)&regs, 0)<0)
+               return -1;
+       return 0;
+#elif defined(MIPS)
+       if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), new)<0)
+               return -1;
+       return 0;
+#elif defined(ALPHA)
+       if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), new)<0)
+               return -1;
+       return 0;
+#elif defined(IA64)
+       if (ia32) {
+               switch (new) {
+                     case 2: break;    /* x86 SYS_fork */
+                     case SYS_clone:   new = 120; break;
+                     default:
+                       fprintf(stderr, "%s: unexpected syscall %d\n",
+                               __FUNCTION__, new);
+                       return -1;
+               }
+               if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R1), new)<0)
+                       return -1;
+       } else if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R15), new)<0)
+               return -1;
+       return 0;
+#elif defined(HPPA)
+       if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR20), new)<0)
+               return -1;
+       return 0;
+#elif defined(SH)
+       if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*(REG_REG0+3)), new)<0)
+               return -1;
+       return 0;
+#elif defined(SH64)
+       /* Top half of reg encodes the no. of args n as 0x1n.
+          Assume 0 args as kernel never actually checks... */
+       if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_SYSCALL),
+                                   0x100000 | new) < 0)
+                       return -1;
+       return 0;
+#else
+#warning Do not know how to handle change_syscall for this architecture
+#endif /* architecture */
+#endif /* LINUX */
+       return -1;
+}
+
+int
+setarg(tcp, argnum)
+       struct tcb *tcp;
+       int argnum;
+{
+#if defined (IA64)
+       {
+               unsigned long *bsp, *ap;
+
+               if (upeek(tcp->pid, PT_AR_BSP, (long *) &bsp) , 0)
+                       return -1;
+
+               ap = ia64_rse_skip_regs(bsp, argnum);
+               errno = 0;
+               ptrace(PTRACE_POKEDATA, tcp->pid, (char *) ap, tcp->u_arg[argnum]);
+               if (errno)
+                       return -1;
+
+       }
+#elif defined(I386)
+       {
+               ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*argnum), tcp->u_arg[argnum]);
+               if (errno)
+                       return -1;
+       }
+#elif defined(X86_64)
+       {
+               ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(8*(long)argnum), tcp->u_arg[argnum]);
+               if (errno)
+                       return -1;
+       }
+#elif defined(POWERPC)
+#ifndef PT_ORIG_R3
+#define PT_ORIG_R3 34
+#endif
+       {
+               ptrace(PTRACE_POKEUSER, tcp->pid,
+                      (char*)((argnum==0 ? PT_ORIG_R3 : argnum+PT_R3)*sizeof(unsigned long)),
+                      tcp->u_arg[argnum]);
+               if (errno)
+                       return -1;
+       }
+#elif defined(MIPS)
+       {
+               errno = 0;
+               if (argnum < 4)
+                       ptrace(PTRACE_POKEUSER, tcp->pid,
+                              (char*)(REG_A0 + argnum), tcp->u_arg[argnum]);
+               else {
+                       unsigned long *sp;
+
+                       if (upeek(tcp->pid, REG_SP, (long *) &sp) , 0)
+                               return -1;
+
+                       ptrace(PTRACE_POKEDATA, tcp->pid,
+                              (char*)(sp + argnum - 4), tcp->u_arg[argnum]);
+               }
+               if (errno)
+                       return -1;
+       }
+#elif defined(S390) || defined(S390X)
+        {
+               if(argnum <= 5)
+                       ptrace(PTRACE_POKEUSER, tcp->pid,
+                              (char *) (argnum==0 ? PT_ORIGGPR2 :
+                              PT_GPR2 + argnum*sizeof(long)),
+                              tcp->u_arg[argnum]);
+               else
+                       return -E2BIG;
+               if (errno)
+                       return -1;
+        }
+#else
+# warning Sorry, setargs not implemented for this architecture.
+#endif
+       return 0;
+}
+
+#if defined SYS_clone || defined SYS_clone2
+int
+internal_clone(tcp)
+struct tcb *tcp;
+{
+       struct tcb *tcpchild;
+       int pid;
+       if (entering(tcp)) {
+               if (!followfork)
+                       return 0;
+               if (fork_tcb(tcp))
+                       return 0;
+               if (setbpt(tcp) < 0)
+                       return 0;
+       } else {
+               int bpt = tcp->flags & TCB_BPTSET;
+
+               if (!(tcp->flags & TCB_FOLLOWFORK))
+                       return 0;
+
+               if (syserror(tcp)) {
+                       if (bpt)
+                               clearbpt(tcp);
+                       return 0;
+               }
+
+               pid = tcp->u_rval;
+
+#ifdef CLONE_PTRACE            /* See new setbpt code.  */
+               tcpchild = pid2tcb(pid);
+               if (tcpchild != NULL) {
+                       /* The child already reported its startup trap
+                          before the parent reported its syscall return.  */
+                       if ((tcpchild->flags
+                            & (TCB_STARTUP|TCB_ATTACHED|TCB_SUSPENDED))
+                           != (TCB_STARTUP|TCB_ATTACHED|TCB_SUSPENDED))
+                               fprintf(stderr, "\
+[preattached child %d of %d in weird state!]\n",
+                                       pid, tcp->pid);
+               }
+               else
+#endif
+               if ((tcpchild = alloctcb(pid)) == NULL) {
+                       if (bpt)
+                               clearbpt(tcp);
+                       fprintf(stderr, " [tcb table full]\n");
+                       kill(pid, SIGKILL); /* XXX */
+                       return 0;
+               }
+
+#ifndef CLONE_PTRACE
+               /* Attach to the new child */
+               if (ptrace(PTRACE_ATTACH, pid, (char *) 1, 0) < 0) {
+                       if (bpt)
+                               clearbpt(tcp);
+                       perror("PTRACE_ATTACH");
+                       fprintf(stderr, "Too late?\n");
+                       droptcb(tcpchild);
+                       return 0;
+               }
+#endif
+
+               if (bpt)
+                       clearbpt(tcp);
+
+               tcpchild->flags |= TCB_ATTACHED;
+               /* Child has BPT too, must be removed on first occasion.  */
+               if (bpt) {
+                       tcpchild->flags |= TCB_BPTSET;
+                       tcpchild->baddr = tcp->baddr;
+                       memcpy(tcpchild->inst, tcp->inst,
+                               sizeof tcpchild->inst);
+               }
+               tcpchild->parent = tcp;
+               tcp->nchildren++;
+               if (tcpchild->flags & TCB_SUSPENDED) {
+                       /* The child was born suspended, due to our having
+                          forced CLONE_PTRACE.  */
+                       if (bpt)
+                               clearbpt(tcpchild);
+
+                       tcpchild->flags &= ~(TCB_SUSPENDED|TCB_STARTUP);
+                       if (ptrace(PTRACE_SYSCALL, pid, (char *) 1, 0) < 0) {
+                               perror("resume: ptrace(PTRACE_SYSCALL, ...)");
+                               return -1;
+                       }
+
+                       if (!qflag)
+                               fprintf(stderr, "\
+Process %u resumed (parent %d ready)\n",
+                                       pid, tcp->pid);
+               }
+               else {
+                       newoutf(tcpchild);
+                       if (!qflag)
+                               fprintf(stderr, "Process %d attached\n", pid);
+               }
+
+#ifdef TCB_CLONE_THREAD
+               {
+                       /*
+                        * Save the flags used in this call,
+                        * in case we point TCP to our parent below.
+                        */
+                       int call_flags = tcp->u_arg[ARG_FLAGS];
+                       if ((tcp->flags & TCB_CLONE_THREAD) &&
+                           tcp->parent != NULL) {
+                               /* The parent in this clone is itself a
+                                  thread belonging to another process.
+                                  There is no meaning to the parentage
+                                  relationship of the new child with the
+                                  thread, only with the process.  We
+                                  associate the new thread with our
+                                  parent.  Since this is done for every
+                                  new thread, there will never be a
+                                  TCB_CLONE_THREAD process that has
+                                  children.  */
+                               --tcp->nchildren;
+                               tcp = tcp->parent;
+                               tcpchild->parent = tcp;
+                               ++tcp->nchildren;
+                       }
+                       if (call_flags & CLONE_THREAD) {
+                               tcpchild->flags |= TCB_CLONE_THREAD;
+                               ++tcp->nclone_threads;
+                       }
+                       if (call_flags & CLONE_DETACHED) {
+                               tcpchild->flags |= TCB_CLONE_DETACHED;
+                               ++tcp->nclone_detached;
+                       }
+               }
+#endif
+
+       }
+       return 0;
+}
+#endif
+
 int
 internal_fork(tcp)
 struct tcb *tcp;
 {
+#ifdef LINUX
+       /* We do special magic with clone for any clone or fork.  */
+       return internal_clone(tcp);
+#else
+
        struct tcb *tcpchild;
        int pid;
        int dont_follow = 0;
 
 #ifdef SYS_vfork
        if (tcp->scno == SYS_vfork) {
-#if defined(I386) && defined(LINUX)
                /* Attempt to make vfork into fork, which we can follow. */
-               if (!followvfork || 
-                   ptrace(PTRACE_POKEUSR, tcp->pid, 
-                          (void *)(ORIG_EAX * 4), SYS_fork) < 0) 
+               if (!followvfork ||
+                   change_syscall(tcp, SYS_fork) < 0)
                        dont_follow = 1;
-               
-#else
-               dont_follow = 1;
-#endif
        }
-#endif
-#ifdef SYS_clone
-       /* clone can do many things, not all of which we know how to handle.
-          Don't do it for now. */
-       if (tcp->scno == SYS_clone)
-               dont_follow = 1;
 #endif
        if (entering(tcp)) {
                if (!followfork || dont_follow)
                        return 0;
-               if (nprocs == MAX_PROCS) {
-                       tcp->flags &= ~TCB_FOLLOWFORK;
-                       fprintf(stderr, "sys_fork: tcb table full\n");
+               if (fork_tcb(tcp))
                        return 0;
-               }
-               tcp->flags |= TCB_FOLLOWFORK;
                if (setbpt(tcp) < 0)
                        return 0;
-       }
+       }
        else {
                int bpt = tcp->flags & TCB_BPTSET;
 
@@ -337,6 +964,24 @@ struct tcb *tcp;
                        return 0;
                }
 #ifdef LINUX
+#ifdef HPPA
+               /* The child must have run before it can be attached. */
+               /* This must be a bug in the parisc kernel, but I havn't
+                * identified it yet.  Seems to be an issue associated
+                * with attaching to a process (which sends it a signal)
+                * before that process has ever been scheduled.  When
+                * debugging, I started seeing crashes in
+                * arch/parisc/kernel/signal.c:do_signal(), apparently
+                * caused by r8 getting corrupt over the dequeue_signal()
+                * call.  Didn't make much sense though...
+                */
+               {
+                       struct timeval tv;
+                       tv.tv_sec = 0;
+                       tv.tv_usec = 10000;
+                       select(0, NULL, NULL, NULL, &tv);
+               }
+#endif
                if (ptrace(PTRACE_ATTACH, pid, (char *) 1, 0) < 0) {
                        perror("PTRACE_ATTACH");
                        fprintf(stderr, "Too late?\n");
@@ -390,11 +1035,12 @@ struct tcb *tcp;
                        fprintf(stderr, "Process %d attached\n", pid);
        }
        return 0;
+#endif
 }
 
-#endif /* !SVR4 */
+#endif /* !USE_PROCFS */
 
-#if defined(SUNOS4) || defined(LINUX)
+#if defined(SUNOS4) || defined(LINUX) || defined(FREEBSD)
 
 int
 sys_vfork(tcp)
@@ -405,7 +1051,7 @@ struct tcb *tcp;
        return 0;
 }
 
-#endif /* SUNOS4 || LINUX */
+#endif /* SUNOS4 || LINUX || FREEBSD */
 
 #ifndef LINUX
 
@@ -476,18 +1122,24 @@ sys_getresuid(tcp)
     struct tcb *tcp;
 {
        if (exiting(tcp)) {
-               uid_t res[3];
-               if (umoven(tcp, tcp->u_arg[0], sizeof(pid_t),
-                                       (char *) &res[0]) < 0
-                               || umoven(tcp, tcp->u_arg[2], sizeof(pid_t),
-                                       (char *) &res[1]) < 0
-                               || umoven(tcp, tcp->u_arg[2], sizeof(pid_t),
-                                       (char *) &res[2]) < 0)
-                       return -1;
-               tprintf("ruid %lu, euid %lu, suid %lu",
-                               (unsigned long) res[0],
-                               (unsigned long) res[1],
-                               (unsigned long) res[2]);
+               __kernel_uid_t uid;
+               if (syserror(tcp))
+                       tprintf("%#lx, %#lx, %#lx", tcp->u_arg[0],
+                               tcp->u_arg[1], tcp->u_arg[2]);
+               else {
+                       if (umove(tcp, tcp->u_arg[0], &uid) < 0)
+                               tprintf("%#lx, ", tcp->u_arg[0]);
+                       else
+                               tprintf("[%lu], ", (unsigned long) uid);
+                       if (umove(tcp, tcp->u_arg[1], &uid) < 0)
+                               tprintf("%#lx, ", tcp->u_arg[1]);
+                       else
+                               tprintf("[%lu], ", (unsigned long) uid);
+                       if (umove(tcp, tcp->u_arg[2], &uid) < 0)
+                               tprintf("%#lx", tcp->u_arg[2]);
+                       else
+                               tprintf("[%lu]", (unsigned long) uid);
+               }
        }
        return 0;
 }
@@ -497,18 +1149,24 @@ sys_getresgid(tcp)
 struct tcb *tcp;
 {
        if (exiting(tcp)) {
-               uid_t res[3];
-               if (umoven(tcp, tcp->u_arg[0], sizeof(pid_t),
-                                       (char *) &res[0]) < 0
-                               || umoven(tcp, tcp->u_arg[2], sizeof(pid_t),
-                                       (char *) &res[1]) < 0
-                               || umoven(tcp, tcp->u_arg[2], sizeof(pid_t),
-                                       (char *) &res[2]) < 0)
-                       return -1;
-               tprintf("rgid %lu, egid %lu, sgid %lu",
-                               (unsigned long) res[0],
-                               (unsigned long) res[1],
-                               (unsigned long) res[2]);
+               __kernel_gid_t gid;
+               if (syserror(tcp))
+                       tprintf("%#lx, %#lx, %#lx", tcp->u_arg[0],
+                               tcp->u_arg[1], tcp->u_arg[2]);
+               else {
+                       if (umove(tcp, tcp->u_arg[0], &gid) < 0)
+                               tprintf("%#lx, ", tcp->u_arg[0]);
+                       else
+                               tprintf("[%lu], ", (unsigned long) gid);
+                       if (umove(tcp, tcp->u_arg[1], &gid) < 0)
+                               tprintf("%#lx, ", tcp->u_arg[1]);
+                       else
+                               tprintf("[%lu], ", (unsigned long) gid);
+                       if (umove(tcp, tcp->u_arg[2], &gid) < 0)
+                               tprintf("%#lx", tcp->u_arg[2]);
+                       else
+                               tprintf("[%lu]", (unsigned long) gid);
+               }
        }
        return 0;
 }
@@ -520,9 +1178,8 @@ sys_setreuid(tcp)
 struct tcb *tcp;
 {
        if (entering(tcp)) {
-               tprintf("%lu, %lu",
-                       (unsigned long) (uid_t) tcp->u_arg[0],
-                       (unsigned long) (uid_t) tcp->u_arg[1]);
+               printuid("", tcp->u_arg[0]);
+               printuid(", ", tcp->u_arg[1]);
        }
        return 0;
 }
@@ -532,23 +1189,21 @@ sys_setregid(tcp)
 struct tcb *tcp;
 {
        if (entering(tcp)) {
-               tprintf("%lu, %lu",
-                       (unsigned long) (gid_t) tcp->u_arg[0],
-                       (unsigned long) (gid_t) tcp->u_arg[1]);
+               printuid("", tcp->u_arg[0]);
+               printuid(", ", tcp->u_arg[1]);
        }
        return 0;
 }
 
-#ifdef LINUX
+#if defined(LINUX) || defined(FREEBSD)
 int
 sys_setresuid(tcp)
      struct tcb *tcp;
 {
        if (entering(tcp)) {
-               tprintf("ruid %u, euid %u, suid %u",
-                               (uid_t) tcp->u_arg[0],
-                               (uid_t) tcp->u_arg[1],
-                               (uid_t) tcp->u_arg[2]);
+               printuid("", tcp->u_arg[0]);
+               printuid(", ", tcp->u_arg[1]);
+               printuid(", ", tcp->u_arg[2]);
        }
        return 0;
 }
@@ -557,48 +1212,66 @@ sys_setresgid(tcp)
      struct tcb *tcp;
 {
        if (entering(tcp)) {
-               tprintf("rgid %u, egid %u, sgid %u",
-                               (uid_t) tcp->u_arg[0],
-                               (uid_t) tcp->u_arg[1],
-                               (uid_t) tcp->u_arg[2]);
+               printuid("", tcp->u_arg[0]);
+               printuid(", ", tcp->u_arg[1]);
+               printuid(", ", tcp->u_arg[2]);
        }
        return 0;
 }
 
-#endif /* LINUX */
+#endif /* LINUX || FREEBSD */
 
 int
 sys_setgroups(tcp)
 struct tcb *tcp;
 {
-       int i, len;
-       GETGROUPS_T *gidset;
-
        if (entering(tcp)) {
+               unsigned long len, size, start, cur, end, abbrev_end;
+               GETGROUPS_T gid;
+               int failed = 0;
+
                len = tcp->u_arg[0];
-               tprintf("%u, ", len);
-               if (len <= 0) {
+               tprintf("%lu, ", len);
+               if (len == 0) {
                        tprintf("[]");
                        return 0;
                }
-               gidset = (GETGROUPS_T *) malloc(len * sizeof(GETGROUPS_T));
-               if (gidset == NULL) {
-                       fprintf(stderr, "sys_setgroups: out of memory\n");
-                       return -1;
+               start = tcp->u_arg[1];
+               if (start == 0) {
+                       tprintf("NULL");
+                       return 0;
                }
-               if (!verbose(tcp))
-                       tprintf("%#lx", tcp->u_arg[1]);
-               else if (umoven(tcp, tcp->u_arg[1],
-                   len * sizeof(GETGROUPS_T), (char *) gidset) < 0)
-                       tprintf("[?]");
-               else {
-                       tprintf("[");
-                       for (i = 0; i < len; i++)
-                               tprintf("%s%lu", i ? ", " : "",
-                                       (unsigned long) gidset[i]);
-                       tprintf("]");
+               size = len * sizeof(gid);
+               end = start + size;
+               if (!verbose(tcp) || size / sizeof(gid) != len || end < start) {
+                       tprintf("%#lx", start);
+                       return 0;
                }
-               free((char *) gidset);
+               if (abbrev(tcp)) {
+                       abbrev_end = start + max_strlen * sizeof(gid);
+                       if (abbrev_end < start)
+                               abbrev_end = end;
+               } else {
+                       abbrev_end = end;
+               }
+               tprintf("[");
+               for (cur = start; cur < end; cur += sizeof(gid)) {
+                       if (cur > start)
+                               tprintf(", ");
+                       if (cur >= abbrev_end) {
+                               tprintf("...");
+                               break;
+                       }
+                       if (umoven(tcp, cur, sizeof(gid), (char *) &gid) < 0) {
+                               tprintf("?");
+                               failed = 1;
+                               break;
+                       }
+                       tprintf("%lu", (unsigned long) gid);
+               }
+               tprintf("]");
+               if (failed)
+                       tprintf(" %#lx", tcp->u_arg[1]);
        }
        return 0;
 }
@@ -607,42 +1280,183 @@ int
 sys_getgroups(tcp)
 struct tcb *tcp;
 {
-       int i, len;
-       GETGROUPS_T *gidset;
+       unsigned long len;
 
        if (entering(tcp)) {
                len = tcp->u_arg[0];
-               tprintf("%u, ", len);
+               tprintf("%lu, ", len);
        } else {
+               unsigned long size, start, cur, end, abbrev_end;
+               GETGROUPS_T gid;
+               int failed = 0;
+
                len = tcp->u_rval;
-               if (len <= 0) {
+               if (len == 0) {
                        tprintf("[]");
                        return 0;
                }
-               gidset = (GETGROUPS_T *) malloc(len * sizeof(GETGROUPS_T));
-               if (gidset == NULL) {
-                       fprintf(stderr, "sys_getgroups: out of memory\n");
-                       return -1;
+               start = tcp->u_arg[1];
+               if (start == 0) {
+                       tprintf("NULL");
+                       return 0;
                }
-               if (!tcp->u_arg[1])
+               if (tcp->u_arg[0] == 0) {
+                       tprintf("%#lx", start);
+                       return 0;
+               }
+               size = len * sizeof(gid);
+               end = start + size;
+               if (!verbose(tcp) || tcp->u_arg[0] == 0 ||
+                   size / sizeof(gid) != len || end < start) {
+                       tprintf("%#lx", start);
+                       return 0;
+               }
+               if (abbrev(tcp)) {
+                       abbrev_end = start + max_strlen * sizeof(gid);
+                       if (abbrev_end < start)
+                               abbrev_end = end;
+               } else {
+                       abbrev_end = end;
+               }
+               tprintf("[");
+               for (cur = start; cur < end; cur += sizeof(gid)) {
+                       if (cur > start)
+                               tprintf(", ");
+                       if (cur >= abbrev_end) {
+                               tprintf("...");
+                               break;
+                       }
+                       if (umoven(tcp, cur, sizeof(gid), (char *) &gid) < 0) {
+                               tprintf("?");
+                               failed = 1;
+                               break;
+                       }
+                       tprintf("%lu", (unsigned long) gid);
+               }
+               tprintf("]");
+               if (failed)
+                       tprintf(" %#lx", tcp->u_arg[1]);
+       }
+       return 0;
+}
+
+#ifdef LINUX
+int
+sys_setgroups32(tcp)
+struct tcb *tcp;
+{
+       if (entering(tcp)) {
+               unsigned long len, size, start, cur, end, abbrev_end;
+               GETGROUPS32_T gid;
+               int failed = 0;
+
+               len = tcp->u_arg[0];
+               tprintf("%lu, ", len);
+               if (len == 0) {
+                       tprintf("[]");
+                       return 0;
+               }
+               start = tcp->u_arg[1];
+               if (start == 0) {
                        tprintf("NULL");
-               else if (!verbose(tcp) || tcp->u_arg[0] == 0)
-                       tprintf("%#lx", tcp->u_arg[1]);
-               else if (umoven(tcp, tcp->u_arg[1],
-                   len * sizeof(GETGROUPS_T), (char *) gidset) < 0)
-                       tprintf("[?]");
-               else {
-                       tprintf("[");
-                       for (i = 0; i < len; i++)
-                               tprintf("%s%lu", i ? ", " : "",
-                                       (unsigned long) gidset[i]);
-                       tprintf("]");
+                       return 0;
+               }
+               size = len * sizeof(gid);
+               end = start + size;
+               if (!verbose(tcp) || size / sizeof(gid) != len || end < start) {
+                       tprintf("%#lx", start);
+                       return 0;
                }
-               free((char *)gidset);
+               if (abbrev(tcp)) {
+                       abbrev_end = start + max_strlen * sizeof(gid);
+                       if (abbrev_end < start)
+                               abbrev_end = end;
+               } else {
+                       abbrev_end = end;
+               }
+               tprintf("[");
+               for (cur = start; cur < end; cur += sizeof(gid)) {
+                       if (cur > start)
+                               tprintf(", ");
+                       if (cur >= abbrev_end) {
+                               tprintf("...");
+                               break;
+                       }
+                       if (umoven(tcp, cur, sizeof(gid), (char *) &gid) < 0) {
+                               tprintf("?");
+                               failed = 1;
+                               break;
+                       }
+                       tprintf("%lu", (unsigned long) gid);
+               }
+               tprintf("]");
+               if (failed)
+                       tprintf(" %#lx", tcp->u_arg[1]);
        }
        return 0;
 }
 
+int
+sys_getgroups32(tcp)
+struct tcb *tcp;
+{
+       unsigned long len;
+
+       if (entering(tcp)) {
+               len = tcp->u_arg[0];
+               tprintf("%lu, ", len);
+       } else {
+               unsigned long size, start, cur, end, abbrev_end;
+               GETGROUPS32_T gid;
+               int failed = 0;
+
+               len = tcp->u_rval;
+               if (len == 0) {
+                       tprintf("[]");
+                       return 0;
+               }
+               start = tcp->u_arg[1];
+               if (start == 0) {
+                       tprintf("NULL");
+                       return 0;
+               }
+               size = len * sizeof(gid);
+               end = start + size;
+               if (!verbose(tcp) || tcp->u_arg[0] == 0 ||
+                   size / sizeof(gid) != len || end < start) {
+                       tprintf("%#lx", start);
+                       return 0;
+               }
+               if (abbrev(tcp)) {
+                       abbrev_end = start + max_strlen * sizeof(gid);
+                       if (abbrev_end < start)
+                               abbrev_end = end;
+               } else {
+                       abbrev_end = end;
+               }
+               tprintf("[");
+               for (cur = start; cur < end; cur += sizeof(gid)) {
+                       if (cur > start)
+                               tprintf(", ");
+                       if (cur >= abbrev_end) {
+                               tprintf("...");
+                               break;
+                       }
+                       if (umoven(tcp, cur, sizeof(gid), (char *) &gid) < 0) {
+                               tprintf("?");
+                               failed = 1;
+                               break;
+                       }
+                       tprintf("%lu", (unsigned long) gid);
+               }
+               tprintf("]");
+               if (failed)
+                       tprintf(" %#lx", tcp->u_arg[1]);
+       }
+       return 0;
+}
+#endif /* LINUX */
+
 int
 sys_setpgrp(tcp)
 struct tcb *tcp;
@@ -704,39 +1518,144 @@ struct tcb *tcp;
        return 0;
 }
 
-void
-fake_execve(tcp, program, argv, envp)
+#if UNIXWARE >= 2
+
+#include <sys/privilege.h>
+
+
+static const struct xlat procpriv_cmds [] = {
+       { SETPRV,       "SETPRV"        },
+       { CLRPRV,       "CLRPRV"        },
+       { PUTPRV,       "PUTPRV"        },
+       { GETPRV,       "GETPRV"        },
+       { CNTPRV,       "CNTPRV"        },
+       { 0,            NULL            },
+};
+
+
+static const struct xlat procpriv_priv [] = {
+       { P_OWNER,      "P_OWNER"       },
+       { P_AUDIT,      "P_AUDIT"       },
+       { P_COMPAT,     "P_COMPAT"      },
+       { P_DACREAD,    "P_DACREAD"     },
+       { P_DACWRITE,   "P_DACWRITE"    },
+       { P_DEV,        "P_DEV"         },
+       { P_FILESYS,    "P_FILESYS"     },
+       { P_MACREAD,    "P_MACREAD"     },
+       { P_MACWRITE,   "P_MACWRITE"    },
+       { P_MOUNT,      "P_MOUNT"       },
+       { P_MULTIDIR,   "P_MULTIDIR"    },
+       { P_SETPLEVEL,  "P_SETPLEVEL"   },
+       { P_SETSPRIV,   "P_SETSPRIV"    },
+       { P_SETUID,     "P_SETUID"      },
+       { P_SYSOPS,     "P_SYSOPS"      },
+       { P_SETUPRIV,   "P_SETUPRIV"    },
+       { P_DRIVER,     "P_DRIVER"      },
+       { P_RTIME,      "P_RTIME"       },
+       { P_MACUPGRADE, "P_MACUPGRADE"  },
+       { P_FSYSRANGE,  "P_FSYSRANGE"   },
+       { P_SETFLEVEL,  "P_SETFLEVEL"   },
+       { P_AUDITWR,    "P_AUDITWR"     },
+       { P_TSHAR,      "P_TSHAR"       },
+       { P_PLOCK,      "P_PLOCK"       },
+       { P_CORE,       "P_CORE"        },
+       { P_LOADMOD,    "P_LOADMOD"     },
+       { P_BIND,       "P_BIND"        },
+       { P_ALLPRIVS,   "P_ALLPRIVS"    },
+       { 0,            NULL            },
+};
+
+
+static const struct xlat procpriv_type [] = {
+       { PS_FIX,       "PS_FIX"        },
+       { PS_INH,       "PS_INH"        },
+       { PS_MAX,       "PS_MAX"        },
+       { PS_WKG,       "PS_WKG"        },
+       { 0,            NULL            },
+};
+
+
+static void
+printpriv(tcp, addr, len, opt)
 struct tcb *tcp;
-char *program;
-char *argv[];
-char *envp[];
+long addr;
+int len;
+const struct xlat *opt;
 {
+       priv_t buf [128];
+       int max = verbose (tcp) ? sizeof buf / sizeof buf [0] : 10;
+       int dots = len > max;
        int i;
 
-#ifdef ARM
-       if (!(qual_flags[SYS_execve - __NR_SYSCALL_BASE] & QUAL_TRACE))
-               return;
-#else
-       if (!(qual_flags[SYS_execve] & QUAL_TRACE))
+       if (len > max) len = max;
+
+       if (len <= 0 ||
+           umoven (tcp, addr, len * sizeof buf[0], (char *) buf) < 0)
+       {
+               tprintf ("%#lx", addr);
                return;
-#endif /* !ARM */
-       printleader(tcp);
-       tprintf("execve(");
-       string_quote(program);
-       tprintf(", [");
-       for (i = 0; argv[i] != NULL; i++) {
-               if (i != 0)
-                       tprintf(", ");
-               string_quote(argv[i]);
        }
-       for (i = 0; envp[i] != NULL; i++)
-               ;
-       tprintf("], [/* %d var%s */]) ", i, (i != 1) ? "s" : "");
-       tabto(acolumn);
-       tprintf("= 0");
-       printtrailer(tcp);
+
+       tprintf ("[");
+
+       for (i = 0; i < len; ++i) {
+               char *t, *p;
+
+               if (i) tprintf (", ");
+
+               if ((t = xlookup (procpriv_type, buf [i] & PS_TYPE)) &&
+                   (p = xlookup (procpriv_priv, buf [i] & ~PS_TYPE)))
+               {
+                       tprintf ("%s|%s", t, p);
+               }
+               else {
+                       tprintf ("%#lx", buf [i]);
+               }
+       }
+
+       if (dots) tprintf (" ...");
+
+       tprintf ("]");
+}
+
+
+int
+sys_procpriv(tcp)
+struct tcb *tcp;
+{
+       if (entering(tcp)) {
+               printxval(procpriv_cmds, tcp->u_arg[0], "???PRV");
+               switch (tcp->u_arg[0]) {
+                   case CNTPRV:
+                       tprintf(", %#lx, %ld", tcp->u_arg[1], tcp->u_arg[2]);
+                       break;
+
+                   case GETPRV:
+                       break;
+
+                   default:
+                       tprintf (", ");
+                       printpriv (tcp, tcp->u_arg[1], tcp->u_arg[2]);
+                       tprintf (", %ld", tcp->u_arg[2]);
+               }
+       }
+       else if (tcp->u_arg[0] == GETPRV) {
+               if (syserror (tcp)) {
+                       tprintf(", %#lx, %ld", tcp->u_arg[1], tcp->u_arg[2]);
+               }
+               else {
+                       tprintf (", ");
+                       printpriv (tcp, tcp->u_arg[1], tcp->u_rval);
+                       tprintf (", %ld", tcp->u_arg[2]);
+               }
+       }
+
+       return 0;
 }
 
+#endif
+
+
 static void
 printargv(tcp, addr)
 struct tcb *tcp;
@@ -826,14 +1745,23 @@ struct tcb *tcp;
                        tprintf("]");
                }
        }
-#ifdef LINUX
-#if defined(ALPHA) || defined(SPARC) || defined(POWERPC)
-       tcp->flags |= TCB_WAITEXECVE;
-#endif /* ALPHA || SPARC || POWERPC */
-#endif /* LINUX */
        return 0;
 }
 
+#if UNIXWARE > 2
+
+int sys_rexecve(tcp)
+struct tcb *tcp;
+{
+       if (entering (tcp)) {
+               sys_execve (tcp);
+               tprintf (", %ld", tcp->u_arg[3]);
+       }
+       return 0;
+}
+
+#endif
+
 int
 internal_exec(tcp)
 struct tcb *tcp;
@@ -842,16 +1770,28 @@ struct tcb *tcp;
        if (exiting(tcp) && !syserror(tcp) && followfork)
                fixvfork(tcp);
 #endif /* SUNOS4 */
+#if defined LINUX && defined TCB_WAITEXECVE
+       if (exiting(tcp) && syserror(tcp))
+               tcp->flags &= ~TCB_WAITEXECVE;
+       else
+               tcp->flags |= TCB_WAITEXECVE;
+#endif /* LINUX && TCB_WAITEXECVE */
        return 0;
 }
 
 #ifdef LINUX
+#ifndef __WNOTHREAD
+#define __WNOTHREAD    0x20000000
+#endif
+#ifndef __WALL
+#define __WALL         0x40000000
+#endif
 #ifndef __WCLONE
-#define __WCLONE       0x8000000
+#define __WCLONE       0x80000000
 #endif
 #endif /* LINUX */
 
-static struct xlat wait4_options[] = {
+static const struct xlat wait4_options[] = {
        { WNOHANG,      "WNOHANG"       },
 #ifndef WSTOPPED
        { WUNTRACED,    "WUNTRACED"     },
@@ -873,10 +1813,30 @@ static struct xlat wait4_options[] = {
 #endif
 #ifdef __WCLONE
        { __WCLONE,     "__WCLONE"      },
+#endif
+#ifdef __WALL
+       { __WALL,       "__WALL"        },
+#endif
+#ifdef __WNOTHREAD
+       { __WNOTHREAD,  "__WNOTHREAD"   },
 #endif
        { 0,            NULL            },
 };
 
+#if !defined WCOREFLAG && defined WCOREFLG
+# define WCOREFLAG WCOREFLG
+#endif
+#ifndef WCOREFLAG
+#define WCOREFLAG 0x80
+#endif
+
+#ifndef W_STOPCODE
+#define W_STOPCODE(sig)                ((sig) << 8 | 0x7f)
+#endif
+#ifndef W_EXITCODE
+#define W_EXITCODE(ret, sig)   ((ret) << 8 | (sig))
+#endif
+
 static int
 printstatus(status)
 int status;
@@ -888,27 +1848,41 @@ int status;
         * is still not entirely satisfactory but since there
         * are no wait status constructors it will have to do.
         */
-       if (WIFSTOPPED(status))
-               tprintf("[WIFSTOPPED(s) && WSTOPSIG(s) == %s]",
-                       signalent[WSTOPSIG(status)]);
-       else if WIFSIGNALED(status)
-               tprintf("[WIFSIGNALED(s) && WTERMSIG(s) == %s%s]",
-                       signalent[WTERMSIG(status)],
+       if (WIFSTOPPED(status)) {
+               tprintf("[{WIFSTOPPED(s) && WSTOPSIG(s) == %s}",
+                       signame(WSTOPSIG(status)));
+               status &= ~W_STOPCODE(WSTOPSIG(status));
+       }
+       else if (WIFSIGNALED(status)) {
+               tprintf("[{WIFSIGNALED(s) && WTERMSIG(s) == %s%s}",
+                       signame(WTERMSIG(status)),
                        WCOREDUMP(status) ? " && WCOREDUMP(s)" : "");
-       else if WIFEXITED(status) {
-               tprintf("[WIFEXITED(s) && WEXITSTATUS(s) == %d]",
+               status &= ~(W_EXITCODE(0, WTERMSIG(status)) | WCOREFLAG);
+       }
+       else if (WIFEXITED(status)) {
+               tprintf("[{WIFEXITED(s) && WEXITSTATUS(s) == %d}",
                        WEXITSTATUS(status));
                exited = 1;
+               status &= ~W_EXITCODE(WEXITSTATUS(status), 0);
        }
-       else
+       else {
                tprintf("[%#x]", status);
+               return 0;
+       }
+
+       if (status == 0)
+               tprintf("]");
+       else
+               tprintf(" | %#x]", status);
+
        return exited;
 }
 
 static int
-printwaitn(tcp, n)
+printwaitn(tcp, n, bitness)
 struct tcb *tcp;
 int n;
+int bitness;
 {
        int status;
        int exited = 0;
@@ -927,16 +1901,21 @@ int n;
                        exited = printstatus(status);
                /* options */
                tprintf(", ");
-               if (!printflags(wait4_options, tcp->u_arg[2]))
-                       tprintf("0");
+               printflags(wait4_options, tcp->u_arg[2], "W???");
                if (n == 4) {
                        tprintf(", ");
                        /* usage */
                        if (!tcp->u_arg[3])
                                tprintf("NULL");
 #ifdef LINUX
-                       else if (tcp->u_rval > 0)
-                               printrusage(tcp, tcp->u_arg[3]);
+                       else if (tcp->u_rval > 0) {
+#ifdef LINUX_64BIT
+                               if (bitness)
+                                       printrusage32(tcp, tcp->u_arg[3]);
+                               else
+#endif
+                                       printrusage(tcp, tcp->u_arg[3]);
+                       }
 #endif /* LINUX */
 #ifdef SUNOS4
                        else if (tcp->u_rval > 0 && exited)
@@ -950,17 +1929,90 @@ int n;
 }
 
 int
-internal_wait(tcp)
+internal_wait(tcp, flagarg)
 struct tcb *tcp;
+int flagarg;
 {
-       if (entering(tcp)) {
-               /* WTA: fix bug with hanging children */
-               if (!(tcp->u_arg[2] & WNOHANG) && tcp->nchildren > 0) {
-                       /* There are traced children */
+       int got_kids;
+
+#ifdef TCB_CLONE_THREAD
+       if (tcp->flags & TCB_CLONE_THREAD)
+               /* The children we wait for are our parent's children.  */
+               got_kids = (tcp->parent->nchildren
+                           > tcp->parent->nclone_detached);
+       else
+               got_kids = (tcp->nchildren > tcp->nclone_detached);
+#else
+       got_kids = tcp->nchildren > 0;
+#endif
+
+       if (entering(tcp) && got_kids) {
+               /* There are children that this parent should block for.
+                  But ptrace made us the parent of the traced children
+                  and the real parent will get ECHILD from the wait call.
+
+                  XXX If we attached with strace -f -p PID, then there
+                  may be untraced dead children the parent could be reaping
+                  now, but we make him block.  */
+
+               /* ??? WTA: fix bug with hanging children */
+
+               if (!(tcp->u_arg[flagarg] & WNOHANG)) {
+                       /*
+                        * There are traced children.  We'll make the parent
+                        * block to avoid a false ECHILD error due to our
+                        * ptrace having stolen the children.  However,
+                        * we shouldn't block if there are zombies to reap.
+                        * XXX doesn't handle pgrp matches (u_arg[0]==0,<-1)
+                        */
+                       struct tcb *child = NULL;
+                       if (tcp->nzombies > 0 &&
+                           (tcp->u_arg[0] == -1 ||
+                            (child = pid2tcb(tcp->u_arg[0])) == NULL))
+                               return 0;
+                       if (tcp->u_arg[0] > 0) {
+                               /*
+                                * If the parent waits for a specified child
+                                * PID, then it must get ECHILD right away
+                                * if that PID is not one of its children.
+                                * Make sure that the requested PID matches
+                                * one of the parent's children that we are
+                                * tracing, and don't suspend it otherwise.
+                                */
+                               if (child == NULL)
+                                       child = pid2tcb(tcp->u_arg[0]);
+                               if (child == NULL || child->parent != (
+#ifdef TCB_CLONE_THREAD
+                                           (tcp->flags & TCB_CLONE_THREAD)
+                                           ? tcp->parent :
+#endif
+                                           tcp))
+                                       return 0;
+                       }
                        tcp->flags |= TCB_SUSPENDED;
                        tcp->waitpid = tcp->u_arg[0];
+#ifdef TCB_CLONE_THREAD
+                       if (tcp->flags & TCB_CLONE_THREAD)
+                               tcp->parent->nclone_waiting++;
+#endif
+               }
+       }
+       if (exiting(tcp) && tcp->u_error == ECHILD && got_kids) {
+               if (tcp->u_arg[flagarg] & WNOHANG) {
+                       /* We must force a fake result of 0 instead of
+                          the ECHILD error.  */
+                       extern int force_result();
+                       return force_result(tcp, 0, 0);
                }
        }
+       else if (exiting(tcp) && tcp->u_error == 0 && tcp->u_rval > 0 &&
+                tcp->nzombies > 0 && pid2tcb(tcp->u_rval) == NULL) {
+               /*
+                * We just reaped a child we don't know about,
+                * presumably a zombie we already droptcb'd.
+                */
+               tcp->nzombies--;
+       }
        return 0;
 }
 
@@ -980,30 +2032,68 @@ struct tcb *tcp;
 
 #endif /* SVR4 */
 
+#ifdef FREEBSD
+int
+sys_wait(tcp)
+struct tcb *tcp;
+{
+       int status;
+
+       if (exiting(tcp)) {
+               if (!syserror(tcp)) {
+                       if (umove(tcp, tcp->u_arg[0], &status) < 0)
+                               tprintf("%#lx", tcp->u_arg[0]);
+                       else
+                               printstatus(status);
+               }
+       }
+       return 0;
+}
+#endif
+
 int
 sys_waitpid(tcp)
 struct tcb *tcp;
 {
-       return printwaitn(tcp, 3);
+       return printwaitn(tcp, 3, 0);
 }
 
 int
 sys_wait4(tcp)
 struct tcb *tcp;
 {
-       return printwaitn(tcp, 4);
+       return printwaitn(tcp, 4, 0);
 }
 
-#ifdef SVR4
+#ifdef ALPHA
+int
+sys_osf_wait4(tcp)
+struct tcb *tcp;
+{
+       return printwaitn(tcp, 4, 1);
+}
+#endif
 
-static struct xlat waitid_types[] = {
+#if defined SVR4 || defined LINUX
+
+static const struct xlat waitid_types[] = {
        { P_PID,        "P_PID"         },
+#ifdef P_PPID
        { P_PPID,       "P_PPID"        },
+#endif
        { P_PGID,       "P_PGID"        },
+#ifdef P_SID
        { P_SID,        "P_SID"         },
+#endif
+#ifdef P_CID
        { P_CID,        "P_CID"         },
+#endif
+#ifdef P_UID
        { P_UID,        "P_UID"         },
+#endif
+#ifdef P_GID
        { P_GID,        "P_GID"         },
+#endif
        { P_ALL,        "P_ALL"         },
 #ifdef P_LWPID
        { P_LWPID,      "P_LWPID"       },
@@ -1011,213 +2101,6 @@ static struct xlat waitid_types[] = {
        { 0,            NULL            },
 };
 
-static struct xlat siginfo_codes[] = {
-#ifdef SI_NOINFO
-       { SI_NOINFO,    "SI_NOINFO"     },
-#endif
-#ifdef SI_USER
-       { SI_USER,      "SI_USER"       },
-#endif
-#ifdef SI_LWP
-       { SI_LWP,       "SI_LWP"        },
-#endif
-#ifdef SI_QUEUE
-       { SI_QUEUE,     "SI_QUEUE"      },
-#endif
-#ifdef SI_TIMER
-       { SI_TIMER,     "SI_TIMER"      },
-#endif
-#ifdef SI_ASYNCIO
-       { SI_ASYNCIO,   "SI_ASYNCIO"    },
-#endif
-#ifdef SI_MESGQ
-       { SI_MESGQ,     "SI_MESGQ"      },
-#endif
-       { 0,            NULL            },
-};
-
-static struct xlat sigtrap_codes[] = {
-       { TRAP_BRKPT,   "TRAP_BRKPT"    },
-       { TRAP_TRACE,   "TRAP_TRACE"    },
-       { 0,            NULL            },
-};
-
-static struct xlat sigcld_codes[] = {
-       { CLD_EXITED,   "CLD_EXITED"    },
-       { CLD_KILLED,   "CLD_KILLED"    },
-       { CLD_DUMPED,   "CLD_DUMPED"    },
-       { CLD_TRAPPED,  "CLD_TRAPPED"   },
-       { CLD_STOPPED,  "CLD_STOPPED"   },
-       { CLD_CONTINUED,"CLD_CONTINUED" },
-       { 0,            NULL            },
-};
-
-static struct xlat sigpoll_codes[] = {
-       { POLL_IN,      "POLL_IN"       },
-       { POLL_OUT,     "POLL_OUT"      },
-       { POLL_MSG,     "POLL_MSG"      },
-       { POLL_ERR,     "POLL_ERR"      },
-       { POLL_PRI,     "POLL_PRI"      },
-       { POLL_HUP,     "POLL_HUP"      },
-       { 0,            NULL            },
-};
-
-static struct xlat sigprof_codes[] = {
-#ifdef PROF_SIG
-       { PROF_SIG,     "PROF_SIG"      },
-#endif
-       { 0,            NULL            },
-};
-
-static struct xlat sigill_codes[] = {
-       { ILL_ILLOPC,   "ILL_ILLOPC"    },
-       { ILL_ILLOPN,   "ILL_ILLOPN"    },
-       { ILL_ILLADR,   "ILL_ILLADR"    },
-       { ILL_ILLTRP,   "ILL_ILLTRP"    },
-       { ILL_PRVOPC,   "ILL_PRVOPC"    },
-       { ILL_PRVREG,   "ILL_PRVREG"    },
-       { ILL_COPROC,   "ILL_COPROC"    },
-       { ILL_BADSTK,   "ILL_BADSTK"    },
-       { 0,            NULL            },
-};
-
-static struct xlat sigemt_codes[] = {
-#ifdef EMT_TAGOVF
-       { EMT_TAGOVF,   "EMT_TAGOVF"    },
-#endif
-       { 0,            NULL            },
-};
-
-static struct xlat sigfpe_codes[] = {
-       { FPE_INTDIV,   "FPE_INTDIV"    },
-       { FPE_INTOVF,   "FPE_INTOVF"    },
-       { FPE_FLTDIV,   "FPE_FLTDIV"    },
-       { FPE_FLTOVF,   "FPE_FLTOVF"    },
-       { FPE_FLTUND,   "FPE_FLTUND"    },
-       { FPE_FLTRES,   "FPE_FLTRES"    },
-       { FPE_FLTINV,   "FPE_FLTINV"    },
-       { FPE_FLTSUB,   "FPE_FLTSUB"    },
-       { 0,            NULL            },
-};
-
-static struct xlat sigsegv_codes[] = {
-       { SEGV_MAPERR,  "SEGV_MAPERR"   },
-       { SEGV_ACCERR,  "SEGV_ACCERR"   },
-       { 0,            NULL            },
-};
-
-static struct xlat sigbus_codes[] = {
-       { BUS_ADRALN,   "BUS_ADRALN"    },
-       { BUS_ADRERR,   "BUS_ADRERR"    },
-       { BUS_OBJERR,   "BUS_OBJERR"    },
-       { 0,            NULL            },
-};
-
-void
-printsiginfo(sip)
-siginfo_t *sip;
-{
-       char *code;
-
-       tprintf("{si_signo=");
-       printsignal(sip->si_signo);
-       code = xlookup(siginfo_codes, sip->si_code);
-       if (!code) {
-               switch (sip->si_signo) {
-               case SIGTRAP:
-                       code = xlookup(sigtrap_codes, sip->si_code);
-                       break;
-               case SIGCHLD:
-                       code = xlookup(sigcld_codes, sip->si_code);
-                       break;
-               case SIGPOLL:
-                       code = xlookup(sigpoll_codes, sip->si_code);
-                       break;
-               case SIGPROF:
-                       code = xlookup(sigprof_codes, sip->si_code);
-                       break;
-               case SIGILL:
-                       code = xlookup(sigill_codes, sip->si_code);
-                       break;
-               case SIGEMT:
-                       code = xlookup(sigemt_codes, sip->si_code);
-                       break;
-               case SIGFPE:
-                       code = xlookup(sigfpe_codes, sip->si_code);
-                       break;
-               case SIGSEGV:
-                       code = xlookup(sigsegv_codes, sip->si_code);
-                       break;
-               case SIGBUS:
-                       code = xlookup(sigbus_codes, sip->si_code);
-                       break;
-               }
-       }
-       if (code)
-               tprintf(", si_code=%s", code);
-       else
-               tprintf(", si_code=%#x", sip->si_code);
-#ifdef SI_NOINFO
-       if (sip->si_code != SI_NOINFO) {
-#endif
-               if (sip->si_errno) {
-                       if (sip->si_errno < 0 || sip->si_errno >= nerrnos)
-                               tprintf(", si_errno=%d", sip->si_errno);
-                       else
-                               tprintf(", si_errno=%s",
-                                       errnoent[sip->si_errno]);
-               }
-               if (SI_FROMUSER(sip)) {
-#ifdef SI_QUEUE
-                       tprintf(", si_pid=%ld, si_uid=%ld",
-                               sip->si_pid, sip->si_uid);
-                       switch (sip->si_code) {
-                       case SI_QUEUE:
-#ifdef SI_TIMER
-                       case SI_TIMER:
-#endif /* SI_QUEUE */
-                       case SI_ASYNCIO:
-#ifdef SI_MESGQ
-                       case SI_MESGQ:
-#endif /* SI_MESGQ */
-                               tprintf(", si_value=%d",
-                                       sip->si_value.sival_int);
-                               break;
-                       }
-#endif /* SI_QUEUE */
-               }
-               else {
-                       switch (sip->si_signo) {
-                       case SIGCHLD:
-                               tprintf(", si_pid=%ld, si_status=",
-                                       sip->si_pid);
-                               if (sip->si_code == CLD_EXITED)
-                                       tprintf("%d", sip->si_status);
-                               else
-                                       printsignal(sip->si_status);
-                               break;
-                       case SIGILL: case SIGFPE:
-                       case SIGSEGV: case SIGBUS:
-                               tprintf(", si_addr=%#lx",
-                                       (unsigned long) sip->si_addr);
-                               break;
-                       case SIGPOLL:
-                               switch (sip->si_code) {
-                               case POLL_IN: case POLL_OUT: case POLL_MSG:
-                                       tprintf(", si_band=%ld",
-                                               (long) sip->si_band);
-                                       break;
-                               }
-                               break;
-                       }
-               }
-               tprintf(", ...");
-#ifdef SI_NOINFO
-       }
-#endif
-       tprintf("}");
-}
-
 int
 sys_waitid(tcp)
 struct tcb *tcp;
@@ -1228,11 +2111,6 @@ struct tcb *tcp;
        if (entering(tcp)) {
                printxval(waitid_types, tcp->u_arg[0], "P_???");
                tprintf(", %ld, ", tcp->u_arg[1]);
-               if (tcp->nchildren > 0) {
-                       /* There are traced children */
-                       tcp->flags |= TCB_SUSPENDED;
-                       tcp->waitpid = tcp->u_arg[0];
-               }
        }
        else {
                /* siginfo */
@@ -1244,16 +2122,25 @@ struct tcb *tcp;
                else if (umove(tcp, tcp->u_arg[2], &si) < 0)
                        tprintf("{???}");
                else
-                       printsiginfo(&si);
+                       printsiginfo(&si, verbose (tcp));
                /* options */
                tprintf(", ");
-               if (!printflags(wait4_options, tcp->u_arg[3]))
-                       tprintf("0");
+               printflags(wait4_options, tcp->u_arg[3], "W???");
+               if (tcp->u_nargs > 4) {
+                       /* usage */
+                       tprintf(", ");
+                       if (!tcp->u_arg[4])
+                               tprintf("NULL");
+                       else if (tcp->u_error)
+                               tprintf("%#lx", tcp->u_arg[4]);
+                       else
+                               printrusage(tcp, tcp->u_arg[4]);
+               }
        }
        return 0;
 }
 
-#endif /* SVR4 */
+#endif /* SVR4 or LINUX */
 
 int
 sys_alarm(tcp)
@@ -1298,7 +2185,8 @@ struct tcb *tcp;
 
 #ifndef SVR4
 
-static struct xlat ptrace_cmds[] = {
+static const struct xlat ptrace_cmds[] = {
+#ifndef FREEBSD
        { PTRACE_TRACEME,       "PTRACE_TRACEME"        },
        { PTRACE_PEEKTEXT,      "PTRACE_PEEKTEXT",      },
        { PTRACE_PEEKDATA,      "PTRACE_PEEKDATA",      },
@@ -1311,11 +2199,31 @@ static struct xlat ptrace_cmds[] = {
        { PTRACE_SINGLESTEP,    "PTRACE_SINGLESTEP"     },
        { PTRACE_ATTACH,        "PTRACE_ATTACH"         },
        { PTRACE_DETACH,        "PTRACE_DETACH"         },
-#ifdef SUNOS4
+#ifdef PTRACE_GETREGS
        { PTRACE_GETREGS,       "PTRACE_GETREGS"        },
+#endif
+#ifdef PTRACE_SETREGS
        { PTRACE_SETREGS,       "PTRACE_SETREGS"        },
+#endif
+#ifdef PTRACE_GETFPREGS
        { PTRACE_GETFPREGS,     "PTRACE_GETFPREGS",     },
+#endif
+#ifdef PTRACE_SETFPREGS
        { PTRACE_SETFPREGS,     "PTRACE_SETFPREGS",     },
+#endif
+#ifdef PTRACE_GETFPXREGS
+       { PTRACE_GETFPXREGS,    "PTRACE_GETFPXREGS",    },
+#endif
+#ifdef PTRACE_SETFPXREGS
+       { PTRACE_SETFPXREGS,    "PTRACE_SETFPXREGS",    },
+#endif
+#ifdef PTRACE_GETVRREGS
+       { PTRACE_GETVRREGS,     "PTRACE_GETVRREGS",     },
+#endif
+#ifdef PTRACE_SETVRREGS
+       { PTRACE_SETVRREGS,     "PTRACE_SETVRREGS",     },
+#endif
+#ifdef SUNOS4
        { PTRACE_READDATA,      "PTRACE_READDATA"       },
        { PTRACE_WRITEDATA,     "PTRACE_WRITEDATA"      },
        { PTRACE_READTEXT,      "PTRACE_READTEXT"       },
@@ -1344,125 +2252,321 @@ static struct xlat ptrace_cmds[] = {
 #endif /* !I386 */
        { PTRACE_GETUCODE,      "PTRACE_GETUCODE"       },
 #endif /* SUNOS4 */
+#else /* FREEBSD */
+       { PT_TRACE_ME,          "PT_TRACE_ME"           },
+       { PT_READ_I,            "PT_READ_I"             },
+       { PT_READ_D,            "PT_READ_D"             },
+       { PT_WRITE_I,           "PT_WRITE_I"            },
+       { PT_WRITE_D,           "PT_WRITE_D"            },
+#ifdef PT_READ_U
+       { PT_READ_U,            "PT_READ_U"             },
+#endif
+       { PT_CONTINUE,          "PT_CONTINUE"           },
+       { PT_KILL,              "PT_KILL"               },
+       { PT_STEP,              "PT_STEP"               },
+       { PT_ATTACH,            "PT_ATTACH"             },
+       { PT_DETACH,            "PT_DETACH"             },
+       { PT_GETREGS,           "PT_GETREGS"            },
+       { PT_SETREGS,           "PT_SETREGS"            },
+       { PT_GETFPREGS,         "PT_GETFPREGS"          },
+       { PT_SETFPREGS,         "PT_SETFPREGS"          },
+       { PT_GETDBREGS,         "PT_GETDBREGS"          },
+       { PT_SETDBREGS,         "PT_SETDBREGS"          },
+#endif /* FREEBSD */
        { 0,                    NULL                    },
 };
 
+#ifndef FREEBSD
 #ifndef SUNOS4_KERNEL_ARCH_KLUDGE
 static
 #endif /* !SUNOS4_KERNEL_ARCH_KLUDGE */
-struct xlat struct_user_offsets[] = {
+const struct xlat struct_user_offsets[] = {
 #ifdef LINUX
-#ifdef SPARC
+#if defined(S390) || defined(S390X)
+       { PT_PSWMASK,           "psw_mask"                              },
+       { PT_PSWADDR,           "psw_addr"                              },
+       { PT_GPR0,              "gpr0"                                  },
+       { PT_GPR1,              "gpr1"                                  },
+       { PT_GPR2,              "gpr2"                                  },
+       { PT_GPR3,              "gpr3"                                  },
+       { PT_GPR4,              "gpr4"                                  },
+       { PT_GPR5,              "gpr5"                                  },
+       { PT_GPR6,              "gpr6"                                  },
+       { PT_GPR7,              "gpr7"                                  },
+       { PT_GPR8,              "gpr8"                                  },
+       { PT_GPR9,              "gpr9"                                  },
+       { PT_GPR10,             "gpr10"                                 },
+       { PT_GPR11,             "gpr11"                                 },
+       { PT_GPR12,             "gpr12"                                 },
+       { PT_GPR13,             "gpr13"                                 },
+       { PT_GPR14,             "gpr14"                                 },
+       { PT_GPR15,             "gpr15"                                 },
+       { PT_ACR0,              "acr0"                                  },
+       { PT_ACR1,              "acr1"                                  },
+       { PT_ACR2,              "acr2"                                  },
+       { PT_ACR3,              "acr3"                                  },
+       { PT_ACR4,              "acr4"                                  },
+       { PT_ACR5,              "acr5"                                  },
+       { PT_ACR6,              "acr6"                                  },
+       { PT_ACR7,              "acr7"                                  },
+       { PT_ACR8,              "acr8"                                  },
+       { PT_ACR9,              "acr9"                                  },
+       { PT_ACR10,             "acr10"                                 },
+       { PT_ACR11,             "acr11"                                 },
+       { PT_ACR12,             "acr12"                                 },
+       { PT_ACR13,             "acr13"                                 },
+       { PT_ACR14,             "acr14"                                 },
+       { PT_ACR15,             "acr15"                                 },
+       { PT_ORIGGPR2,          "orig_gpr2"                             },
+       { PT_FPC,               "fpc"                                   },
+#if defined(S390)
+       { PT_FPR0_HI,           "fpr0.hi"                               },
+       { PT_FPR0_LO,           "fpr0.lo"                               },
+       { PT_FPR1_HI,           "fpr1.hi"                               },
+       { PT_FPR1_LO,           "fpr1.lo"                               },
+       { PT_FPR2_HI,           "fpr2.hi"                               },
+       { PT_FPR2_LO,           "fpr2.lo"                               },
+       { PT_FPR3_HI,           "fpr3.hi"                               },
+       { PT_FPR3_LO,           "fpr3.lo"                               },
+       { PT_FPR4_HI,           "fpr4.hi"                               },
+       { PT_FPR4_LO,           "fpr4.lo"                               },
+       { PT_FPR5_HI,           "fpr5.hi"                               },
+       { PT_FPR5_LO,           "fpr5.lo"                               },
+       { PT_FPR6_HI,           "fpr6.hi"                               },
+       { PT_FPR6_LO,           "fpr6.lo"                               },
+       { PT_FPR7_HI,           "fpr7.hi"                               },
+       { PT_FPR7_LO,           "fpr7.lo"                               },
+       { PT_FPR8_HI,           "fpr8.hi"                               },
+       { PT_FPR8_LO,           "fpr8.lo"                               },
+       { PT_FPR9_HI,           "fpr9.hi"                               },
+       { PT_FPR9_LO,           "fpr9.lo"                               },
+       { PT_FPR10_HI,          "fpr10.hi"                              },
+       { PT_FPR10_LO,          "fpr10.lo"                              },
+       { PT_FPR11_HI,          "fpr11.hi"                              },
+       { PT_FPR11_LO,          "fpr11.lo"                              },
+       { PT_FPR12_HI,          "fpr12.hi"                              },
+       { PT_FPR12_LO,          "fpr12.lo"                              },
+       { PT_FPR13_HI,          "fpr13.hi"                              },
+       { PT_FPR13_LO,          "fpr13.lo"                              },
+       { PT_FPR14_HI,          "fpr14.hi"                              },
+       { PT_FPR14_LO,          "fpr14.lo"                              },
+       { PT_FPR15_HI,          "fpr15.hi"                              },
+       { PT_FPR15_LO,          "fpr15.lo"                              },
+#endif
+#if defined(S390X)
+       { PT_FPR0,              "fpr0"                                  },
+       { PT_FPR1,              "fpr1"                                  },
+       { PT_FPR2,              "fpr2"                                  },
+       { PT_FPR3,              "fpr3"                                  },
+       { PT_FPR4,              "fpr4"                                  },
+       { PT_FPR5,              "fpr5"                                  },
+       { PT_FPR6,              "fpr6"                                  },
+       { PT_FPR7,              "fpr7"                                  },
+       { PT_FPR8,              "fpr8"                                  },
+       { PT_FPR9,              "fpr9"                                  },
+       { PT_FPR10,             "fpr10"                                 },
+       { PT_FPR11,             "fpr11"                                 },
+       { PT_FPR12,             "fpr12"                                 },
+       { PT_FPR13,             "fpr13"                                 },
+       { PT_FPR14,             "fpr14"                                 },
+       { PT_FPR15,             "fpr15"                                 },
+#endif
+       { PT_CR_9,              "cr9"                                   },
+       { PT_CR_10,             "cr10"                                  },
+       { PT_CR_11,             "cr11"                                  },
+       { PT_IEEE_IP,           "ieee_exception_ip"                     },
+#endif
+#if defined(SPARC)
+       /* XXX No support for these offsets yet. */
+#elif defined(HPPA)
        /* XXX No support for these offsets yet. */
 #elif defined(POWERPC)
-       { 4*PT_R0,              "4*PT_R0"       },
-       { 4*PT_R1,              "4*PT_R1"       },
-       { 4*PT_R2,              "4*PT_R2"       },
-       { 4*PT_R3,              "4*PT_R3"       },
-       { 4*PT_R4,              "4*PT_R4"       },
-       { 4*PT_R5,              "4*PT_R5"       },
-       { 4*PT_R6,              "4*PT_R6"       },
-       { 4*PT_R7,              "4*PT_R7"       },
-       { 4*PT_R8,              "4*PT_R8"       },
-       { 4*PT_R9,              "4*PT_R9"       },
-       { 4*PT_R10,             "4*PT_R10"      },
-       { 4*PT_R11,             "4*PT_R11"      },
-       { 4*PT_R12,             "4*PT_R12"      },
-       { 4*PT_R13,             "4*PT_R13"      },
-       { 4*PT_R14,             "4*PT_R14"      },
-       { 4*PT_R15,             "4*PT_R15"      },
-       { 4*PT_R16,             "4*PT_R16"      },
-       { 4*PT_R17,             "4*PT_R17"      },
-       { 4*PT_R18,             "4*PT_R18"      },
-       { 4*PT_R19,             "4*PT_R19"      },
-       { 4*PT_R20,             "4*PT_R20"      },
-       { 4*PT_R21,             "4*PT_R21"      },
-       { 4*PT_R22,             "4*PT_R22"      },
-       { 4*PT_R23,             "4*PT_R23"      },
-       { 4*PT_R24,             "4*PT_R24"      },
-       { 4*PT_R25,             "4*PT_R25"      },
-       { 4*PT_R26,             "4*PT_R26"      },
-       { 4*PT_R27,             "4*PT_R27"      },
-       { 4*PT_R28,             "4*PT_R28"      },
-       { 4*PT_R29,             "4*PT_R29"      },
-       { 4*PT_R30,             "4*PT_R30"      },
-       { 4*PT_R31,             "4*PT_R31"      },
-       { 4*PT_NIP,             "4*PT_NIP"      },
-       { 4*PT_MSR,             "4*PT_MSR"      },
-       { 4*PT_ORIG_R3,  "4*PT_ORIG_R3" },
-       { 4*PT_CTR,             "4*PT_CTR"      },
-       { 4*PT_LNK,             "4*PT_LNK"      },
-       { 4*PT_XER,             "4*PT_XER"      },
-       { 4*PT_CCR,             "4*PT_CCR"      },
-       { 4*PT_FPR0,    "4*PT_FPR0"     },
-#else  
+#ifndef PT_ORIG_R3
+#define PT_ORIG_R3 34
+#endif
+#define REGSIZE (sizeof(unsigned long))
+       { REGSIZE*PT_R0,                "r0"                            },
+       { REGSIZE*PT_R1,                "r1"                            },
+       { REGSIZE*PT_R2,                "r2"                            },
+       { REGSIZE*PT_R3,                "r3"                            },
+       { REGSIZE*PT_R4,                "r4"                            },
+       { REGSIZE*PT_R5,                "r5"                            },
+       { REGSIZE*PT_R6,                "r6"                            },
+       { REGSIZE*PT_R7,                "r7"                            },
+       { REGSIZE*PT_R8,                "r8"                            },
+       { REGSIZE*PT_R9,                "r9"                            },
+       { REGSIZE*PT_R10,               "r10"                           },
+       { REGSIZE*PT_R11,               "r11"                           },
+       { REGSIZE*PT_R12,               "r12"                           },
+       { REGSIZE*PT_R13,               "r13"                           },
+       { REGSIZE*PT_R14,               "r14"                           },
+       { REGSIZE*PT_R15,               "r15"                           },
+       { REGSIZE*PT_R16,               "r16"                           },
+       { REGSIZE*PT_R17,               "r17"                           },
+       { REGSIZE*PT_R18,               "r18"                           },
+       { REGSIZE*PT_R19,               "r19"                           },
+       { REGSIZE*PT_R20,               "r20"                           },
+       { REGSIZE*PT_R21,               "r21"                           },
+       { REGSIZE*PT_R22,               "r22"                           },
+       { REGSIZE*PT_R23,               "r23"                           },
+       { REGSIZE*PT_R24,               "r24"                           },
+       { REGSIZE*PT_R25,               "r25"                           },
+       { REGSIZE*PT_R26,               "r26"                           },
+       { REGSIZE*PT_R27,               "r27"                           },
+       { REGSIZE*PT_R28,               "r28"                           },
+       { REGSIZE*PT_R29,               "r29"                           },
+       { REGSIZE*PT_R30,               "r30"                           },
+       { REGSIZE*PT_R31,               "r31"                           },
+       { REGSIZE*PT_NIP,               "NIP"                           },
+       { REGSIZE*PT_MSR,               "MSR"                           },
+       { REGSIZE*PT_ORIG_R3,           "ORIG_R3"                       },
+       { REGSIZE*PT_CTR,               "CTR"                           },
+       { REGSIZE*PT_LNK,               "LNK"                           },
+       { REGSIZE*PT_XER,               "XER"                           },
+       { REGSIZE*PT_CCR,               "CCR"                           },
+       { REGSIZE*PT_FPR0,              "FPR0"                          },
+#undef REGSIZE
+#else
 #ifdef ALPHA
-       { 0,            "r0"                                    },
-       { 1,            "r1"                                    },
-       { 2,            "r2"                                    },
-       { 3,            "r3"                                    },
-       { 4,            "r4"                                    },
-       { 5,            "r5"                                    },
-       { 6,            "r6"                                    },
-       { 7,            "r7"                                    },
-       { 8,            "r8"                                    },
-       { 9,            "r9"                                    },
-       { 10,           "r10"                                   },
-       { 11,           "r11"                                   },
-       { 12,           "r12"                                   },
-       { 13,           "r13"                                   },
-       { 14,           "r14"                                   },
-       { 15,           "r15"                                   },
-       { 16,           "r16"                                   },
-       { 17,           "r17"                                   },
-       { 18,           "r18"                                   },
-       { 19,           "r19"                                   },
-       { 20,           "r20"                                   },
-       { 21,           "r21"                                   },
-       { 22,           "r22"                                   },
-       { 23,           "r23"                                   },
-       { 24,           "r24"                                   },
-       { 25,           "r25"                                   },
-       { 26,           "r26"                                   },
-       { 27,           "r27"                                   },
-       { 28,           "r28"                                   },
-       { 29,           "gp"                                    },
-       { 30,           "fp"                                    },
-       { 31,           "zero"                                  },
-       { 32,           "fp0"                                   },
-       { 33,           "fp"                                    },
-       { 34,           "fp2"                                   },
-       { 35,           "fp3"                                   },
-       { 36,           "fp4"                                   },
-       { 37,           "fp5"                                   },
-       { 38,           "fp6"                                   },
-       { 39,           "fp7"                                   },
-       { 40,           "fp8"                                   },
-       { 41,           "fp9"                                   },
-       { 42,           "fp10"                                  },
-       { 43,           "fp11"                                  },
-       { 44,           "fp12"                                  },
-       { 45,           "fp13"                                  },
-       { 46,           "fp14"                                  },
-       { 47,           "fp15"                                  },
-       { 48,           "fp16"                                  },
-       { 49,           "fp17"                                  },
-       { 50,           "fp18"                                  },
-       { 51,           "fp19"                                  },
-       { 52,           "fp20"                                  },
-       { 53,           "fp21"                                  },
-       { 54,           "fp22"                                  },
-       { 55,           "fp23"                                  },
-       { 56,           "fp24"                                  },
-       { 57,           "fp25"                                  },
-       { 58,           "fp26"                                  },
-       { 59,           "fp27"                                  },
-       { 60,           "fp28"                                  },
-       { 61,           "fp29"                                  },
-       { 62,           "fp30"                                  },
-       { 63,           "fp31"                                  },
-       { 64,           "pc"                                    },
+       { 0,                    "r0"                                    },
+       { 1,                    "r1"                                    },
+       { 2,                    "r2"                                    },
+       { 3,                    "r3"                                    },
+       { 4,                    "r4"                                    },
+       { 5,                    "r5"                                    },
+       { 6,                    "r6"                                    },
+       { 7,                    "r7"                                    },
+       { 8,                    "r8"                                    },
+       { 9,                    "r9"                                    },
+       { 10,                   "r10"                                   },
+       { 11,                   "r11"                                   },
+       { 12,                   "r12"                                   },
+       { 13,                   "r13"                                   },
+       { 14,                   "r14"                                   },
+       { 15,                   "r15"                                   },
+       { 16,                   "r16"                                   },
+       { 17,                   "r17"                                   },
+       { 18,                   "r18"                                   },
+       { 19,                   "r19"                                   },
+       { 20,                   "r20"                                   },
+       { 21,                   "r21"                                   },
+       { 22,                   "r22"                                   },
+       { 23,                   "r23"                                   },
+       { 24,                   "r24"                                   },
+       { 25,                   "r25"                                   },
+       { 26,                   "r26"                                   },
+       { 27,                   "r27"                                   },
+       { 28,                   "r28"                                   },
+       { 29,                   "gp"                                    },
+       { 30,                   "fp"                                    },
+       { 31,                   "zero"                                  },
+       { 32,                   "fp0"                                   },
+       { 33,                   "fp"                                    },
+       { 34,                   "fp2"                                   },
+       { 35,                   "fp3"                                   },
+       { 36,                   "fp4"                                   },
+       { 37,                   "fp5"                                   },
+       { 38,                   "fp6"                                   },
+       { 39,                   "fp7"                                   },
+       { 40,                   "fp8"                                   },
+       { 41,                   "fp9"                                   },
+       { 42,                   "fp10"                                  },
+       { 43,                   "fp11"                                  },
+       { 44,                   "fp12"                                  },
+       { 45,                   "fp13"                                  },
+       { 46,                   "fp14"                                  },
+       { 47,                   "fp15"                                  },
+       { 48,                   "fp16"                                  },
+       { 49,                   "fp17"                                  },
+       { 50,                   "fp18"                                  },
+       { 51,                   "fp19"                                  },
+       { 52,                   "fp20"                                  },
+       { 53,                   "fp21"                                  },
+       { 54,                   "fp22"                                  },
+       { 55,                   "fp23"                                  },
+       { 56,                   "fp24"                                  },
+       { 57,                   "fp25"                                  },
+       { 58,                   "fp26"                                  },
+       { 59,                   "fp27"                                  },
+       { 60,                   "fp28"                                  },
+       { 61,                   "fp29"                                  },
+       { 62,                   "fp30"                                  },
+       { 63,                   "fp31"                                  },
+       { 64,                   "pc"                                    },
 #else /* !ALPHA */
+#ifdef IA64
+       { PT_F32, "f32" }, { PT_F33, "f33" }, { PT_F34, "f34" },
+       { PT_F35, "f35" }, { PT_F36, "f36" }, { PT_F37, "f37" },
+       { PT_F38, "f38" }, { PT_F39, "f39" }, { PT_F40, "f40" },
+       { PT_F41, "f41" }, { PT_F42, "f42" }, { PT_F43, "f43" },
+       { PT_F44, "f44" }, { PT_F45, "f45" }, { PT_F46, "f46" },
+       { PT_F47, "f47" }, { PT_F48, "f48" }, { PT_F49, "f49" },
+       { PT_F50, "f50" }, { PT_F51, "f51" }, { PT_F52, "f52" },
+       { PT_F53, "f53" }, { PT_F54, "f54" }, { PT_F55, "f55" },
+       { PT_F56, "f56" }, { PT_F57, "f57" }, { PT_F58, "f58" },
+       { PT_F59, "f59" }, { PT_F60, "f60" }, { PT_F61, "f61" },
+       { PT_F62, "f62" }, { PT_F63, "f63" }, { PT_F64, "f64" },
+       { PT_F65, "f65" }, { PT_F66, "f66" }, { PT_F67, "f67" },
+       { PT_F68, "f68" }, { PT_F69, "f69" }, { PT_F70, "f70" },
+       { PT_F71, "f71" }, { PT_F72, "f72" }, { PT_F73, "f73" },
+       { PT_F74, "f74" }, { PT_F75, "f75" }, { PT_F76, "f76" },
+       { PT_F77, "f77" }, { PT_F78, "f78" }, { PT_F79, "f79" },
+       { PT_F80, "f80" }, { PT_F81, "f81" }, { PT_F82, "f82" },
+       { PT_F83, "f83" }, { PT_F84, "f84" }, { PT_F85, "f85" },
+       { PT_F86, "f86" }, { PT_F87, "f87" }, { PT_F88, "f88" },
+       { PT_F89, "f89" }, { PT_F90, "f90" }, { PT_F91, "f91" },
+       { PT_F92, "f92" }, { PT_F93, "f93" }, { PT_F94, "f94" },
+       { PT_F95, "f95" }, { PT_F96, "f96" }, { PT_F97, "f97" },
+       { PT_F98, "f98" }, { PT_F99, "f99" }, { PT_F100, "f100" },
+       { PT_F101, "f101" }, { PT_F102, "f102" }, { PT_F103, "f103" },
+       { PT_F104, "f104" }, { PT_F105, "f105" }, { PT_F106, "f106" },
+       { PT_F107, "f107" }, { PT_F108, "f108" }, { PT_F109, "f109" },
+       { PT_F110, "f110" }, { PT_F111, "f111" }, { PT_F112, "f112" },
+       { PT_F113, "f113" }, { PT_F114, "f114" }, { PT_F115, "f115" },
+       { PT_F116, "f116" }, { PT_F117, "f117" }, { PT_F118, "f118" },
+       { PT_F119, "f119" }, { PT_F120, "f120" }, { PT_F121, "f121" },
+       { PT_F122, "f122" }, { PT_F123, "f123" }, { PT_F124, "f124" },
+       { PT_F125, "f125" }, { PT_F126, "f126" }, { PT_F127, "f127" },
+       /* switch stack: */
+       { PT_F2, "f2" }, { PT_F3, "f3" }, { PT_F4, "f4" },
+       { PT_F5, "f5" }, { PT_F10, "f10" }, { PT_F11, "f11" },
+       { PT_F12, "f12" }, { PT_F13, "f13" }, { PT_F14, "f14" },
+       { PT_F15, "f15" }, { PT_F16, "f16" }, { PT_F17, "f17" },
+       { PT_F18, "f18" }, { PT_F19, "f19" }, { PT_F20, "f20" },
+       { PT_F21, "f21" }, { PT_F22, "f22" }, { PT_F23, "f23" },
+       { PT_F24, "f24" }, { PT_F25, "f25" }, { PT_F26, "f26" },
+       { PT_F27, "f27" }, { PT_F28, "f28" }, { PT_F29, "f29" },
+       { PT_F30, "f30" }, { PT_F31, "f31" }, { PT_R4, "r4" },
+       { PT_R5, "r5" }, { PT_R6, "r6" }, { PT_R7, "r7" },
+       { PT_B1, "b1" }, { PT_B2, "b2" }, { PT_B3, "b3" },
+       { PT_B4, "b4" }, { PT_B5, "b5" },
+       { PT_AR_EC, "ar.ec" }, { PT_AR_LC, "ar.lc" },
+       /* pt_regs */
+       { PT_CR_IPSR, "psr" }, { PT_CR_IIP, "ip" },
+       { PT_CFM, "cfm" }, { PT_AR_UNAT, "ar.unat" },
+       { PT_AR_PFS, "ar.pfs" }, { PT_AR_RSC, "ar.rsc" },
+       { PT_AR_RNAT, "ar.rnat" }, { PT_AR_BSPSTORE, "ar.bspstore" },
+       { PT_PR, "pr" }, { PT_B6, "b6" }, { PT_AR_BSP, "ar.bsp" },
+       { PT_R1, "r1" }, { PT_R2, "r2" }, { PT_R3, "r3" },
+       { PT_R12, "r12" }, { PT_R13, "r13" }, { PT_R14, "r14" },
+       { PT_R15, "r15" }, { PT_R8, "r8" }, { PT_R9, "r9" },
+       { PT_R10, "r10" }, { PT_R11, "r11" }, { PT_R16, "r16" },
+       { PT_R17, "r17" }, { PT_R18, "r18" }, { PT_R19, "r19" },
+       { PT_R20, "r20" }, { PT_R21, "r21" }, { PT_R22, "r22" },
+       { PT_R23, "r23" }, { PT_R24, "r24" }, { PT_R25, "r25" },
+       { PT_R26, "r26" }, { PT_R27, "r27" }, { PT_R28, "r28" },
+       { PT_R29, "r29" }, { PT_R30, "r30" }, { PT_R31, "r31" },
+       { PT_AR_CCV, "ar.ccv" }, { PT_AR_FPSR, "ar.fpsr" },
+       { PT_B0, "b0" }, { PT_B7, "b7" }, { PT_F6, "f6" },
+       { PT_F7, "f7" }, { PT_F8, "f8" }, { PT_F9, "f9" },
+# ifdef PT_AR_CSD
+       { PT_AR_CSD, "ar.csd" },
+# endif
+# ifdef PT_AR_SSD
+       { PT_AR_SSD, "ar.ssd" },
+# endif
+       { PT_DBR, "dbr" }, { PT_IBR, "ibr" }, { PT_PMD, "pmd" },
+#else /* !IA64 */
 #ifdef I386
        { 4*EBX,                "4*EBX"                                 },
        { 4*ECX,                "4*ECX"                                 },
@@ -1482,6 +2586,35 @@ struct xlat struct_user_offsets[] = {
        { 4*UESP,               "4*UESP"                                },
        { 4*SS,                 "4*SS"                                  },
 #else /* !I386 */
+#ifdef X86_64
+       { 8*RDI,                "8*RDI"                                 },
+       { 8*RSI,                "8*RSI"                                 },
+       { 8*RDX,                "8*RDX"                                 },
+       { 8*R10,                "8*R10" },
+       { 8*R8,                 "8*R8" },
+       { 8*R9,                 "8*R9" },
+       { 8*RBX,                "8*RBX"                                 },
+       { 8*RCX,                "8*RCX"                                 },
+       { 8*RBP,                "8*RBP"                                 },
+       { 8*RAX,                "8*RAX"                                 },
+#if 0
+       { 8*DS,                 "8*DS"                                  },
+       { 8*ES,                 "8*ES"                                  },
+       { 8*FS,                 "8*FS"                                  },
+       { 8*GS,                 "8*GS"                                  },
+#endif
+       { 8*ORIG_RAX,           "8*ORIG_EAX"                            },
+       { 8*RIP,                "8*RIP"                                 },
+       { 8*CS,                 "8*CS"                                  },
+       { 8*EFLAGS,             "8*EFL"                                 },
+       { 8*RSP,                "8*RSP"                         },
+       { 8*SS,                 "8*SS"                                  },
+       { 8*R11,                "8*R11" },
+       { 8*R12,                "8*R12" },
+       { 8*R13,                "8*R13" },
+       { 8*R14,                "8*R14" },
+       { 8*R15,                "8*R15" },
+#endif
 #ifdef M68K
        { 4*PT_D1,              "4*PT_D1"                               },
        { 4*PT_D2,              "4*PT_D2"                               },
@@ -1504,8 +2637,237 @@ struct xlat struct_user_offsets[] = {
        { 4*PT_PC,              "4*PT_PC"                               },
 #endif /* M68K */
 #endif /* !I386 */
+#ifdef SH
+       { 4*REG_REG0,           "4*REG_REG0"                            },
+       { 4*(REG_REG0+1),       "4*REG_REG1"                            },
+       { 4*(REG_REG0+2),       "4*REG_REG2"                            },
+       { 4*(REG_REG0+3),       "4*REG_REG3"                            },
+       { 4*(REG_REG0+4),       "4*REG_REG4"                            },
+       { 4*(REG_REG0+5),       "4*REG_REG5"                            },
+       { 4*(REG_REG0+6),       "4*REG_REG6"                            },
+       { 4*(REG_REG0+7),       "4*REG_REG7"                            },
+       { 4*(REG_REG0+8),       "4*REG_REG8"                            },
+       { 4*(REG_REG0+9),       "4*REG_REG9"                            },
+       { 4*(REG_REG0+10),      "4*REG_REG10"                           },
+       { 4*(REG_REG0+11),      "4*REG_REG11"                           },
+       { 4*(REG_REG0+12),      "4*REG_REG12"                           },
+       { 4*(REG_REG0+13),      "4*REG_REG13"                           },
+       { 4*(REG_REG0+14),      "4*REG_REG14"                           },
+       { 4*REG_REG15,          "4*REG_REG15"                           },
+       { 4*REG_PC,             "4*REG_PC"                              },
+       { 4*REG_PR,             "4*REG_PR"                              },
+       { 4*REG_SR,             "4*REG_SR"                              },
+       { 4*REG_GBR,            "4*REG_GBR"                             },
+       { 4*REG_MACH,           "4*REG_MACH"                            },
+       { 4*REG_MACL,           "4*REG_MACL"                            },
+       { 4*REG_SYSCALL,        "4*REG_SYSCALL"                         },
+       { 4*REG_FPUL,           "4*REG_FPUL"                            },
+       { 4*REG_FPREG0,         "4*REG_FPREG0"                          },
+       { 4*(REG_FPREG0+1),     "4*REG_FPREG1"                          },
+       { 4*(REG_FPREG0+2),     "4*REG_FPREG2"                          },
+       { 4*(REG_FPREG0+3),     "4*REG_FPREG3"                          },
+       { 4*(REG_FPREG0+4),     "4*REG_FPREG4"                          },
+       { 4*(REG_FPREG0+5),     "4*REG_FPREG5"                          },
+       { 4*(REG_FPREG0+6),     "4*REG_FPREG6"                          },
+       { 4*(REG_FPREG0+7),     "4*REG_FPREG7"                          },
+       { 4*(REG_FPREG0+8),     "4*REG_FPREG8"                          },
+       { 4*(REG_FPREG0+9),     "4*REG_FPREG9"                          },
+       { 4*(REG_FPREG0+10),    "4*REG_FPREG10"                         },
+       { 4*(REG_FPREG0+11),    "4*REG_FPREG11"                         },
+       { 4*(REG_FPREG0+12),    "4*REG_FPREG12"                         },
+       { 4*(REG_FPREG0+13),    "4*REG_FPREG13"                         },
+       { 4*(REG_FPREG0+14),    "4*REG_FPREG14"                         },
+       { 4*REG_FPREG15,        "4*REG_FPREG15"                         },
+#ifdef REG_XDREG0
+       { 4*REG_XDREG0,         "4*REG_XDREG0"                          },
+       { 4*(REG_XDREG0+2),     "4*REG_XDREG2"                          },
+       { 4*(REG_XDREG0+4),     "4*REG_XDREG4"                          },
+       { 4*(REG_XDREG0+6),     "4*REG_XDREG6"                          },
+       { 4*(REG_XDREG0+8),     "4*REG_XDREG8"                          },
+       { 4*(REG_XDREG0+10),    "4*REG_XDREG10"                         },
+       { 4*(REG_XDREG0+12),    "4*REG_XDREG12"                         },
+       { 4*REG_XDREG14,        "4*REG_XDREG14"                         },
+#endif
+       { 4*REG_FPSCR,          "4*REG_FPSCR"                           },
+#endif /* SH */
+#ifdef SH64
+       { 0,                    "PC(L)"                                 },
+       { 4,                    "PC(U)"                                 },
+       { 8,                    "SR(L)"                                 },
+       { 12,                   "SR(U)"                                 },
+       { 16,                   "syscall no.(L)"                        },
+       { 20,                   "syscall_no.(U)"                        },
+       { 24,                   "R0(L)"                                 },
+       { 28,                   "R0(U)"                                 },
+       { 32,                   "R1(L)"                                 },
+       { 36,                   "R1(U)"                                 },
+       { 40,                   "R2(L)"                                 },
+       { 44,                   "R2(U)"                                 },
+       { 48,                   "R3(L)"                                 },
+       { 52,                   "R3(U)"                                 },
+       { 56,                   "R4(L)"                                 },
+       { 60,                   "R4(U)"                                 },
+       { 64,                   "R5(L)"                                 },
+       { 68,                   "R5(U)"                                 },
+       { 72,                   "R6(L)"                                 },
+       { 76,                   "R6(U)"                                 },
+       { 80,                   "R7(L)"                                 },
+       { 84,                   "R7(U)"                                 },
+       { 88,                   "R8(L)"                                 },
+       { 92,                   "R8(U)"                                 },
+       { 96,                   "R9(L)"                                 },
+       { 100,                  "R9(U)"                                 },
+       { 104,                  "R10(L)"                                },
+       { 108,                  "R10(U)"                                },
+       { 112,                  "R11(L)"                                },
+       { 116,                  "R11(U)"                                },
+       { 120,                  "R12(L)"                                },
+       { 124,                  "R12(U)"                                },
+       { 128,                  "R13(L)"                                },
+       { 132,                  "R13(U)"                                },
+       { 136,                  "R14(L)"                                },
+       { 140,                  "R14(U)"                                },
+       { 144,                  "R15(L)"                                },
+       { 148,                  "R15(U)"                                },
+       { 152,                  "R16(L)"                                },
+       { 156,                  "R16(U)"                                },
+       { 160,                  "R17(L)"                                },
+       { 164,                  "R17(U)"                                },
+       { 168,                  "R18(L)"                                },
+       { 172,                  "R18(U)"                                },
+       { 176,                  "R19(L)"                                },
+       { 180,                  "R19(U)"                                },
+       { 184,                  "R20(L)"                                },
+       { 188,                  "R20(U)"                                },
+       { 192,                  "R21(L)"                                },
+       { 196,                  "R21(U)"                                },
+       { 200,                  "R22(L)"                                },
+       { 204,                  "R22(U)"                                },
+       { 208,                  "R23(L)"                                },
+       { 212,                  "R23(U)"                                },
+       { 216,                  "R24(L)"                                },
+       { 220,                  "R24(U)"                                },
+       { 224,                  "R25(L)"                                },
+       { 228,                  "R25(U)"                                },
+       { 232,                  "R26(L)"                                },
+       { 236,                  "R26(U)"                                },
+       { 240,                  "R27(L)"                                },
+       { 244,                  "R27(U)"                                },
+       { 248,                  "R28(L)"                                },
+       { 252,                  "R28(U)"                                },
+       { 256,                  "R29(L)"                                },
+       { 260,                  "R29(U)"                                },
+       { 264,                  "R30(L)"                                },
+       { 268,                  "R30(U)"                                },
+       { 272,                  "R31(L)"                                },
+       { 276,                  "R31(U)"                                },
+       { 280,                  "R32(L)"                                },
+       { 284,                  "R32(U)"                                },
+       { 288,                  "R33(L)"                                },
+       { 292,                  "R33(U)"                                },
+       { 296,                  "R34(L)"                                },
+       { 300,                  "R34(U)"                                },
+       { 304,                  "R35(L)"                                },
+       { 308,                  "R35(U)"                                },
+       { 312,                  "R36(L)"                                },
+       { 316,                  "R36(U)"                                },
+       { 320,                  "R37(L)"                                },
+       { 324,                  "R37(U)"                                },
+       { 328,                  "R38(L)"                                },
+       { 332,                  "R38(U)"                                },
+       { 336,                  "R39(L)"                                },
+       { 340,                  "R39(U)"                                },
+       { 344,                  "R40(L)"                                },
+       { 348,                  "R40(U)"                                },
+       { 352,                  "R41(L)"                                },
+       { 356,                  "R41(U)"                                },
+       { 360,                  "R42(L)"                                },
+       { 364,                  "R42(U)"                                },
+       { 368,                  "R43(L)"                                },
+       { 372,                  "R43(U)"                                },
+       { 376,                  "R44(L)"                                },
+       { 380,                  "R44(U)"                                },
+       { 384,                  "R45(L)"                                },
+       { 388,                  "R45(U)"                                },
+       { 392,                  "R46(L)"                                },
+       { 396,                  "R46(U)"                                },
+       { 400,                  "R47(L)"                                },
+       { 404,                  "R47(U)"                                },
+       { 408,                  "R48(L)"                                },
+       { 412,                  "R48(U)"                                },
+       { 416,                  "R49(L)"                                },
+       { 420,                  "R49(U)"                                },
+       { 424,                  "R50(L)"                                },
+       { 428,                  "R50(U)"                                },
+       { 432,                  "R51(L)"                                },
+       { 436,                  "R51(U)"                                },
+       { 440,                  "R52(L)"                                },
+       { 444,                  "R52(U)"                                },
+       { 448,                  "R53(L)"                                },
+       { 452,                  "R53(U)"                                },
+       { 456,                  "R54(L)"                                },
+       { 460,                  "R54(U)"                                },
+       { 464,                  "R55(L)"                                },
+       { 468,                  "R55(U)"                                },
+       { 472,                  "R56(L)"                                },
+       { 476,                  "R56(U)"                                },
+       { 480,                  "R57(L)"                                },
+       { 484,                  "R57(U)"                                },
+       { 488,                  "R58(L)"                                },
+       { 492,                  "R58(U)"                                },
+       { 496,                  "R59(L)"                                },
+       { 500,                  "R59(U)"                                },
+       { 504,                  "R60(L)"                                },
+       { 508,                  "R60(U)"                                },
+       { 512,                  "R61(L)"                                },
+       { 516,                  "R61(U)"                                },
+       { 520,                  "R62(L)"                                },
+       { 524,                  "R62(U)"                                },
+       { 528,                  "TR0(L)"                                },
+       { 532,                  "TR0(U)"                                },
+       { 536,                  "TR1(L)"                                },
+       { 540,                  "TR1(U)"                                },
+       { 544,                  "TR2(L)"                                },
+       { 548,                  "TR2(U)"                                },
+       { 552,                  "TR3(L)"                                },
+       { 556,                  "TR3(U)"                                },
+       { 560,                  "TR4(L)"                                },
+       { 564,                  "TR4(U)"                                },
+       { 568,                  "TR5(L)"                                },
+       { 572,                  "TR5(U)"                                },
+       { 576,                  "TR6(L)"                                },
+       { 580,                  "TR6(U)"                                },
+       { 584,                  "TR7(L)"                                },
+       { 588,                  "TR7(U)"                                },
+        /* This entry is in case pt_regs contains dregs (depends on
+           the kernel build options). */
+       { uoff(regs),           "offsetof(struct user, regs)"           },
+       { uoff(fpu),            "offsetof(struct user, fpu)"            },
+#endif
+#ifdef ARM
+       { uoff(regs.ARM_r0),    "r0"                                    },
+       { uoff(regs.ARM_r1),    "r1"                                    },
+       { uoff(regs.ARM_r2),    "r2"                                    },
+       { uoff(regs.ARM_r3),    "r3"                                    },
+       { uoff(regs.ARM_r4),    "r4"                                    },
+       { uoff(regs.ARM_r5),    "r5"                                    },
+       { uoff(regs.ARM_r6),    "r6"                                    },
+       { uoff(regs.ARM_r7),    "r7"                                    },
+       { uoff(regs.ARM_r8),    "r8"                                    },
+       { uoff(regs.ARM_r9),    "r9"                                    },
+       { uoff(regs.ARM_r10),   "r10"                                   },
+       { uoff(regs.ARM_fp),    "fp"                                    },
+       { uoff(regs.ARM_ip),    "ip"                                    },
+       { uoff(regs.ARM_sp),    "sp"                                    },
+       { uoff(regs.ARM_lr),    "lr"                                    },
+       { uoff(regs.ARM_pc),    "pc"                                    },
+       { uoff(regs.ARM_cpsr),  "cpsr"                                  },
+#endif
+
+#if !defined(S390) && !defined(S390X) && !defined(MIPS) && !defined(SPARC64)
        { uoff(u_fpvalid),      "offsetof(struct user, u_fpvalid)"      },
-#ifdef I386
+#endif
+#if  defined(I386) || defined(X86_64)
        { uoff(i387),           "offsetof(struct user, i387)"           },
 #else /* !I386 */
 #ifdef M68K
@@ -1515,19 +2877,31 @@ struct xlat struct_user_offsets[] = {
        { uoff(u_tsize),        "offsetof(struct user, u_tsize)"        },
        { uoff(u_dsize),        "offsetof(struct user, u_dsize)"        },
        { uoff(u_ssize),        "offsetof(struct user, u_ssize)"        },
+#if !defined(SPARC64)
        { uoff(start_code),     "offsetof(struct user, start_code)"     },
+#endif
+#ifdef SH64
+       { uoff(start_data),     "offsetof(struct user, start_data)"     },
+#endif
+#if !defined(SPARC64)
        { uoff(start_stack),    "offsetof(struct user, start_stack)"    },
+#endif
        { uoff(signal),         "offsetof(struct user, signal)"         },
+#if !defined(S390) && !defined(S390X) && !defined(MIPS) && !defined(SH) && !defined(SH64) && !defined(SPARC64)
        { uoff(reserved),       "offsetof(struct user, reserved)"       },
+#endif
+#if !defined(SPARC64)
        { uoff(u_ar0),          "offsetof(struct user, u_ar0)"          },
-#ifndef ARM
+#endif
+#if !defined(ARM) && !defined(MIPS) && !defined(S390) && !defined(S390X) && !defined(SPARC64)
        { uoff(u_fpstate),      "offsetof(struct user, u_fpstate)"      },
 #endif
        { uoff(magic),          "offsetof(struct user, magic)"          },
        { uoff(u_comm),         "offsetof(struct user, u_comm)"         },
-#ifdef I386
+#if defined(I386) || defined(X86_64)
        { uoff(u_debugreg),     "offsetof(struct user, u_debugreg)"     },
 #endif /* I386 */
+#endif /* !IA64 */
 #endif /* !ALPHA */
 #endif /* !POWERPC/!SPARC */
 #endif /* LINUX */
@@ -1578,24 +2952,31 @@ struct xlat struct_user_offsets[] = {
        { uoff(u_exdata.ux_shell[0]),"offsetof(struct user, u_exdata.ux_shell[0])"},
        { uoff(u_lofault),      "offsetof(struct user, u_lofault)"      },
 #endif /* SUNOS4 */
+#ifndef HPPA
        { sizeof(struct user),  "sizeof(struct user)"                   },
+#endif
        { 0,                    NULL                                    },
 };
+#endif
 
 int
 sys_ptrace(tcp)
 struct tcb *tcp;
 {
-       char *cmd;
-       struct xlat *x;
+       const struct xlat *x;
        long addr;
 
-       cmd = xlookup(ptrace_cmds, tcp->u_arg[0]);
-       if (!cmd)
-               cmd = "PTRACE_???";
        if (entering(tcp)) {
-               tprintf("%s, %lu, ", cmd, tcp->u_arg[1]);
+               printxval(ptrace_cmds, tcp->u_arg[0],
+#ifndef FREEBSD
+                         "PTRACE_???"
+#else
+                         "PT_???"
+#endif
+                       );
+               tprintf(", %lu, ", tcp->u_arg[1]);
                addr = tcp->u_arg[2];
+#ifndef FREEBSD
                if (tcp->u_arg[0] == PTRACE_PEEKUSER
                        || tcp->u_arg[0] == PTRACE_POKEUSER) {
                        for (x = struct_user_offsets; x->str; x++) {
@@ -1612,6 +2993,7 @@ struct tcb *tcp;
                                tprintf("%s, ", x->str);
                }
                else
+#endif
                        tprintf("%#lx, ", tcp->u_arg[2]);
 #ifdef LINUX
                switch (tcp->u_arg[0]) {
@@ -1634,7 +3016,7 @@ struct tcb *tcp;
                case PTRACE_PEEKDATA:
                case PTRACE_PEEKTEXT:
                case PTRACE_PEEKUSER:
-                       printnum(tcp, tcp->u_arg[3], "%#x");
+                       printnum(tcp, tcp->u_arg[3], "%#lx");
                        break;
                }
        }
@@ -1656,7 +3038,195 @@ struct tcb *tcp;
                }
        }
 #endif /* SUNOS4 */
+#ifdef FREEBSD
+               tprintf("%lu", tcp->u_arg[3]);
+       }
+#endif /* FREEBSD */
        return 0;
 }
 
 #endif /* !SVR4 */
+
+#ifdef LINUX
+static const struct xlat futexops[] = {
+       { FUTEX_WAIT,   "FUTEX_WAIT" },
+       { FUTEX_WAKE,   "FUTEX_WAKE" },
+       { FUTEX_FD,     "FUTEX_FD" },
+       { FUTEX_REQUEUE,"FUTEX_REQUEUE" },
+       { 0,            NULL }
+};
+
+int
+sys_futex(tcp)
+struct tcb *tcp;
+{
+    if (entering(tcp)) {
+       tprintf("%p, ", (void *) tcp->u_arg[0]);
+       printxval(futexops, tcp->u_arg[1], "FUTEX_???");
+       tprintf(", %ld", tcp->u_arg[2]);
+       if (tcp->u_arg[1] == FUTEX_WAIT) {
+               tprintf(", ");
+               printtv(tcp, tcp->u_arg[3]);
+       } else if (tcp->u_arg[1] == FUTEX_REQUEUE)
+               tprintf(", %ld, %p", tcp->u_arg[3], (void *) tcp->u_arg[4]);
+    }
+    return 0;
+}
+
+static void
+print_affinitylist(tcp, list, len)
+struct tcb *tcp;
+long list;
+unsigned int len;
+{
+    int first = 1;
+    tprintf(" {");
+    while (len >= sizeof (unsigned long)) {
+       unsigned long w;
+       umove(tcp, list, &w);
+       tprintf("%s %lx", first ? "" : ",", w);
+       first = 0;
+       len -= sizeof (unsigned long);
+       list += sizeof(unsigned long);
+    }
+    tprintf(" }");
+}
+
+int
+sys_sched_setaffinity(tcp)
+struct tcb *tcp;
+{
+    if (entering(tcp)) {
+       tprintf("%ld, %lu, ", tcp->u_arg[0], tcp->u_arg[1]);
+       print_affinitylist(tcp, tcp->u_arg[2], tcp->u_arg[1]);
+    }
+    return 0;
+}
+
+int
+sys_sched_getaffinity(tcp)
+struct tcb *tcp;
+{
+    if (entering(tcp)) {
+       tprintf("%ld, %lu, ", tcp->u_arg[0], tcp->u_arg[1]);
+    } else {
+       if (tcp->u_rval == -1)
+           tprintf("%#lx", tcp->u_arg[2]);
+       else
+           print_affinitylist(tcp, tcp->u_arg[2], tcp->u_rval);
+    }
+    return 0;
+}
+
+static const struct xlat schedulers[] = {
+       { SCHED_OTHER,  "SCHED_OTHER" },
+       { SCHED_RR,     "SCHED_RR" },
+       { SCHED_FIFO,   "SCHED_FIFO" },
+       { 0,            NULL }
+};
+
+int
+sys_sched_getscheduler(tcp)
+struct tcb *tcp;
+{
+    if (entering(tcp)) {
+       tprintf("%d", (int) tcp->u_arg[0]);
+    } else if (! syserror(tcp)) {
+       tcp->auxstr = xlookup (schedulers, tcp->u_rval);
+       if (tcp->auxstr != NULL)
+           return RVAL_STR;
+    }
+    return 0;
+}
+
+int
+sys_sched_setscheduler(tcp)
+struct tcb *tcp;
+{
+    if (entering(tcp)) {
+       struct sched_param p;
+       tprintf("%d, ", (int) tcp->u_arg[0]);
+       printxval(schedulers, tcp->u_arg[1], "SCHED_???");
+       if (umove(tcp, tcp->u_arg[2], &p) < 0)
+           tprintf(", %#lx", tcp->u_arg[2]);
+       else
+           tprintf(", { %d }", p.__sched_priority);
+    }
+    return 0;
+}
+
+int
+sys_sched_getparam(tcp)
+struct tcb *tcp;
+{
+    if (entering(tcp)) {
+           tprintf("%d, ", (int) tcp->u_arg[0]);
+    } else {
+       struct sched_param p;
+       if (umove(tcp, tcp->u_arg[1], &p) < 0)
+           tprintf("%#lx", tcp->u_arg[1]);
+       else
+           tprintf("{ %d }", p.__sched_priority);
+    }
+    return 0;
+}
+
+int
+sys_sched_setparam(tcp)
+struct tcb *tcp;
+{
+    if (entering(tcp)) {
+       struct sched_param p;
+       if (umove(tcp, tcp->u_arg[1], &p) < 0)
+           tprintf("%d, %#lx", (int) tcp->u_arg[0], tcp->u_arg[1]);
+       else
+           tprintf("%d, { %d }", (int) tcp->u_arg[0], p.__sched_priority);
+    }
+    return 0;
+}
+
+int
+sys_sched_get_priority_min(tcp)
+struct tcb *tcp;
+{
+    if (entering(tcp)) {
+       printxval(schedulers, tcp->u_arg[0], "SCHED_???");
+    }
+    return 0;
+}
+
+#ifdef X86_64
+#include <asm/prctl.h>
+
+static const struct xlat archvals[] = {
+       { ARCH_SET_GS,          "ARCH_SET_GS"           },
+       { ARCH_SET_FS,          "ARCH_SET_FS"           },
+       { ARCH_GET_FS,          "ARCH_GET_FS"           },
+       { ARCH_GET_GS,          "ARCH_GET_GS"           },
+       { 0,                    NULL                    },
+};
+
+int
+sys_arch_prctl(tcp)
+struct tcb *tcp;
+{
+    if (entering(tcp)) {
+       printxval(archvals, tcp->u_arg[0], "ARCH_???");
+       if (tcp->u_arg[0] == ARCH_SET_GS
+           || tcp->u_arg[0] == ARCH_SET_FS)
+           tprintf(", %#lx", tcp->u_arg[1]);
+    } else {
+       if (tcp->u_arg[0] == ARCH_GET_GS
+           || tcp->u_arg[0] == ARCH_GET_FS) {
+           long int v;
+           if (!syserror(tcp) && umove(tcp, tcp->u_arg[1], &v) != -1)
+               tprintf(", [%#lx]", v);
+           else
+               tprintf(", %#lx", tcp->u_arg[1]);
+       }
+    }
+    return 0;
+}
+#endif
+
+#endif