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