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