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