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