syscall.c revision 9797cebddbb0b2ce2ed19ed31ffdbd25d1f860da
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 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 * 3. The name of the author may not be used to endorse or promote products
20 *    derived from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 *
33 *	$Id$
34 */
35
36#include "defs.h"
37
38#include <signal.h>
39#include <time.h>
40#include <errno.h>
41#include <sys/user.h>
42#include <sys/syscall.h>
43#include <sys/param.h>
44
45#if HAVE_ASM_REG_H
46#ifdef SPARC
47#  define fpq kernel_fpq
48#  define fq kernel_fq
49#  define fpu kernel_fpu
50#endif
51#include <asm/reg.h>
52#ifdef SPARC
53#  undef fpq
54#  undef fq
55#  undef fpu
56#endif
57#endif
58
59#ifdef HAVE_SYS_REG_H
60#include <sys/reg.h>
61#ifndef PTRACE_PEEKUSR
62# define PTRACE_PEEKUSR PTRACE_PEEKUSER
63#endif
64#elif defined(HAVE_LINUX_PTRACE_H)
65#undef PTRACE_SYSCALL
66#include <linux/ptrace.h>
67#endif
68
69#if defined(LINUX) && defined(IA64)
70# include <asm/ptrace_offsets.h>
71# include <asm/rse.h>
72#endif
73
74#define NR_SYSCALL_BASE 0
75#ifdef LINUX
76#ifndef ERESTARTSYS
77#define ERESTARTSYS	512
78#endif
79#ifndef ERESTARTNOINTR
80#define ERESTARTNOINTR	513
81#endif
82#ifndef ERESTARTNOHAND
83#define ERESTARTNOHAND	514	/* restart if no handler.. */
84#endif
85#ifndef ENOIOCTLCMD
86#define ENOIOCTLCMD	515	/* No ioctl command */
87#endif
88#ifndef NSIG
89#define NSIG 32
90#endif
91#ifdef ARM
92#undef NSIG
93#define NSIG 32
94#undef NR_SYSCALL_BASE
95#define NR_SYSCALL_BASE __NR_SYSCALL_BASE
96#endif
97#endif /* LINUX */
98
99#include "syscall.h"
100
101/* Define these shorthand notations to simplify the syscallent files. */
102#define TF TRACE_FILE
103#define TI TRACE_IPC
104#define TN TRACE_NETWORK
105#define TP TRACE_PROCESS
106#define TS TRACE_SIGNAL
107
108struct sysent sysent0[] = {
109#include "syscallent.h"
110};
111int nsyscalls0 = sizeof sysent0 / sizeof sysent0[0];
112
113#if SUPPORTED_PERSONALITIES >= 2
114struct sysent sysent1[] = {
115#include "syscallent1.h"
116};
117int nsyscalls1 = sizeof sysent1 / sizeof sysent1[0];
118#endif /* SUPPORTED_PERSONALITIES >= 2 */
119
120#if SUPPORTED_PERSONALITIES >= 3
121struct sysent sysent2[] = {
122#include "syscallent2.h"
123};
124int nsyscalls2 = sizeof sysent2 / sizeof sysent2[0];
125#endif /* SUPPORTED_PERSONALITIES >= 3 */
126
127struct sysent *sysent;
128int nsyscalls;
129
130/* Now undef them since short defines cause wicked namespace pollution. */
131#undef TF
132#undef TI
133#undef TN
134#undef TP
135#undef TS
136
137char *errnoent0[] = {
138#include "errnoent.h"
139};
140int nerrnos0 = sizeof errnoent0 / sizeof errnoent0[0];
141
142#if SUPPORTED_PERSONALITIES >= 2
143char *errnoent1[] = {
144#include "errnoent1.h"
145};
146int nerrnos1 = sizeof errnoent1 / sizeof errnoent1[0];
147#endif /* SUPPORTED_PERSONALITIES >= 2 */
148
149#if SUPPORTED_PERSONALITIES >= 3
150char *errnoent2[] = {
151#include "errnoent2.h"
152};
153int nerrnos2 = sizeof errnoent2 / sizeof errnoent2[0];
154#endif /* SUPPORTED_PERSONALITIES >= 3 */
155
156char **errnoent;
157int nerrnos;
158
159int current_personality;
160
161int
162set_personality(personality)
163int personality;
164{
165	switch (personality) {
166	case 0:
167		errnoent = errnoent0;
168		nerrnos = nerrnos0;
169		sysent = sysent0;
170		nsyscalls = nsyscalls0;
171		ioctlent = ioctlent0;
172		nioctlents = nioctlents0;
173		signalent = signalent0;
174		nsignals = nsignals0;
175		break;
176
177#if SUPPORTED_PERSONALITIES >= 2
178	case 1:
179		errnoent = errnoent1;
180		nerrnos = nerrnos1;
181		sysent = sysent1;
182		nsyscalls = nsyscalls1;
183		ioctlent = ioctlent1;
184		nioctlents = nioctlents1;
185		signalent = signalent1;
186		nsignals = nsignals1;
187		break;
188#endif /* SUPPORTED_PERSONALITIES >= 2 */
189
190#if SUPPORTED_PERSONALITIES >= 3
191	case 2:
192		errnoent = errnoent2;
193		nerrnos = nerrnos2;
194		sysent = sysent2;
195		nsyscalls = nsyscalls2;
196		ioctlent = ioctlent2;
197		nioctlents = nioctlents2;
198		signalent = signalent2;
199		nsignals = nsignals2;
200		break;
201#endif /* SUPPORTED_PERSONALITIES >= 3 */
202
203	default:
204		return -1;
205	}
206
207	current_personality = personality;
208	return 0;
209}
210
211int qual_flags[MAX_QUALS];
212
213static int call_count[MAX_QUALS];
214static int error_count[MAX_QUALS];
215static struct timeval tv_count[MAX_QUALS];
216static int sorted_count[MAX_QUALS];
217
218static struct timeval shortest = { 1000000, 0 };
219
220static int qual_syscall(), qual_signal(), qual_fault(), qual_desc();
221
222static struct qual_options {
223	int bitflag;
224	char *option_name;
225	int (*qualify)();
226	char *argument_name;
227} qual_options[] = {
228	{ QUAL_TRACE,	"trace",	qual_syscall,	"system call"	},
229	{ QUAL_TRACE,	"t",		qual_syscall,	"system call"	},
230	{ QUAL_ABBREV,	"abbrev",	qual_syscall,	"system call"	},
231	{ QUAL_ABBREV,	"a",		qual_syscall,	"system call"	},
232	{ QUAL_VERBOSE,	"verbose",	qual_syscall,	"system call"	},
233	{ QUAL_VERBOSE,	"v",		qual_syscall,	"system call"	},
234	{ QUAL_RAW,	"raw",		qual_syscall,	"system call"	},
235	{ QUAL_RAW,	"x",		qual_syscall,	"system call"	},
236	{ QUAL_SIGNAL,	"signal",	qual_signal,	"signal"	},
237	{ QUAL_SIGNAL,	"signals",	qual_signal,	"signal"	},
238	{ QUAL_SIGNAL,	"s",		qual_signal,	"signal"	},
239	{ QUAL_FAULT,	"fault",	qual_fault,	"fault"		},
240	{ QUAL_FAULT,	"faults",	qual_fault,	"fault"		},
241	{ QUAL_FAULT,	"m",		qual_fault,	"fault"		},
242	{ QUAL_READ,	"read",		qual_desc,	"descriptor"	},
243	{ QUAL_READ,	"reads",	qual_desc,	"descriptor"	},
244	{ QUAL_READ,	"r",		qual_desc,	"descriptor"	},
245	{ QUAL_WRITE,	"write",	qual_desc,	"descriptor"	},
246	{ QUAL_WRITE,	"writes",	qual_desc,	"descriptor"	},
247	{ QUAL_WRITE,	"w",		qual_desc,	"descriptor"	},
248	{ 0,		NULL,		NULL,		NULL		},
249};
250
251static void
252qualify_one(n, opt, not)
253	int n;
254	struct qual_options *opt;
255	int not;
256{
257	if (not)
258		qual_flags[n] &= ~opt->bitflag;
259	else
260		qual_flags[n] |= opt->bitflag;
261}
262
263static int
264qual_syscall(s, opt, not)
265	char *s;
266	struct qual_options *opt;
267	int not;
268{
269	int i;
270	int any = 0;
271
272	for (i = 0; i < nsyscalls; i++) {
273		if (strcmp(s, sysent[i].sys_name) == 0) {
274			qualify_one(i, opt, not);
275			any = 1;
276		}
277	}
278	return !any;
279}
280
281static int
282qual_signal(s, opt, not)
283	char *s;
284	struct qual_options *opt;
285	int not;
286{
287	int i;
288	char buf[32];
289
290	if (s && *s && isdigit((unsigned char)*s)) {
291		qualify_one(atoi(s), opt, not);
292		return 1;
293	}
294	strcpy(buf, s);
295	s = buf;
296	for (i = 0; s[i]; i++)
297		s[i] = toupper((unsigned char)(s[i]));
298	if (strncmp(s, "SIG", 3) == 0)
299		s += 3;
300	for (i = 0; i <= NSIG; i++)
301		if (strcmp(s, signame(i) + 3) == 0) {
302			qualify_one(atoi(s), opt, not);
303			return 1;
304		}
305	return 0;
306}
307
308static int
309qual_fault(s, opt, not)
310	char *s;
311	struct qual_options *opt;
312	int not;
313{
314	return -1;
315}
316
317static int
318qual_desc(s, opt, not)
319	char *s;
320	struct qual_options *opt;
321	int not;
322{
323	if (s && *s && isdigit((unsigned char)*s)) {
324		qualify_one(atoi(s), opt, not);
325	}
326	return -1;
327}
328
329static int
330lookup_class(s)
331	char *s;
332{
333	if (strcmp(s, "file") == 0)
334		return TRACE_FILE;
335	if (strcmp(s, "ipc") == 0)
336		return TRACE_IPC;
337	if (strcmp(s, "network") == 0)
338		return TRACE_NETWORK;
339	if (strcmp(s, "process") == 0)
340		return TRACE_PROCESS;
341	if (strcmp(s, "signal") == 0)
342		return TRACE_SIGNAL;
343	return -1;
344}
345
346void
347qualify(s)
348char *s;
349{
350	struct qual_options *opt;
351	int not;
352	char *p;
353	int i, n;
354
355	opt = &qual_options[0];
356	for (i = 0; (p = qual_options[i].option_name); i++) {
357		n = strlen(p);
358		if (strncmp(s, p, n) == 0 && s[n] == '=') {
359			opt = &qual_options[i];
360			s += n + 1;
361			break;
362		}
363	}
364	not = 0;
365	if (*s == '!') {
366		not = 1;
367		s++;
368	}
369	if (strcmp(s, "none") == 0) {
370		not = 1 - not;
371		s = "all";
372	}
373	if (strcmp(s, "all") == 0) {
374		for (i = 0; i < MAX_QUALS; i++) {
375			if (not)
376				qual_flags[i] &= ~opt->bitflag;
377			else
378				qual_flags[i] |= opt->bitflag;
379		}
380		return;
381	}
382	for (i = 0; i < MAX_QUALS; i++) {
383		if (not)
384			qual_flags[i] |= opt->bitflag;
385		else
386			qual_flags[i] &= ~opt->bitflag;
387	}
388	for (p = strtok(s, ","); p; p = strtok(NULL, ",")) {
389		if (opt->bitflag == QUAL_TRACE && (n = lookup_class(p)) > 0) {
390			for (i = 0; i < MAX_QUALS; i++) {
391				if (sysent[i].sys_flags & n) {
392					if (not)
393						qual_flags[i] &= ~opt->bitflag;
394					else
395						qual_flags[i] |= opt->bitflag;
396				}
397			}
398			continue;
399		}
400		if (opt->qualify(p, opt, not)) {
401			fprintf(stderr, "strace: invalid %s `%s'\n",
402				opt->argument_name, p);
403			exit(1);
404		}
405	}
406	return;
407}
408
409static void
410dumpio(tcp)
411struct tcb *tcp;
412{
413	if (syserror(tcp))
414		return;
415	if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
416		return;
417	switch (tcp->scno + NR_SYSCALL_BASE) {
418	case SYS_read:
419#ifdef SYS_recv
420	case SYS_recv:
421#endif
422#ifdef SYS_recvfrom
423	case SYS_recvfrom:
424#endif
425		if (qual_flags[tcp->u_arg[0]] & QUAL_READ)
426			dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
427		break;
428	case SYS_write:
429#ifdef SYS_send
430	case SYS_send:
431#endif
432#ifdef SYS_sendto
433	case SYS_sendto:
434#endif
435		if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE)
436			dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
437		break;
438#ifdef SYS_readv
439        case SYS_readv:
440                if (qual_flags[tcp->u_arg[0]] & QUAL_READ)
441                        dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
442                break;
443#endif
444#ifdef SYS_writev
445        case SYS_writev:
446
447                if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE)
448                        dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
449                break;
450#endif
451	}
452}
453
454#ifndef FREEBSD
455enum subcall_style { shift_style, deref_style, mask_style, door_style };
456#else /* FREEBSD */
457enum subcall_style { shift_style, deref_style, mask_style, door_style, table_style };
458
459struct subcall {
460  int call;
461  int nsubcalls;
462  int subcalls[5];
463};
464
465const struct subcall subcalls_table[] = {
466  { SYS_shmsys, 5, { SYS_shmat, SYS_shmctl, SYS_shmdt, SYS_shmget, SYS_shmctl } },
467#ifdef SYS_semconfig
468  { SYS_semsys, 4, { SYS___semctl, SYS_semget, SYS_semop, SYS_semconfig } },
469#else
470  { SYS_semsys, 3, { SYS___semctl, SYS_semget, SYS_semop } },
471#endif
472  { SYS_msgsys, 4, { SYS_msgctl, SYS_msgget, SYS_msgsnd, SYS_msgrcv } },
473};
474#endif /* FREEBSD */
475
476#if !(defined(LINUX) && ( defined(ALPHA) || defined(MIPS) ))
477
478const int socket_map [] = {
479	       /* SYS_SOCKET      */ 97,
480	       /* SYS_BIND        */ 104,
481	       /* SYS_CONNECT     */ 98,
482	       /* SYS_LISTEN      */ 106,
483	       /* SYS_ACCEPT      */ 99,
484	       /* SYS_GETSOCKNAME */ 150,
485	       /* SYS_GETPEERNAME */ 141,
486	       /* SYS_SOCKETPAIR  */ 135,
487	       /* SYS_SEND        */ 101,
488	       /* SYS_RECV        */ 102,
489	       /* SYS_SENDTO      */ 133,
490	       /* SYS_RECVFROM    */ 125,
491	       /* SYS_SHUTDOWN    */ 134,
492	       /* SYS_SETSOCKOPT  */ 105,
493	       /* SYS_GETSOCKOPT  */ 118,
494	       /* SYS_SENDMSG     */ 114,
495	       /* SYS_RECVMSG     */ 113
496};
497
498void
499sparc_socket_decode (tcp)
500struct tcb *tcp;
501{
502	volatile long addr;
503	volatile int i, n;
504
505	if (tcp->u_arg [0] < 1 || tcp->u_arg [0] > sizeof(socket_map)/sizeof(int)+1){
506		return;
507	}
508	tcp->scno = socket_map [tcp->u_arg [0]-1];
509	n = tcp->u_nargs = sysent [tcp->scno].nargs;
510	addr = tcp->u_arg [1];
511	for (i = 0; i < n; i++){
512	        int arg;
513		if (umoven (tcp, addr, sizeof (arg), (void *) &arg) < 0)
514			arg = 0;
515		tcp->u_arg [i] = arg;
516		addr += sizeof (arg);
517	}
518}
519
520void
521decode_subcall(tcp, subcall, nsubcalls, style)
522struct tcb *tcp;
523int subcall;
524int nsubcalls;
525enum subcall_style style;
526{
527	long addr, mask, arg;
528	int i;
529
530	switch (style) {
531	case shift_style:
532		if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= nsubcalls)
533			return;
534		tcp->scno = subcall + tcp->u_arg[0];
535		if (sysent[tcp->scno].nargs != -1)
536			tcp->u_nargs = sysent[tcp->scno].nargs;
537		else
538			tcp->u_nargs--;
539		for (i = 0; i < tcp->u_nargs; i++)
540			tcp->u_arg[i] = tcp->u_arg[i + 1];
541		break;
542	case deref_style:
543		if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= nsubcalls)
544			return;
545		tcp->scno = subcall + tcp->u_arg[0];
546		addr = tcp->u_arg[1];
547		for (i = 0; i < sysent[tcp->scno].nargs; i++) {
548			if (umove(tcp, addr, &arg) < 0)
549				arg = 0;
550			tcp->u_arg[i] = arg;
551			addr += sizeof(arg);
552		}
553		tcp->u_nargs = sysent[tcp->scno].nargs;
554		break;
555	case mask_style:
556		mask = (tcp->u_arg[0] >> 8) & 0xff;
557		for (i = 0; mask; i++)
558			mask >>= 1;
559		if (i >= nsubcalls)
560			return;
561		tcp->u_arg[0] &= 0xff;
562		tcp->scno = subcall + i;
563		if (sysent[tcp->scno].nargs != -1)
564			tcp->u_nargs = sysent[tcp->scno].nargs;
565		break;
566	case door_style:
567		/*
568		 * Oh, yuck.  The call code is the *sixth* argument.
569		 * (don't you mean the *last* argument? - JH)
570		 */
571		if (tcp->u_arg[5] < 0 || tcp->u_arg[5] >= nsubcalls)
572			return;
573		tcp->scno = subcall + tcp->u_arg[5];
574		if (sysent[tcp->scno].nargs != -1)
575			tcp->u_nargs = sysent[tcp->scno].nargs;
576		else
577			tcp->u_nargs--;
578		break;
579#ifdef FREEBSD
580	case table_style:
581		for (i = 0; i < sizeof(subcalls_table) / sizeof(struct subcall); i++)
582			if (subcalls_table[i].call == tcp->scno) break;
583		if (i < sizeof(subcalls_table) / sizeof(struct subcall) &&
584		    tcp->u_arg[0] >= 0 && tcp->u_arg[0] < subcalls_table[i].nsubcalls) {
585			tcp->scno = subcalls_table[i].subcalls[tcp->u_arg[0]];
586			for (i = 0; i < tcp->u_nargs; i++)
587				tcp->u_arg[i] = tcp->u_arg[i + 1];
588		}
589		break;
590#endif /* FREEBSD */
591	}
592}
593#endif
594
595struct tcb *tcp_last = NULL;
596
597static int
598internal_syscall(tcp)
599struct tcb *tcp;
600{
601	/*
602	 * We must always trace a few critical system calls in order to
603	 * correctly support following forks in the presence of tracing
604	 * qualifiers.
605	 */
606	switch (tcp->scno + NR_SYSCALL_BASE) {
607#ifdef SYS_fork
608	case SYS_fork:
609#endif
610#ifdef SYS_vfork
611	case SYS_vfork:
612#endif
613#ifdef SYS_fork1
614	case SYS_fork1:
615#endif
616#ifdef SYS_forkall
617	case SYS_forkall:
618#endif
619#ifdef SYS_rfork1
620	case SYS_rfork1:
621#endif
622#ifdef SYS_rforkall
623	case SYS_rforkall:
624#endif
625		internal_fork(tcp);
626		break;
627#ifdef SYS_clone
628	case SYS_clone:
629		internal_clone(tcp);
630		break;
631#endif
632#ifdef SYS_clone2
633	case SYS_clone2:
634		internal_clone(tcp);
635		break;
636#endif
637#ifdef SYS_execv
638	case SYS_execv:
639#endif
640#ifdef SYS_execve
641	case SYS_execve:
642#endif
643#ifdef SYS_rexecve
644	case SYS_rexecve:
645#endif
646		internal_exec(tcp);
647		break;
648
649#ifdef SYS_wait
650	case SYS_wait:
651#endif
652#ifdef SYS_wait4
653	case SYS_wait4:
654#endif
655#ifdef SYS32_wait4
656	case SYS32_wait4:
657#endif
658#ifdef SYS_waitpid
659	case SYS_waitpid:
660#endif
661#ifdef SYS_waitsys
662	case SYS_waitsys:
663#endif
664		internal_wait(tcp);
665		break;
666
667#ifdef SYS_exit
668	case SYS_exit:
669#endif
670#ifdef SYS32_exit
671	case SYS32_exit:
672#endif
673		internal_exit(tcp);
674		break;
675	}
676	return 0;
677}
678
679
680#ifdef LINUX
681#if defined (I386)
682	static long eax;
683#elif defined (IA64)
684	long r8, r10, psr;
685	long ia32 = 0;
686#elif defined (POWERPC)
687	static long result,flags;
688#elif defined (M68K)
689	static int d0;
690#elif defined (ARM)
691	static int r0;
692#elif defined (ALPHA)
693	static long r0;
694	static long a3;
695#elif defined (SPARC)
696	static struct regs regs;
697	static unsigned long trap;
698#elif defined(MIPS)
699	static long a3;
700	static long r2;
701#elif defined(S390) || defined(S390X)
702	static long gpr2;
703	static long pc;
704	static long syscall_mode;
705#elif defined(HPPA)
706	static long r28;
707#elif defined(SH)
708       static long r0;
709#elif defined(X86_64)
710       static long rax;
711#endif
712#endif /* LINUX */
713#ifdef FREEBSD
714	struct reg regs;
715#endif /* FREEBSD */
716
717int
718get_scno(tcp)
719struct tcb *tcp;
720{
721	long scno = 0;
722#ifndef USE_PROCFS
723	int pid = tcp->pid;
724#endif /* !PROCFS */
725
726#ifdef LINUX
727#if defined(S390) || defined(S390X)
728	if (upeek(pid, PT_GPR2, &syscall_mode) < 0)
729		return -1;
730	if (syscall_mode != -ENOSYS){
731		/*
732		 * Since kernel version 2.5.44 the scno gets passed in gpr2.
733		 */
734		scno = syscall_mode;
735	}
736	else {
737	       	/*
738		 * Old style of "passing" the scno via the SVC instruction.
739		 */
740
741		long opcode, offset_reg, tmp;
742		void * svc_addr;
743		int gpr_offset[16] = {PT_GPR0,  PT_GPR1,  PT_ORIGGPR2, PT_GPR3,
744				      PT_GPR4,  PT_GPR5,  PT_GPR6,     PT_GPR7,
745				      PT_GPR8,  PT_GPR9,  PT_GPR10,    PT_GPR11,
746				      PT_GPR12, PT_GPR13, PT_GPR14,    PT_GPR15};
747
748		if (upeek(pid, PT_PSWADDR, &pc) < 0)
749			return -1;
750		opcode = ptrace(PTRACE_PEEKTEXT, pid, (char *)(pc-sizeof(long)), 0);
751		if (errno)
752			return -1;
753
754		/*
755		 *  We have to check if the SVC got executed directly or via an
756		 *  EXECUTE instruction. In case of EXECUTE it is necessary to do
757		 *  instruction decoding to derive the system call number.
758		 *  Unfortunately the opcode sizes of EXECUTE and SVC are differently,
759		 *  so that this doesn't work if a SVC opcode is part of an EXECUTE
760		 *  opcode. Since there is no way to find out the opcode size this
761		 *  is the best we can do...
762		 */
763
764		if ((opcode & 0xff00) == 0x0a00) {
765			/* SVC opcode */
766			scno = opcode & 0xff;
767		}
768		else {
769			/* SVC got executed by EXECUTE instruction */
770
771			/*
772			 *  Do instruction decoding of EXECUTE. If you really want to
773			 *  understand this, read the Principles of Operations.
774			 */
775			svc_addr = (void *) (opcode & 0xfff);
776
777			tmp = 0;
778			offset_reg = (opcode & 0x000f0000) >> 16;
779			if (offset_reg && (upeek(pid, gpr_offset[offset_reg], &tmp) < 0))
780				return -1;
781			svc_addr += tmp;
782
783			tmp = 0;
784			offset_reg = (opcode & 0x0000f000) >> 12;
785			if (offset_reg && (upeek(pid, gpr_offset[offset_reg], &tmp) < 0))
786				return -1;
787			svc_addr += tmp;
788
789			scno = ptrace(PTRACE_PEEKTEXT, pid, svc_addr, 0);
790			if (errno)
791				return -1;
792#if defined(S390X)
793			scno >>= 48;
794#else
795			scno >>= 16;
796#endif
797			tmp = 0;
798			offset_reg = (opcode & 0x00f00000) >> 20;
799			if (offset_reg && (upeek(pid, gpr_offset[offset_reg], &tmp) < 0))
800				return -1;
801
802			scno = (scno | tmp) & 0xff;
803		}
804	}
805#elif defined (POWERPC)
806	if (upeek(pid, 4*PT_R0, &scno) < 0)
807		return -1;
808	if (!(tcp->flags & TCB_INSYSCALL)) {
809		/* Check if we return from execve. */
810		if (scno == 0 && (tcp->flags & TCB_WAITEXECVE)) {
811			tcp->flags &= ~TCB_WAITEXECVE;
812			return 0;
813		}
814	}
815#elif defined (I386)
816	if (upeek(pid, 4*ORIG_EAX, &scno) < 0)
817		return -1;
818#elif defined (X86_64)
819	if (upeek(pid, 8*ORIG_RAX, &scno) < 0)
820		return -1;
821
822	if (!(tcp->flags & TCB_INSYSCALL)) {
823	  	static int currpers=-1;
824		long val;
825
826		/* Check CS register value. On x86-64 linux it is:
827		 * 	0x33	for long mode (64 bit)
828		 * 	0x23	for compatibility mode (32 bit)
829		 * It takes only one ptrace and thus doesn't need
830		 * to be cached.
831		 */
832		if (upeek(pid, 8*CS, &val) < 0)
833			return -1;
834		switch(val)
835		{
836			case 0x23: currpers = 1; break;
837			case 0x33: currpers = 0; break;
838			default:
839				fprintf(stderr, "Unknown value CS=0x%02X while "
840					 "detecting personality of process "
841					 "PID=%d\n", (int)val, pid);
842				currpers = current_personality;
843				break;
844		}
845#if 0
846		/* This version analyzes the opcode of a syscall instruction.
847		 * (int 0x80 on i386 vs. syscall on x86-64)
848		 * It works, but is too complicated.
849		 */
850		unsigned long val, rip, i;
851
852		if(upeek(pid, 8*RIP, &rip)<0)
853			perror("upeek(RIP)");
854
855		/* sizeof(syscall) == sizeof(int 0x80) == 2 */
856		rip-=2;
857		errno = 0;
858
859		call = ptrace(PTRACE_PEEKTEXT,pid,(char *)rip,0);
860		if (errno)
861			printf("ptrace_peektext failed: %s\n",
862					strerror(errno));
863		switch (call & 0xffff)
864		{
865			/* x86-64: syscall = 0x0f 0x05 */
866			case 0x050f: currpers = 0; break;
867			/* i386: int 0x80 = 0xcd 0x80 */
868			case 0x80cd: currpers = 1; break;
869			default:
870				currpers = current_personality;
871				fprintf(stderr,
872					"Unknown syscall opcode (0x%04X) while "
873					"detecting personality of process "
874					"PID=%d\n", (int)call, pid);
875				break;
876		}
877#endif
878		if(currpers != current_personality)
879		{
880			char *names[]={"64 bit", "32 bit"};
881			set_personality(currpers);
882			printf("[ Process PID=%d runs in %s mode. ]\n",
883					pid, names[current_personality]);
884		}
885	}
886#elif defined(IA64)
887#	define IA64_PSR_IS	((long)1 << 34)
888	if (upeek (pid, PT_CR_IPSR, &psr) >= 0)
889		ia32 = (psr & IA64_PSR_IS) != 0;
890	if (!(tcp->flags & TCB_INSYSCALL)) {
891		if (ia32) {
892			if (upeek(pid, PT_R1, &scno) < 0)	/* orig eax */
893				return -1;
894			/* Check if we return from execve. */
895		} else {
896			if (upeek (pid, PT_R15, &scno) < 0)
897				return -1;
898		}
899	} else {
900		/* syscall in progress */
901		if (upeek (pid, PT_R8, &r8) < 0)
902			return -1;
903		if (upeek (pid, PT_R10, &r10) < 0)
904			return -1;
905	}
906	if (tcp->flags & TCB_WAITEXECVE) {
907		tcp->flags &= ~TCB_WAITEXECVE;
908		return 0;
909	}
910
911#elif defined (ARM)
912	{
913	    long pc;
914	    upeek(pid, 4*15, &pc);
915	    umoven(tcp, pc-4, 4, (char *)&scno);
916	    scno &= 0x000fffff;
917	}
918#elif defined (M68K)
919	if (upeek(pid, 4*PT_ORIG_D0, &scno) < 0)
920		return -1;
921#elif defined (MIPS)
922	if (upeek(pid, REG_A3, &a3) < 0)
923	  	return -1;
924
925	if(!(tcp->flags & TCB_INSYSCALL)) {
926	  	if (upeek(pid, REG_V0, &scno) < 0)
927		  	return -1;
928
929		if (scno < 0 || scno > nsyscalls) {
930			if(a3 == 0 || a3 == -1) {
931				if(debug)
932					fprintf (stderr, "stray syscall exit: v0 = %ld\n", scno);
933				return 0;
934			}
935		}
936	} else {
937	  	if (upeek(pid, REG_V0, &r2) < 0)
938	    		return -1;
939	}
940#elif defined (ALPHA)
941	if (upeek(pid, REG_A3, &a3) < 0)
942		return -1;
943
944	if (!(tcp->flags & TCB_INSYSCALL)) {
945		if (upeek(pid, REG_R0, &scno) < 0)
946			return -1;
947
948		/* Check if we return from execve. */
949		if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
950			tcp->flags &= ~TCB_WAITEXECVE;
951			return 0;
952		}
953
954		/*
955		 * Do some sanity checks to figure out if it's
956		 * really a syscall entry
957		 */
958		if (scno < 0 || scno > nsyscalls) {
959			if (a3 == 0 || a3 == -1) {
960				if (debug)
961					fprintf (stderr, "stray syscall exit: r0 = %ld\n", scno);
962				return 0;
963			}
964		}
965	}
966	else {
967		if (upeek(pid, REG_R0, &r0) < 0)
968			return -1;
969	}
970#elif defined (SPARC)
971	/* Everything we need is in the current register set. */
972	if (ptrace(PTRACE_GETREGS,pid,(char *)&regs,0) < 0)
973		return -1;
974
975        /* If we are entering, then disassemble the syscall trap. */
976	if (!(tcp->flags & TCB_INSYSCALL)) {
977		/* Retrieve the syscall trap instruction. */
978		errno = 0;
979		trap = ptrace(PTRACE_PEEKTEXT,pid,(char *)regs.r_pc,0);
980		if (errno)
981			return -1;
982
983		/* Disassemble the trap to see what personality to use. */
984		switch (trap) {
985		case 0x91d02010:
986			/* Linux/SPARC syscall trap. */
987			set_personality(0);
988			break;
989		case 0x91d0206d:
990			/* Linux/SPARC64 syscall trap. */
991			fprintf(stderr,"syscall: Linux/SPARC64 not supported yet\n");
992			return -1;
993		case 0x91d02000:
994			/* SunOS syscall trap. (pers 1) */
995			fprintf(stderr,"syscall: SunOS no support\n");
996			return -1;
997		case 0x91d02008:
998			/* Solaris 2.x syscall trap. (per 2) */
999			set_personality(1);
1000			break;
1001		case 0x91d02009:
1002			/* NetBSD/FreeBSD syscall trap. */
1003			fprintf(stderr,"syscall: NetBSD/FreeBSD not supported\n");
1004			return -1;
1005		case 0x91d02027:
1006			/* Solaris 2.x gettimeofday */
1007			set_personality(1);
1008			break;
1009		default:
1010			/* Unknown syscall trap. */
1011			if(tcp->flags & TCB_WAITEXECVE) {
1012				tcp->flags &= ~TCB_WAITEXECVE;
1013				return 0;
1014			}
1015			fprintf(stderr,"syscall: unknown syscall trap %08x %08x\n", trap, regs.r_pc);
1016			return -1;
1017		}
1018
1019		/* Extract the system call number from the registers. */
1020		if (trap == 0x91d02027)
1021			scno = 156;
1022		else
1023			scno = regs.r_g1;
1024		if (scno == 0) {
1025			scno = regs.r_o0;
1026			memmove (&regs.r_o0, &regs.r_o1, 7*sizeof(regs.r_o0));
1027		}
1028	}
1029#elif defined(HPPA)
1030	if (upeek(pid, PT_GR20, &scno) < 0)
1031		return -1;
1032	if (!(tcp->flags & TCB_INSYSCALL)) {
1033		/* Check if we return from execve. */
1034		if ((tcp->flags & TCB_WAITEXECVE)) {
1035			tcp->flags &= ~TCB_WAITEXECVE;
1036			return 0;
1037		}
1038	}
1039#elif defined(SH)
1040       /*
1041        * In the new syscall ABI, the system call number is in R3.
1042        */
1043       if (upeek(pid, 4*(REG_REG0+3), &scno) < 0)
1044               return -1;
1045
1046       if (scno < 0) {
1047           /* Odd as it may seem, a glibc bug has been known to cause
1048              glibc to issue bogus negative syscall numbers.  So for
1049              our purposes, make strace print what it *should* have been */
1050           long correct_scno = (scno & 0xff);
1051           if (debug)
1052               fprintf(stderr,
1053                   "Detected glibc bug: bogus system call number = %ld, "
1054		   "correcting to %ld\n",
1055                   scno,
1056                   correct_scno);
1057           scno = correct_scno;
1058       }
1059
1060
1061       if (!(tcp->flags & TCB_INSYSCALL)) {
1062               /* Check if we return from execve. */
1063               if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1064                       tcp->flags &= ~TCB_WAITEXECVE;
1065                       return 0;
1066               }
1067       }
1068#endif /* SH */
1069#endif /* LINUX */
1070#ifdef SUNOS4
1071	if (upeek(pid, uoff(u_arg[7]), &scno) < 0)
1072		return -1;
1073#elif defined(SH)
1074       /* new syscall ABI returns result in R0 */
1075       if (upeek(pid, 4*REG_REG0, (long *)&r0) < 0)
1076               return -1;
1077#endif
1078#ifdef USE_PROCFS
1079#ifdef HAVE_PR_SYSCALL
1080	scno = tcp->status.PR_SYSCALL;
1081#else /* !HAVE_PR_SYSCALL */
1082#ifndef FREEBSD
1083	scno = tcp->status.PR_WHAT;
1084#else /* FREEBSD */
1085	if (pread(tcp->pfd_reg, &regs, sizeof(regs), 0) < 0) {
1086	        perror("pread");
1087                return -1;
1088        }
1089	switch (regs.r_eax) {
1090	case SYS_syscall:
1091	case SYS___syscall:
1092    	        pread(tcp->pfd, &scno, sizeof(scno), regs.r_esp + sizeof(int));
1093	        break;
1094	default:
1095	        scno = regs.r_eax;
1096	        break;
1097	}
1098#endif /* FREEBSD */
1099#endif /* !HAVE_PR_SYSCALL */
1100#endif /* USE_PROCFS */
1101	if (!(tcp->flags & TCB_INSYSCALL))
1102		tcp->scno = scno;
1103	return 1;
1104}
1105
1106
1107int
1108syscall_fixup(tcp)
1109struct tcb *tcp;
1110{
1111#ifndef USE_PROCFS
1112	int pid = tcp->pid;
1113#else /* USE_PROCFS */
1114	int scno = tcp->scno;
1115
1116	if (!(tcp->flags & TCB_INSYSCALL)) {
1117		if (tcp->status.PR_WHY != PR_SYSENTRY) {
1118			if (
1119			    scno == SYS_fork
1120#ifdef SYS_vfork
1121			    || scno == SYS_vfork
1122#endif /* SYS_vfork */
1123#ifdef SYS_fork1
1124			    || scno == SYS_fork1
1125#endif /* SYS_fork1 */
1126#ifdef SYS_forkall
1127			    || scno == SYS_forkall
1128#endif /* SYS_forkall */
1129#ifdef SYS_rfork1
1130			    || scno == SYS_rfork1
1131#endif /* SYS_fork1 */
1132#ifdef SYS_rforkall
1133			    || scno == SYS_rforkall
1134#endif /* SYS_rforkall */
1135			    ) {
1136				/* We are returning in the child, fake it. */
1137				tcp->status.PR_WHY = PR_SYSENTRY;
1138				trace_syscall(tcp);
1139				tcp->status.PR_WHY = PR_SYSEXIT;
1140			}
1141			else {
1142				fprintf(stderr, "syscall: missing entry\n");
1143				tcp->flags |= TCB_INSYSCALL;
1144			}
1145		}
1146	}
1147	else {
1148		if (tcp->status.PR_WHY != PR_SYSEXIT) {
1149			fprintf(stderr, "syscall: missing exit\n");
1150			tcp->flags &= ~TCB_INSYSCALL;
1151		}
1152	}
1153#endif /* USE_PROCFS */
1154#ifdef SUNOS4
1155	if (!(tcp->flags & TCB_INSYSCALL)) {
1156		if (scno == 0) {
1157			fprintf(stderr, "syscall: missing entry\n");
1158			tcp->flags |= TCB_INSYSCALL;
1159		}
1160	}
1161	else {
1162		if (scno != 0) {
1163			if (debug) {
1164				/*
1165				 * This happens when a signal handler
1166				 * for a signal which interrupted a
1167				 * a system call makes another system call.
1168				 */
1169				fprintf(stderr, "syscall: missing exit\n");
1170			}
1171			tcp->flags &= ~TCB_INSYSCALL;
1172		}
1173	}
1174#endif /* SUNOS4 */
1175#ifdef LINUX
1176#if defined (I386)
1177	if (upeek(pid, 4*EAX, &eax) < 0)
1178		return -1;
1179	if (eax != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1180		if (debug)
1181			fprintf(stderr, "stray syscall exit: eax = %ld\n", eax);
1182		return 0;
1183	}
1184#elif defined (X86_64)
1185	if (upeek(pid, 8*RAX, &rax) < 0)
1186		return -1;
1187	if (rax != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1188		if (debug)
1189			fprintf(stderr, "stray syscall exit: rax = %ld\n", rax);
1190		return 0;
1191	}
1192#elif defined (S390) || defined (S390X)
1193	if (upeek(pid, PT_GPR2, &gpr2) < 0)
1194		return -1;
1195	if (syscall_mode != -ENOSYS)
1196		syscall_mode = tcp->scno;
1197	if (gpr2 != syscall_mode && !(tcp->flags & TCB_INSYSCALL)) {
1198		if (debug)
1199			fprintf(stderr, "stray syscall exit: gpr2 = %ld\n", gpr2);
1200		return 0;
1201	}
1202#elif defined (POWERPC)
1203# define SO_MASK 0x10000000
1204	if (upeek(pid, 4*PT_CCR, &flags) < 0)
1205		return -1;
1206	if (upeek(pid, 4*PT_R3, &result) < 0)
1207		return -1;
1208	if (flags & SO_MASK)
1209		result = -result;
1210#elif defined (M68K)
1211	if (upeek(pid, 4*PT_D0, &d0) < 0)
1212		return -1;
1213	if (d0 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1214		if (debug)
1215			fprintf(stderr, "stray syscall exit: d0 = %ld\n", d0);
1216		return 0;
1217	}
1218#elif defined (ARM)
1219	if (upeek(pid, 4*0, (long *)&r0) < 0)
1220		return -1;
1221	if ( 0 && r0 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1222		if (debug)
1223			fprintf(stderr, "stray syscall exit: d0 = %ld\n", r0);
1224		return 0;
1225	}
1226#elif defined (HPPA)
1227	if (upeek(pid, PT_GR28, &r28) < 0)
1228		return -1;
1229#elif defined(IA64)
1230	if (upeek(pid, PT_R10, &r10) < 0)
1231		return -1;
1232	if (upeek(pid, PT_R8, &r8) < 0)
1233		return -1;
1234	if (ia32 && r8 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1235		if (debug)
1236			fprintf(stderr, "stray syscall exit: r8 = %ld\n", r8);
1237		return 0;
1238	}
1239#endif
1240#endif /* LINUX */
1241	return 1;
1242}
1243
1244int
1245get_error(tcp)
1246struct tcb *tcp;
1247{
1248	int u_error = 0;
1249#ifdef LINUX
1250#if defined(S390) || defined(S390X)
1251		if (gpr2 && (unsigned) -gpr2 < nerrnos) {
1252			tcp->u_rval = -1;
1253			u_error = -gpr2;
1254		}
1255		else {
1256			tcp->u_rval = gpr2;
1257			u_error = 0;
1258		}
1259#else /* !S390 && !S390X */
1260#ifdef I386
1261		if (eax < 0 && -eax < nerrnos) {
1262			tcp->u_rval = -1;
1263			u_error = -eax;
1264		}
1265		else {
1266			tcp->u_rval = eax;
1267			u_error = 0;
1268		}
1269#else /* !I386 */
1270#ifdef X86_64
1271		if (rax < 0 && -rax < nerrnos) {
1272			tcp->u_rval = -1;
1273			u_error = -rax;
1274		}
1275		else {
1276			tcp->u_rval = rax;
1277			u_error = 0;
1278		}
1279#else
1280#ifdef IA64
1281		if (ia32) {
1282			int err;
1283
1284			err = (int)r8;
1285			if (err < 0 && -err < nerrnos) {
1286				tcp->u_rval = -1;
1287				u_error = -err;
1288			}
1289			else {
1290				tcp->u_rval = err;
1291				u_error = 0;
1292			}
1293		} else {
1294			if (r10) {
1295				tcp->u_rval = -1;
1296				u_error = r8;
1297			} else {
1298				tcp->u_rval = r8;
1299				u_error = 0;
1300			}
1301		}
1302#else /* !IA64 */
1303#ifdef MIPS
1304		if (a3) {
1305		  	tcp->u_rval = -1;
1306			u_error = r2;
1307		} else {
1308		  	tcp->u_rval = r2;
1309			u_error = 0;
1310		}
1311#else
1312#ifdef POWERPC
1313		if (result && (unsigned) -result < nerrnos) {
1314			tcp->u_rval = -1;
1315			u_error = -result;
1316		}
1317		else {
1318			tcp->u_rval = result;
1319			u_error = 0;
1320		}
1321#else /* !POWERPC */
1322#ifdef M68K
1323		if (d0 && (unsigned) -d0 < nerrnos) {
1324			tcp->u_rval = -1;
1325			u_error = -d0;
1326		}
1327		else {
1328			tcp->u_rval = d0;
1329			u_error = 0;
1330		}
1331#else /* !M68K */
1332#ifdef ARM
1333		if (r0 && (unsigned) -r0 < nerrnos) {
1334			tcp->u_rval = -1;
1335			u_error = -r0;
1336		}
1337		else {
1338			tcp->u_rval = r0;
1339			u_error = 0;
1340		}
1341#else /* !ARM */
1342#ifdef ALPHA
1343		if (a3) {
1344			tcp->u_rval = -1;
1345			u_error = r0;
1346		}
1347		else {
1348			tcp->u_rval = r0;
1349			u_error = 0;
1350		}
1351#else /* !ALPHA */
1352#ifdef SPARC
1353		if (regs.r_psr & PSR_C) {
1354			tcp->u_rval = -1;
1355			u_error = regs.r_o0;
1356		}
1357		else {
1358			tcp->u_rval = regs.r_o0;
1359			u_error = 0;
1360		}
1361#else /* !SPARC */
1362#ifdef HPPA
1363		if (r28 && (unsigned) -r28 < nerrnos) {
1364			tcp->u_rval = -1;
1365			u_error = -r28;
1366		}
1367		else {
1368			tcp->u_rval = r28;
1369			u_error = 0;
1370		}
1371#else
1372#ifdef SH
1373               /* interpret R0 as return value or error number */
1374               if (r0 && (unsigned) -r0 < nerrnos) {
1375                       tcp->u_rval = -1;
1376                       u_error = -r0;
1377               }
1378               else {
1379                       tcp->u_rval = r0;
1380                       u_error = 0;
1381               }
1382#endif /* SH */
1383#endif /* HPPA */
1384#endif /* SPARC */
1385#endif /* ALPHA */
1386#endif /* ARM */
1387#endif /* M68K */
1388#endif /* POWERPC */
1389#endif /* MIPS */
1390#endif /* IA64 */
1391#endif /* X86_64 */
1392#endif /* I386 */
1393#endif /* S390 || S390X */
1394#endif /* LINUX */
1395#ifdef SUNOS4
1396		/* get error code from user struct */
1397		if (upeek(pid, uoff(u_error), &u_error) < 0)
1398			return -1;
1399		u_error >>= 24; /* u_error is a char */
1400
1401		/* get system call return value */
1402		if (upeek(pid, uoff(u_rval1), &tcp->u_rval) < 0)
1403			return -1;
1404#endif /* SUNOS4 */
1405#ifdef SVR4
1406#ifdef SPARC
1407		/* Judicious guessing goes a long way. */
1408		if (tcp->status.pr_reg[R_PSR] & 0x100000) {
1409			tcp->u_rval = -1;
1410			u_error = tcp->status.pr_reg[R_O0];
1411		}
1412		else {
1413			tcp->u_rval = tcp->status.pr_reg[R_O0];
1414			u_error = 0;
1415		}
1416#endif /* SPARC */
1417#ifdef I386
1418		/* Wanna know how to kill an hour single-stepping? */
1419		if (tcp->status.PR_REG[EFL] & 0x1) {
1420			tcp->u_rval = -1;
1421			u_error = tcp->status.PR_REG[EAX];
1422		}
1423		else {
1424			tcp->u_rval = tcp->status.PR_REG[EAX];
1425#ifdef HAVE_LONG_LONG
1426			tcp->u_lrval =
1427				((unsigned long long) tcp->status.PR_REG[EDX] << 32) +
1428				tcp->status.PR_REG[EAX];
1429#endif
1430			u_error = 0;
1431		}
1432#endif /* I386 */
1433#ifdef X86_64
1434		/* Wanna know how to kill an hour single-stepping? */
1435		if (tcp->status.PR_REG[EFLAGS] & 0x1) {
1436			tcp->u_rval = -1;
1437			u_error = tcp->status.PR_REG[RAX];
1438		}
1439		else {
1440			tcp->u_rval = tcp->status.PR_REG[RAX];
1441			u_error = 0;
1442		}
1443#endif /* X86_64 */
1444#ifdef MIPS
1445		if (tcp->status.pr_reg[CTX_A3]) {
1446			tcp->u_rval = -1;
1447			u_error = tcp->status.pr_reg[CTX_V0];
1448		}
1449		else {
1450			tcp->u_rval = tcp->status.pr_reg[CTX_V0];
1451			u_error = 0;
1452		}
1453#endif /* MIPS */
1454#endif /* SVR4 */
1455#ifdef FREEBSD
1456		if (regs.r_eflags & PSL_C) {
1457 		        tcp->u_rval = -1;
1458		        u_error = regs.r_eax;
1459		} else {
1460		        tcp->u_rval = regs.r_eax;
1461			tcp->u_lrval =
1462			  ((unsigned long long) regs.r_edx << 32) +  regs.r_eax;
1463		        u_error = 0;
1464		}
1465#endif /* FREEBSD */
1466	tcp->u_error = u_error;
1467	return 1;
1468}
1469
1470int
1471force_result(tcp, error, rval)
1472	struct tcb *tcp;
1473	int error;
1474	long rval;
1475{
1476#ifdef LINUX
1477#if defined(S390) || defined(S390X)
1478	gpr2 = error ? -error : rval;
1479	if (upeek(pid, PT_GPR2, &gpr2) < 0)
1480		return -1;
1481	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)PT_GPR2, gpr2) < 0)
1482		return -1;
1483#else /* !S390 && !S390X */
1484#ifdef I386
1485	eax = error ? -error : rval;
1486	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(EAX * 4), eax) < 0)
1487		return -1;
1488#else /* !I386 */
1489#ifdef X86_64
1490	rax = error ? -error : rval;
1491	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(RAX * 4), rax) < 0)
1492		return -1;
1493#else
1494#ifdef IA64
1495	if (ia32) {
1496		r8 = error ? -error : rval;
1497		if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R8), r8) < 0)
1498			return -1;
1499	}
1500	else {
1501		if (error) {
1502			r8 = error;
1503			r10 = -1;
1504		}
1505		else {
1506			r8 = rval;
1507			r10 = 0;
1508		}
1509		if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R8), r8) < 0 ||
1510		    ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R10), r10) < 0)
1511			return -1;
1512	}
1513#else /* !IA64 */
1514#ifdef MIPS
1515	if (error) {
1516		r2 = error;
1517		a3 = -1;
1518	}
1519	else {
1520		r2 = rval;
1521		a3 = 0;
1522	}
1523	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), a3) < 0 ||
1524	    ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), r2) < 0)
1525	    	return -1;
1526#else
1527#ifdef POWERPC
1528	if (upeek(tcp->pid, 4*PT_CCR, &flags) < 0)
1529		return -1;
1530	if (error) {
1531		flags |= SO_MASK;
1532		result = error;
1533	}
1534	else {
1535		flags &= ~SO_MASK;
1536		result = rval;
1537	}
1538	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_CCR), flags) < 0 ||
1539	    ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_R3), result) < 0)
1540		return -1;
1541#else /* !POWERPC */
1542#ifdef M68K
1543	d0 = error ? -error : rval;
1544	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_D0), d0) < 0)
1545		return -1;
1546#else /* !M68K */
1547#ifdef ARM
1548	r0 = error ? -error : rval;
1549	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*0), r0) < 0)
1550		return -1;
1551#else /* !ARM */
1552#ifdef ALPHA
1553	if (error) {
1554		a3 = -1;
1555		r0 = error;
1556	}
1557	else {
1558		a3 = 0;
1559		r0 = rval;
1560	}
1561	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), a3) < 0 ||
1562	    ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_R0), r0) < 0)
1563		return -1;
1564#else /* !ALPHA */
1565#ifdef SPARC
1566	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1567		return -1;
1568	if (error) {
1569		regs.r_psr |= PSR_C;
1570		regs.r_o0 = error;
1571	}
1572	else {
1573		regs.r_psr &= ~PSR_C;
1574		regs.r_o0 = rval;
1575	}
1576	if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0)
1577		return -1;
1578#else /* !SPARC */
1579#ifdef HPPA
1580	r28 = error ? -error : rval;
1581	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR28), r28) < 0)
1582		return -1;
1583#else
1584#ifdef SH
1585	r0 = error ? -error : rval;
1586	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*REG_REG0), r0) < 0)
1587		return -1;
1588#endif /* SH */
1589#endif /* HPPA */
1590#endif /* SPARC */
1591#endif /* ALPHA */
1592#endif /* ARM */
1593#endif /* M68K */
1594#endif /* POWERPC */
1595#endif /* MIPS */
1596#endif /* IA64 */
1597#endif /* X86_64 */
1598#endif /* I386 */
1599#endif /* S390 || S390X */
1600#endif /* LINUX */
1601#ifdef SUNOS4
1602	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)uoff(u_error),
1603		   error << 24) < 0 ||
1604	    ptrace(PTRACE_POKEUSER, tcp->pid, (char*)uoff(u_rval1), rval) < 0)
1605		return -1;
1606#endif /* SUNOS4 */
1607#ifdef SVR4
1608	/* XXX no clue */
1609	return -1;
1610#endif /* SVR4 */
1611#ifdef FREEBSD
1612	if (pread(tcp->pfd_reg, &regs, sizeof(regs), 0) < 0) {
1613	        perror("pread");
1614                return -1;
1615        }
1616	if (error) {
1617		regs.r_eflags |= PSL_C;
1618		regs.r_eax = error;
1619	}
1620	else {
1621		regs.r_eflags &= ~PSL_C;
1622		regs.r_eax = rval;
1623	}
1624	if (pwrite(tcp->pfd_reg, &regs, sizeof(regs), 0) < 0) {
1625	        perror("pwrite");
1626                return -1;
1627        }
1628#endif /* FREEBSD */
1629
1630	/* All branches reach here on success (only).  */
1631	tcp->u_error = error;
1632	tcp->u_rval = rval;
1633	return 0;
1634}
1635
1636int syscall_enter(tcp)
1637struct tcb *tcp;
1638{
1639#ifndef USE_PROCFS
1640	int pid = tcp->pid;
1641#endif /* !USE_PROCFS */
1642#ifdef LINUX
1643#if defined(S390) || defined(S390X)
1644	{
1645		int i;
1646		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1647			tcp->u_nargs = sysent[tcp->scno].nargs;
1648		else
1649     	        	tcp->u_nargs = MAX_ARGS;
1650		for (i = 0; i < tcp->u_nargs; i++) {
1651			if (upeek(pid,i==0 ? PT_ORIGGPR2:PT_GPR2+i*sizeof(long), &tcp->u_arg[i]) < 0)
1652				return -1;
1653		}
1654	}
1655#elif defined (ALPHA)
1656	{
1657		int i;
1658		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1659			tcp->u_nargs = sysent[tcp->scno].nargs;
1660		else
1661     	        	tcp->u_nargs = MAX_ARGS;
1662		for (i = 0; i < tcp->u_nargs; i++) {
1663			/* WTA: if scno is out-of-bounds this will bomb. Add range-check
1664			 * for scno somewhere above here!
1665			 */
1666			if (upeek(pid, REG_A0+i, &tcp->u_arg[i]) < 0)
1667				return -1;
1668		}
1669	}
1670#elif defined (IA64)
1671	{
1672		if (!ia32) {
1673			unsigned long *out0, *rbs_end, cfm, sof, sol, i;
1674			/* be backwards compatible with kernel < 2.4.4... */
1675#			ifndef PT_RBS_END
1676#			  define PT_RBS_END	PT_AR_BSP
1677#			endif
1678
1679			if (upeek(pid, PT_RBS_END, (long *) &rbs_end) < 0)
1680				return -1;
1681			if (upeek(pid, PT_CFM, (long *) &cfm) < 0)
1682				return -1;
1683
1684			sof = (cfm >> 0) & 0x7f;
1685			sol = (cfm >> 7) & 0x7f;
1686			out0 = ia64_rse_skip_regs(rbs_end, -sof + sol);
1687
1688			if (tcp->scno >= 0 && tcp->scno < nsyscalls
1689			    && sysent[tcp->scno].nargs != -1)
1690				tcp->u_nargs = sysent[tcp->scno].nargs;
1691			else
1692				tcp->u_nargs = MAX_ARGS;
1693			for (i = 0; i < tcp->u_nargs; ++i) {
1694				if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
1695					   sizeof(long), (char *) &tcp->u_arg[i]) < 0)
1696					return -1;
1697			}
1698		} else {
1699			int i;
1700
1701			if (/* EBX = out0 */
1702			    upeek(pid, PT_R11, (long *) &tcp->u_arg[0]) < 0
1703			    /* ECX = out1 */
1704			    || upeek(pid, PT_R9,  (long *) &tcp->u_arg[1]) < 0
1705			    /* EDX = out2 */
1706			    || upeek(pid, PT_R10, (long *) &tcp->u_arg[2]) < 0
1707			    /* ESI = out3 */
1708			    || upeek(pid, PT_R14, (long *) &tcp->u_arg[3]) < 0
1709			    /* EDI = out4 */
1710			    || upeek(pid, PT_R15, (long *) &tcp->u_arg[4]) < 0
1711			    /* EBP = out5 */
1712			    || upeek(pid, PT_R13, (long *) &tcp->u_arg[5]) < 0)
1713				return -1;
1714
1715			for (i = 0; i < 6; ++i)
1716				/* truncate away IVE sign-extension */
1717				tcp->u_arg[i] &= 0xffffffff;
1718
1719			if (tcp->scno >= 0 && tcp->scno < nsyscalls
1720			    && sysent[tcp->scno].nargs != -1)
1721				tcp->u_nargs = sysent[tcp->scno].nargs;
1722			else
1723				tcp->u_nargs = 5;
1724		}
1725	}
1726#elif defined (MIPS)
1727	{
1728	  	long sp;
1729	  	int i, nargs;
1730
1731		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1732			nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
1733		else
1734     	        	nargs = tcp->u_nargs = MAX_ARGS;
1735		if(nargs > 4) {
1736		  	if(upeek(pid, REG_SP, &sp) < 0)
1737			  	return -1;
1738			for(i = 0; i < 4; i++) {
1739			  	if (upeek(pid, REG_A0 + i, &tcp->u_arg[i])<0)
1740				  	return -1;
1741			}
1742			umoven(tcp, sp+16, (nargs-4) * sizeof(tcp->u_arg[0]),
1743			       (char *)(tcp->u_arg + 4));
1744		} else {
1745		  	for(i = 0; i < nargs; i++) {
1746			  	if (upeek(pid, REG_A0 + i, &tcp->u_arg[i]) < 0)
1747				  	return -1;
1748			}
1749		}
1750	}
1751#elif defined (POWERPC)
1752#ifndef PT_ORIG_R3
1753#define PT_ORIG_R3 34
1754#endif
1755	{
1756		int i;
1757		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1758			tcp->u_nargs = sysent[tcp->scno].nargs;
1759		else
1760     	        	tcp->u_nargs = MAX_ARGS;
1761		for (i = 0; i < tcp->u_nargs; i++) {
1762			if (upeek(pid, (i==0) ? (4*PT_ORIG_R3) : ((i+PT_R3)*4), &tcp->u_arg[i]) < 0)
1763				return -1;
1764		}
1765	}
1766#elif defined (SPARC)
1767	{
1768		int i;
1769
1770		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1771			tcp->u_nargs = sysent[tcp->scno].nargs;
1772		else
1773     	        	tcp->u_nargs = MAX_ARGS;
1774		for (i = 0; i < tcp->u_nargs; i++)
1775			tcp->u_arg[i] = *((&regs.r_o0) + i);
1776	}
1777#elif defined (HPPA)
1778	{
1779		int i;
1780
1781		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1782			tcp->u_nargs = sysent[tcp->scno].nargs;
1783		else
1784     	        	tcp->u_nargs = MAX_ARGS;
1785		for (i = 0; i < tcp->u_nargs; i++) {
1786			if (upeek(pid, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
1787				return -1;
1788		}
1789	}
1790#elif defined(SH)
1791       {
1792               int i;
1793               static int syscall_regs[] = {
1794                   REG_REG0+4, REG_REG0+5, REG_REG0+6, REG_REG0+7,
1795                   REG_REG0, REG_REG0+1, REG_REG0+2
1796                   };
1797
1798               tcp->u_nargs = sysent[tcp->scno].nargs;
1799               for (i = 0; i < tcp->u_nargs; i++) {
1800                       if (upeek(pid, 4*syscall_regs[i], &tcp->u_arg[i]) < 0)
1801                               return -1;
1802               }
1803        }
1804#elif defined(X86_64)
1805	{
1806		int i;
1807		static int argreg[SUPPORTED_PERSONALITIES][MAX_ARGS] = {
1808			{RDI,RSI,RDX,R10,R8,R9},	/* x86-64 ABI */
1809			{RBX,RCX,RDX,RDX,RSI,RDI,RBP}	/* i386 ABI */
1810		};
1811
1812		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1813			tcp->u_nargs = sysent[tcp->scno].nargs;
1814		else
1815     	        	tcp->u_nargs = MAX_ARGS;
1816		for (i = 0; i < tcp->u_nargs; i++) {
1817			if (upeek(pid, argreg[current_personality][i]*8, &tcp->u_arg[i]) < 0)
1818				return -1;
1819		}
1820	}
1821#else /* Other architecture (like i386) (32bits specific) */
1822	{
1823		int i;
1824		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1825			tcp->u_nargs = sysent[tcp->scno].nargs;
1826		else
1827     	        	tcp->u_nargs = MAX_ARGS;
1828		for (i = 0; i < tcp->u_nargs; i++) {
1829			if (upeek(pid, i*4, &tcp->u_arg[i]) < 0)
1830				return -1;
1831		}
1832	}
1833#endif
1834#endif /* LINUX */
1835#ifdef SUNOS4
1836	{
1837		int i;
1838		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1839			tcp->u_nargs = sysent[tcp->scno].nargs;
1840		else
1841     	        	tcp->u_nargs = MAX_ARGS;
1842		for (i = 0; i < tcp->u_nargs; i++) {
1843			struct user *u;
1844
1845			if (upeek(pid, uoff(u_arg[0]) +
1846			    (i*sizeof(u->u_arg[0])), &tcp->u_arg[i]) < 0)
1847				return -1;
1848		}
1849	}
1850#endif /* SUNOS4 */
1851#ifdef SVR4
1852#ifdef MIPS
1853	/*
1854	 * SGI is broken: even though it has pr_sysarg, it doesn't
1855	 * set them on system call entry.  Get a clue.
1856	 */
1857	if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1858		tcp->u_nargs = sysent[tcp->scno].nargs;
1859	else
1860		tcp->u_nargs = tcp->status.pr_nsysarg;
1861	if (tcp->u_nargs > 4) {
1862		memcpy(tcp->u_arg, &tcp->status.pr_reg[CTX_A0],
1863			4*sizeof(tcp->u_arg[0]));
1864		umoven(tcp, tcp->status.pr_reg[CTX_SP] + 16,
1865			(tcp->u_nargs - 4)*sizeof(tcp->u_arg[0]), (char *) (tcp->u_arg + 4));
1866	}
1867	else {
1868		memcpy(tcp->u_arg, &tcp->status.pr_reg[CTX_A0],
1869			tcp->u_nargs*sizeof(tcp->u_arg[0]));
1870	}
1871#elif UNIXWARE >= 2
1872	/*
1873	 * Like SGI, UnixWare doesn't set pr_sysarg until system call exit
1874	 */
1875	if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1876		tcp->u_nargs = sysent[tcp->scno].nargs;
1877	else
1878		tcp->u_nargs = tcp->status.pr_lwp.pr_nsysarg;
1879	umoven(tcp, tcp->status.PR_REG[UESP] + 4,
1880		tcp->u_nargs*sizeof(tcp->u_arg[0]), (char *) tcp->u_arg);
1881#elif defined (HAVE_PR_SYSCALL)
1882	if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1883		tcp->u_nargs = sysent[tcp->scno].nargs;
1884	else
1885		tcp->u_nargs = tcp->status.pr_nsysarg;
1886	{
1887		int i;
1888		for (i = 0; i < tcp->u_nargs; i++)
1889			tcp->u_arg[i] = tcp->status.pr_sysarg[i];
1890	}
1891#elif defined (I386)
1892	if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1893		tcp->u_nargs = sysent[tcp->scno].nargs;
1894	else
1895		tcp->u_nargs = 5;
1896	umoven(tcp, tcp->status.PR_REG[UESP] + 4,
1897		tcp->u_nargs*sizeof(tcp->u_arg[0]), (char *) tcp->u_arg);
1898#else
1899	I DONT KNOW WHAT TO DO
1900#endif /* !HAVE_PR_SYSCALL */
1901#endif /* SVR4 */
1902#ifdef FREEBSD
1903	if (tcp->scno >= 0 && tcp->scno < nsyscalls &&
1904	    sysent[tcp->scno].nargs > tcp->status.val)
1905		tcp->u_nargs = sysent[tcp->scno].nargs;
1906	else
1907	  	tcp->u_nargs = tcp->status.val;
1908	if (tcp->u_nargs < 0)
1909		tcp->u_nargs = 0;
1910	if (tcp->u_nargs > MAX_ARGS)
1911		tcp->u_nargs = MAX_ARGS;
1912	switch(regs.r_eax) {
1913	case SYS___syscall:
1914		pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
1915		      regs.r_esp + sizeof(int) + sizeof(quad_t));
1916	  break;
1917        case SYS_syscall:
1918		pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
1919		      regs.r_esp + 2 * sizeof(int));
1920	  break;
1921        default:
1922		pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
1923		      regs.r_esp + sizeof(int));
1924	  break;
1925	}
1926#endif /* FREEBSD */
1927	return 1;
1928}
1929
1930int
1931trace_syscall(tcp)
1932struct tcb *tcp;
1933{
1934	int sys_res;
1935	struct timeval tv;
1936	int res;
1937
1938	/* Measure the exit time as early as possible to avoid errors. */
1939	if (dtime && (tcp->flags & TCB_INSYSCALL))
1940		gettimeofday(&tv, NULL);
1941
1942	res = get_scno(tcp);
1943	if (res != 1)
1944		return res;
1945
1946	res = syscall_fixup(tcp);
1947	if (res != 1)
1948		return res;
1949
1950	if (tcp->flags & TCB_INSYSCALL) {
1951		long u_error;
1952		res = get_error(tcp);
1953		if (res != 1)
1954			return res;
1955
1956		internal_syscall(tcp);
1957		if (tcp->scno >= 0 && tcp->scno < nsyscalls &&
1958		    !(qual_flags[tcp->scno] & QUAL_TRACE)) {
1959			tcp->flags &= ~TCB_INSYSCALL;
1960			return 0;
1961		}
1962
1963		if (tcp->flags & TCB_REPRINT) {
1964			printleader(tcp);
1965			tprintf("<... ");
1966			if (tcp->scno >= nsyscalls || tcp->scno < 0)
1967				tprintf("syscall_%lu", tcp->scno);
1968			else
1969				tprintf("%s", sysent[tcp->scno].sys_name);
1970			tprintf(" resumed> ");
1971		}
1972
1973		if (cflag && tcp->scno < nsyscalls && tcp->scno >= 0) {
1974			call_count[tcp->scno]++;
1975			if (tcp->u_error)
1976				error_count[tcp->scno]++;
1977			tv_sub(&tv, &tv, &tcp->etime);
1978#ifdef LINUX
1979			if (tv_cmp(&tv, &tcp->dtime) > 0) {
1980				static struct timeval one_tick =
1981					{ 0, 1000000 / HZ };
1982
1983				if (tv_nz(&tcp->dtime))
1984					tv = tcp->dtime;
1985				else if (tv_cmp(&tv, &one_tick) > 0) {
1986					if (tv_cmp(&shortest, &one_tick) < 0)
1987						tv = shortest;
1988					else
1989						tv = one_tick;
1990				}
1991			}
1992#endif /* LINUX */
1993			if (tv_cmp(&tv, &shortest) < 0)
1994				shortest = tv;
1995			tv_add(&tv_count[tcp->scno],
1996				&tv_count[tcp->scno], &tv);
1997			tcp->flags &= ~TCB_INSYSCALL;
1998			return 0;
1999		}
2000
2001		if (tcp->scno >= nsyscalls || tcp->scno < 0
2002		    || (qual_flags[tcp->scno] & QUAL_RAW))
2003			sys_res = printargs(tcp);
2004		else {
2005			if (not_failing_only && tcp->u_error)
2006				return 0;	/* ignore failed syscalls */
2007			sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2008		}
2009		u_error = tcp->u_error;
2010		tprintf(") ");
2011		tabto(acolumn);
2012		if (tcp->scno >= nsyscalls || tcp->scno < 0 ||
2013		    qual_flags[tcp->scno] & QUAL_RAW) {
2014			if (u_error)
2015				tprintf("= -1 (errno %ld)", u_error);
2016			else
2017				tprintf("= %#lx", tcp->u_rval);
2018		}
2019		else if (!(sys_res & RVAL_NONE) && u_error) {
2020			switch (u_error) {
2021#ifdef LINUX
2022			case ERESTARTSYS:
2023				tprintf("= ? ERESTARTSYS (To be restarted)");
2024				break;
2025			case ERESTARTNOINTR:
2026				tprintf("= ? ERESTARTNOINTR (To be restarted)");
2027				break;
2028			case ERESTARTNOHAND:
2029				tprintf("= ? ERESTARTNOHAND (To be restarted)");
2030				break;
2031#endif /* LINUX */
2032			default:
2033				tprintf("= -1 ");
2034				if (u_error < 0)
2035					tprintf("E??? (errno %ld)", u_error);
2036				else if (u_error < nerrnos)
2037					tprintf("%s (%s)", errnoent[u_error],
2038						strerror(u_error));
2039				else
2040					tprintf("ERRNO_%ld (%s)", u_error,
2041						strerror(u_error));
2042				break;
2043			}
2044		}
2045		else {
2046			if (sys_res & RVAL_NONE)
2047				tprintf("= ?");
2048			else {
2049				switch (sys_res & RVAL_MASK) {
2050				case RVAL_HEX:
2051					tprintf("= %#lx", tcp->u_rval);
2052					break;
2053				case RVAL_OCTAL:
2054					tprintf("= %#lo", tcp->u_rval);
2055					break;
2056				case RVAL_UDECIMAL:
2057					tprintf("= %lu", tcp->u_rval);
2058					break;
2059				case RVAL_DECIMAL:
2060					tprintf("= %ld", tcp->u_rval);
2061					break;
2062#ifdef HAVE_LONG_LONG
2063				case RVAL_LHEX:
2064					tprintf("= %#llx", tcp->u_lrval);
2065					break;
2066				case RVAL_LOCTAL:
2067					tprintf("= %#llo", tcp->u_lrval);
2068					break;
2069				case RVAL_LUDECIMAL:
2070					tprintf("= %llu", tcp->u_lrval);
2071					break;
2072				case RVAL_LDECIMAL:
2073					tprintf("= %lld", tcp->u_lrval);
2074					break;
2075#endif
2076				default:
2077					fprintf(stderr,
2078						"invalid rval format\n");
2079					break;
2080				}
2081			}
2082			if ((sys_res & RVAL_STR) && tcp->auxstr)
2083				tprintf(" (%s)", tcp->auxstr);
2084		}
2085		if (dtime) {
2086			tv_sub(&tv, &tv, &tcp->etime);
2087			tprintf(" <%ld.%06ld>",
2088				(long) tv.tv_sec, (long) tv.tv_usec);
2089		}
2090		printtrailer(tcp);
2091
2092		dumpio(tcp);
2093		if (fflush(tcp->outf) == EOF)
2094			return -1;
2095		tcp->flags &= ~TCB_INSYSCALL;
2096		return 0;
2097	}
2098
2099	/* Entering system call */
2100	res = syscall_enter(tcp);
2101	if (res != 1)
2102		return res;
2103
2104	switch (tcp->scno + NR_SYSCALL_BASE) {
2105#ifdef LINUX
2106#if !defined (ALPHA) && !defined(SPARC) && !defined(MIPS) && !defined(HPPA) && !defined(X86_64)
2107	case SYS_socketcall:
2108		decode_subcall(tcp, SYS_socket_subcall,
2109			SYS_socket_nsubcalls, deref_style);
2110		break;
2111	case SYS_ipc:
2112		decode_subcall(tcp, SYS_ipc_subcall,
2113			SYS_ipc_nsubcalls, shift_style);
2114		break;
2115#endif /* !ALPHA && !MIPS && !SPARC && !HPPA && !X86_64 */
2116#ifdef SPARC
2117	case SYS_socketcall:
2118		sparc_socket_decode (tcp);
2119		break;
2120#endif
2121#endif /* LINUX */
2122#ifdef SVR4
2123#ifdef SYS_pgrpsys_subcall
2124	case SYS_pgrpsys:
2125		decode_subcall(tcp, SYS_pgrpsys_subcall,
2126			SYS_pgrpsys_nsubcalls, shift_style);
2127		break;
2128#endif /* SYS_pgrpsys_subcall */
2129#ifdef SYS_sigcall_subcall
2130	case SYS_sigcall:
2131		decode_subcall(tcp, SYS_sigcall_subcall,
2132			SYS_sigcall_nsubcalls, mask_style);
2133		break;
2134#endif /* SYS_sigcall_subcall */
2135	case SYS_msgsys:
2136		decode_subcall(tcp, SYS_msgsys_subcall,
2137			SYS_msgsys_nsubcalls, shift_style);
2138		break;
2139	case SYS_shmsys:
2140		decode_subcall(tcp, SYS_shmsys_subcall,
2141			SYS_shmsys_nsubcalls, shift_style);
2142		break;
2143	case SYS_semsys:
2144		decode_subcall(tcp, SYS_semsys_subcall,
2145			SYS_semsys_nsubcalls, shift_style);
2146		break;
2147#if 0 /* broken */
2148	case SYS_utssys:
2149		decode_subcall(tcp, SYS_utssys_subcall,
2150			SYS_utssys_nsubcalls, shift_style);
2151		break;
2152#endif
2153	case SYS_sysfs:
2154		decode_subcall(tcp, SYS_sysfs_subcall,
2155			SYS_sysfs_nsubcalls, shift_style);
2156		break;
2157	case SYS_spcall:
2158		decode_subcall(tcp, SYS_spcall_subcall,
2159			SYS_spcall_nsubcalls, shift_style);
2160		break;
2161#ifdef SYS_context_subcall
2162	case SYS_context:
2163		decode_subcall(tcp, SYS_context_subcall,
2164			SYS_context_nsubcalls, shift_style);
2165		break;
2166#endif /* SYS_context_subcall */
2167#ifdef SYS_door_subcall
2168	case SYS_door:
2169		decode_subcall(tcp, SYS_door_subcall,
2170			SYS_door_nsubcalls, door_style);
2171		break;
2172#endif /* SYS_door_subcall */
2173#ifdef SYS_kaio_subcall
2174	case SYS_kaio:
2175		decode_subcall(tcp, SYS_kaio_subcall,
2176			SYS_kaio_nsubcalls, shift_style);
2177		break;
2178#endif
2179#endif /* SVR4 */
2180#ifdef FREEBSD
2181	case SYS_msgsys:
2182	case SYS_shmsys:
2183	case SYS_semsys:
2184		decode_subcall(tcp, 0, 0, table_style);
2185		break;
2186#endif
2187#ifdef SUNOS4
2188	case SYS_semsys:
2189		decode_subcall(tcp, SYS_semsys_subcall,
2190			SYS_semsys_nsubcalls, shift_style);
2191		break;
2192	case SYS_msgsys:
2193		decode_subcall(tcp, SYS_msgsys_subcall,
2194			SYS_msgsys_nsubcalls, shift_style);
2195		break;
2196	case SYS_shmsys:
2197		decode_subcall(tcp, SYS_shmsys_subcall,
2198			SYS_shmsys_nsubcalls, shift_style);
2199		break;
2200#endif
2201	}
2202
2203	internal_syscall(tcp);
2204	if (tcp->scno >=0 && tcp->scno < nsyscalls && !(qual_flags[tcp->scno] & QUAL_TRACE)) {
2205		tcp->flags |= TCB_INSYSCALL;
2206		return 0;
2207	}
2208
2209	if (cflag) {
2210		gettimeofday(&tcp->etime, NULL);
2211		tcp->flags |= TCB_INSYSCALL;
2212		return 0;
2213	}
2214
2215	printleader(tcp);
2216	tcp->flags &= ~TCB_REPRINT;
2217	tcp_last = tcp;
2218	if (tcp->scno >= nsyscalls || tcp->scno < 0)
2219		tprintf("syscall_%lu(", tcp->scno);
2220	else
2221		tprintf("%s(", sysent[tcp->scno].sys_name);
2222	if (tcp->scno >= nsyscalls || tcp->scno < 0 ||
2223	    ((qual_flags[tcp->scno] & QUAL_RAW) && tcp->scno != SYS_exit))
2224		sys_res = printargs(tcp);
2225	else
2226		sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2227	if (fflush(tcp->outf) == EOF)
2228		return -1;
2229	tcp->flags |= TCB_INSYSCALL;
2230	/* Measure the entrance time as late as possible to avoid errors. */
2231	if (dtime)
2232		gettimeofday(&tcp->etime, NULL);
2233	return sys_res;
2234}
2235
2236int
2237printargs(tcp)
2238struct tcb *tcp;
2239{
2240	if (entering(tcp)) {
2241		int i;
2242
2243		for (i = 0; i < tcp->u_nargs; i++)
2244			tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
2245	}
2246	return 0;
2247}
2248
2249long
2250getrval2(tcp)
2251struct tcb *tcp;
2252{
2253	long val = -1;
2254
2255#ifdef LINUX
2256#ifdef SPARC
2257	struct regs regs;
2258	if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
2259		return -1;
2260	val = regs.r_o1;
2261#endif /* SPARC */
2262#endif /* LINUX */
2263
2264#ifdef SUNOS4
2265	if (upeek(tcp->pid, uoff(u_rval2), &val) < 0)
2266		return -1;
2267#endif /* SUNOS4 */
2268
2269#ifdef SVR4
2270#ifdef SPARC
2271	val = tcp->status.PR_REG[R_O1];
2272#endif /* SPARC */
2273#ifdef I386
2274	val = tcp->status.PR_REG[EDX];
2275#endif /* I386 */
2276#ifdef X86_64
2277	val = tcp->status.PR_REG[RDX];
2278#endif /* X86_64 */
2279#ifdef MIPS
2280	val = tcp->status.PR_REG[CTX_V1];
2281#endif /* MIPS */
2282#endif /* SVR4 */
2283#ifdef FREEBSD
2284	struct reg regs;
2285	pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
2286	val = regs.r_edx;
2287#endif
2288	return val;
2289}
2290
2291/*
2292 * Apparently, indirect system calls have already be converted by ptrace(2),
2293 * so if you see "indir" this program has gone astray.
2294 */
2295int
2296sys_indir(tcp)
2297struct tcb *tcp;
2298{
2299	int i, scno, nargs;
2300
2301	if (entering(tcp)) {
2302		if ((scno = tcp->u_arg[0]) > nsyscalls) {
2303			fprintf(stderr, "Bogus syscall: %u\n", scno);
2304			return 0;
2305		}
2306		nargs = sysent[scno].nargs;
2307		tprintf("%s", sysent[scno].sys_name);
2308		for (i = 0; i < nargs; i++)
2309			tprintf(", %#lx", tcp->u_arg[i+1]);
2310	}
2311	return 0;
2312}
2313
2314static int
2315time_cmp(a, b)
2316void *a;
2317void *b;
2318{
2319	return -tv_cmp(&tv_count[*((int *) a)], &tv_count[*((int *) b)]);
2320}
2321
2322static int
2323syscall_cmp(a, b)
2324void *a;
2325void *b;
2326{
2327	return strcmp(sysent[*((int *) a)].sys_name,
2328		sysent[*((int *) b)].sys_name);
2329}
2330
2331static int
2332count_cmp(a, b)
2333void *a;
2334void *b;
2335{
2336	int m = call_count[*((int *) a)], n = call_count[*((int *) b)];
2337
2338	return (m < n) ? 1 : (m > n) ? -1 : 0;
2339}
2340
2341static int (*sortfun)();
2342static struct timeval overhead = { -1, -1 };
2343
2344void
2345set_sortby(sortby)
2346char *sortby;
2347{
2348	if (strcmp(sortby, "time") == 0)
2349		sortfun = time_cmp;
2350	else if (strcmp(sortby, "calls") == 0)
2351		sortfun = count_cmp;
2352	else if (strcmp(sortby, "name") == 0)
2353		sortfun = syscall_cmp;
2354	else if (strcmp(sortby, "nothing") == 0)
2355		sortfun = NULL;
2356	else {
2357		fprintf(stderr, "invalid sortby: `%s'\n", sortby);
2358		exit(1);
2359	}
2360}
2361
2362void set_overhead(n)
2363int n;
2364{
2365	overhead.tv_sec = n / 1000000;
2366	overhead.tv_usec = n % 1000000;
2367}
2368
2369void
2370call_summary(outf)
2371FILE *outf;
2372{
2373	int i, j;
2374	int call_cum, error_cum;
2375	struct timeval tv_cum, dtv;
2376	double percent;
2377	char *dashes = "-------------------------";
2378	char error_str[16];
2379
2380	call_cum = error_cum = tv_cum.tv_sec = tv_cum.tv_usec = 0;
2381	if (overhead.tv_sec == -1) {
2382		tv_mul(&overhead, &shortest, 8);
2383		tv_div(&overhead, &overhead, 10);
2384	}
2385	for (i = 0; i < nsyscalls; i++) {
2386		sorted_count[i] = i;
2387		if (call_count[i] == 0)
2388			continue;
2389		tv_mul(&dtv, &overhead, call_count[i]);
2390		tv_sub(&tv_count[i], &tv_count[i], &dtv);
2391		call_cum += call_count[i];
2392		error_cum += error_count[i];
2393		tv_add(&tv_cum, &tv_cum, &tv_count[i]);
2394	}
2395	if (sortfun)
2396		qsort((void *) sorted_count, nsyscalls, sizeof(int), sortfun);
2397	fprintf(outf, "%6.6s %11.11s %11.11s %9.9s %9.9s %s\n",
2398		"% time", "seconds", "usecs/call",
2399		"calls", "errors", "syscall");
2400	fprintf(outf, "%6.6s %11.11s %11.11s %9.9s %9.9s %-16.16s\n",
2401		dashes, dashes, dashes, dashes, dashes, dashes);
2402	for (i = 0; i < nsyscalls; i++) {
2403		j = sorted_count[i];
2404		if (call_count[j] == 0)
2405			continue;
2406		tv_div(&dtv, &tv_count[j], call_count[j]);
2407		if (error_count[j])
2408			sprintf(error_str, "%d", error_count[j]);
2409		else
2410			error_str[0] = '\0';
2411		percent = 100.0*tv_float(&tv_count[j])/tv_float(&tv_cum);
2412		fprintf(outf, "%6.2f %4ld.%06ld %11ld %9d %9.9s %s\n",
2413			percent, (long) tv_count[j].tv_sec,
2414			(long) tv_count[j].tv_usec,
2415			(long) 1000000 * dtv.tv_sec + dtv.tv_usec,
2416			call_count[j], error_str, sysent[j].sys_name);
2417	}
2418	fprintf(outf, "%6.6s %11.11s %11.11s %9.9s %9.9s %-16.16s\n",
2419		dashes, dashes, dashes, dashes, dashes, dashes);
2420	if (error_cum)
2421		sprintf(error_str, "%d", error_cum);
2422	else
2423		error_str[0] = '\0';
2424	fprintf(outf, "%6.6s %4ld.%06ld %11.11s %9d %9.9s %s\n",
2425		"100.00", (long) tv_cum.tv_sec, (long) tv_cum.tv_usec, "",
2426		call_cum, error_str, "total");
2427}
2428