syscall.c revision eb285359906700f46b22cf4f9911695034313736
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#ifdef __NR_exit_group
674	case __NR_exit_group:
675#endif
676		internal_exit(tcp);
677		break;
678	}
679	return 0;
680}
681
682
683#ifdef LINUX
684#if defined (I386)
685	static long eax;
686#elif defined (IA64)
687	long r8, r10, psr;
688	long ia32 = 0;
689#elif defined (POWERPC)
690	static long result,flags;
691#elif defined (M68K)
692	static int d0;
693#elif defined (ARM)
694	static int r0;
695#elif defined (ALPHA)
696	static long r0;
697	static long a3;
698#elif defined (SPARC)
699	static struct regs regs;
700	static unsigned long trap;
701#elif defined(MIPS)
702	static long a3;
703	static long r2;
704#elif defined(S390) || defined(S390X)
705	static long gpr2;
706	static long pc;
707	static long syscall_mode;
708#elif defined(HPPA)
709	static long r28;
710#elif defined(SH)
711       static long r0;
712#elif defined(X86_64)
713       static long rax;
714#endif
715#endif /* LINUX */
716#ifdef FREEBSD
717	struct reg regs;
718#endif /* FREEBSD */
719
720int
721get_scno(tcp)
722struct tcb *tcp;
723{
724	long scno = 0;
725#ifndef USE_PROCFS
726	int pid = tcp->pid;
727#endif /* !PROCFS */
728
729#ifdef LINUX
730#if defined(S390) || defined(S390X)
731	if (upeek(pid, PT_GPR2, &syscall_mode) < 0)
732		return -1;
733	if (syscall_mode != -ENOSYS){
734		/*
735		 * Since kernel version 2.5.44 the scno gets passed in gpr2.
736		 */
737		scno = syscall_mode;
738	}
739	else {
740	       	/*
741		 * Old style of "passing" the scno via the SVC instruction.
742		 */
743
744		long opcode, offset_reg, tmp;
745		void * svc_addr;
746		int gpr_offset[16] = {PT_GPR0,  PT_GPR1,  PT_ORIGGPR2, PT_GPR3,
747				      PT_GPR4,  PT_GPR5,  PT_GPR6,     PT_GPR7,
748				      PT_GPR8,  PT_GPR9,  PT_GPR10,    PT_GPR11,
749				      PT_GPR12, PT_GPR13, PT_GPR14,    PT_GPR15};
750
751		if (upeek(pid, PT_PSWADDR, &pc) < 0)
752			return -1;
753		opcode = ptrace(PTRACE_PEEKTEXT, pid, (char *)(pc-sizeof(long)), 0);
754		if (errno)
755			return -1;
756
757		/*
758		 *  We have to check if the SVC got executed directly or via an
759		 *  EXECUTE instruction. In case of EXECUTE it is necessary to do
760		 *  instruction decoding to derive the system call number.
761		 *  Unfortunately the opcode sizes of EXECUTE and SVC are differently,
762		 *  so that this doesn't work if a SVC opcode is part of an EXECUTE
763		 *  opcode. Since there is no way to find out the opcode size this
764		 *  is the best we can do...
765		 */
766
767		if ((opcode & 0xff00) == 0x0a00) {
768			/* SVC opcode */
769			scno = opcode & 0xff;
770		}
771		else {
772			/* SVC got executed by EXECUTE instruction */
773
774			/*
775			 *  Do instruction decoding of EXECUTE. If you really want to
776			 *  understand this, read the Principles of Operations.
777			 */
778			svc_addr = (void *) (opcode & 0xfff);
779
780			tmp = 0;
781			offset_reg = (opcode & 0x000f0000) >> 16;
782			if (offset_reg && (upeek(pid, gpr_offset[offset_reg], &tmp) < 0))
783				return -1;
784			svc_addr += tmp;
785
786			tmp = 0;
787			offset_reg = (opcode & 0x0000f000) >> 12;
788			if (offset_reg && (upeek(pid, gpr_offset[offset_reg], &tmp) < 0))
789				return -1;
790			svc_addr += tmp;
791
792			scno = ptrace(PTRACE_PEEKTEXT, pid, svc_addr, 0);
793			if (errno)
794				return -1;
795#if defined(S390X)
796			scno >>= 48;
797#else
798			scno >>= 16;
799#endif
800			tmp = 0;
801			offset_reg = (opcode & 0x00f00000) >> 20;
802			if (offset_reg && (upeek(pid, gpr_offset[offset_reg], &tmp) < 0))
803				return -1;
804
805			scno = (scno | tmp) & 0xff;
806		}
807	}
808#elif defined (POWERPC)
809	if (upeek(pid, sizeof(unsigned long)*PT_R0, &scno) < 0)
810		return -1;
811	if (!(tcp->flags & TCB_INSYSCALL)) {
812		/* Check if we return from execve. */
813		if (scno == 0 && (tcp->flags & TCB_WAITEXECVE)) {
814			tcp->flags &= ~TCB_WAITEXECVE;
815			return 0;
816		}
817	}
818#elif defined (I386)
819	if (upeek(pid, 4*ORIG_EAX, &scno) < 0)
820		return -1;
821#elif defined (X86_64)
822	if (upeek(pid, 8*ORIG_RAX, &scno) < 0)
823		return -1;
824
825	if (!(tcp->flags & TCB_INSYSCALL)) {
826	  	static int currpers=-1;
827		long val;
828
829		/* Check CS register value. On x86-64 linux it is:
830		 * 	0x33	for long mode (64 bit)
831		 * 	0x23	for compatibility mode (32 bit)
832		 * It takes only one ptrace and thus doesn't need
833		 * to be cached.
834		 */
835		if (upeek(pid, 8*CS, &val) < 0)
836			return -1;
837		switch(val)
838		{
839			case 0x23: currpers = 1; break;
840			case 0x33: currpers = 0; break;
841			default:
842				fprintf(stderr, "Unknown value CS=0x%02X while "
843					 "detecting personality of process "
844					 "PID=%d\n", (int)val, pid);
845				currpers = current_personality;
846				break;
847		}
848#if 0
849		/* This version analyzes the opcode of a syscall instruction.
850		 * (int 0x80 on i386 vs. syscall on x86-64)
851		 * It works, but is too complicated.
852		 */
853		unsigned long val, rip, i;
854
855		if(upeek(pid, 8*RIP, &rip)<0)
856			perror("upeek(RIP)");
857
858		/* sizeof(syscall) == sizeof(int 0x80) == 2 */
859		rip-=2;
860		errno = 0;
861
862		call = ptrace(PTRACE_PEEKTEXT,pid,(char *)rip,0);
863		if (errno)
864			printf("ptrace_peektext failed: %s\n",
865					strerror(errno));
866		switch (call & 0xffff)
867		{
868			/* x86-64: syscall = 0x0f 0x05 */
869			case 0x050f: currpers = 0; break;
870			/* i386: int 0x80 = 0xcd 0x80 */
871			case 0x80cd: currpers = 1; break;
872			default:
873				currpers = current_personality;
874				fprintf(stderr,
875					"Unknown syscall opcode (0x%04X) while "
876					"detecting personality of process "
877					"PID=%d\n", (int)call, pid);
878				break;
879		}
880#endif
881		if(currpers != current_personality)
882		{
883			char *names[]={"64 bit", "32 bit"};
884			set_personality(currpers);
885			printf("[ Process PID=%d runs in %s mode. ]\n",
886					pid, names[current_personality]);
887		}
888	}
889#elif defined(IA64)
890#	define IA64_PSR_IS	((long)1 << 34)
891	if (upeek (pid, PT_CR_IPSR, &psr) >= 0)
892		ia32 = (psr & IA64_PSR_IS) != 0;
893	if (!(tcp->flags & TCB_INSYSCALL)) {
894		if (ia32) {
895			if (upeek(pid, PT_R1, &scno) < 0)	/* orig eax */
896				return -1;
897			/* Check if we return from execve. */
898		} else {
899			if (upeek (pid, PT_R15, &scno) < 0)
900				return -1;
901		}
902	} else {
903		/* syscall in progress */
904		if (upeek (pid, PT_R8, &r8) < 0)
905			return -1;
906		if (upeek (pid, PT_R10, &r10) < 0)
907			return -1;
908	}
909	if (tcp->flags & TCB_WAITEXECVE) {
910		tcp->flags &= ~TCB_WAITEXECVE;
911		return 0;
912	}
913
914#elif defined (ARM)
915	{
916	    long pc;
917	    upeek(pid, 4*15, &pc);
918	    umoven(tcp, pc-4, 4, (char *)&scno);
919	    scno &= 0x000fffff;
920	}
921#elif defined (M68K)
922	if (upeek(pid, 4*PT_ORIG_D0, &scno) < 0)
923		return -1;
924#elif defined (MIPS)
925	if (upeek(pid, REG_A3, &a3) < 0)
926	  	return -1;
927
928	if(!(tcp->flags & TCB_INSYSCALL)) {
929	  	if (upeek(pid, REG_V0, &scno) < 0)
930		  	return -1;
931
932		if (scno < 0 || scno > nsyscalls) {
933			if(a3 == 0 || a3 == -1) {
934				if(debug)
935					fprintf (stderr, "stray syscall exit: v0 = %ld\n", scno);
936				return 0;
937			}
938		}
939	} else {
940	  	if (upeek(pid, REG_V0, &r2) < 0)
941	    		return -1;
942	}
943#elif defined (ALPHA)
944	if (upeek(pid, REG_A3, &a3) < 0)
945		return -1;
946
947	if (!(tcp->flags & TCB_INSYSCALL)) {
948		if (upeek(pid, REG_R0, &scno) < 0)
949			return -1;
950
951		/* Check if we return from execve. */
952		if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
953			tcp->flags &= ~TCB_WAITEXECVE;
954			return 0;
955		}
956
957		/*
958		 * Do some sanity checks to figure out if it's
959		 * really a syscall entry
960		 */
961		if (scno < 0 || scno > nsyscalls) {
962			if (a3 == 0 || a3 == -1) {
963				if (debug)
964					fprintf (stderr, "stray syscall exit: r0 = %ld\n", scno);
965				return 0;
966			}
967		}
968	}
969	else {
970		if (upeek(pid, REG_R0, &r0) < 0)
971			return -1;
972	}
973#elif defined (SPARC)
974	/* Everything we need is in the current register set. */
975	if (ptrace(PTRACE_GETREGS,pid,(char *)&regs,0) < 0)
976		return -1;
977
978        /* If we are entering, then disassemble the syscall trap. */
979	if (!(tcp->flags & TCB_INSYSCALL)) {
980		/* Retrieve the syscall trap instruction. */
981		errno = 0;
982		trap = ptrace(PTRACE_PEEKTEXT,pid,(char *)regs.r_pc,0);
983		if (errno)
984			return -1;
985
986		/* Disassemble the trap to see what personality to use. */
987		switch (trap) {
988		case 0x91d02010:
989			/* Linux/SPARC syscall trap. */
990			set_personality(0);
991			break;
992		case 0x91d0206d:
993			/* Linux/SPARC64 syscall trap. */
994			fprintf(stderr,"syscall: Linux/SPARC64 not supported yet\n");
995			return -1;
996		case 0x91d02000:
997			/* SunOS syscall trap. (pers 1) */
998			fprintf(stderr,"syscall: SunOS no support\n");
999			return -1;
1000		case 0x91d02008:
1001			/* Solaris 2.x syscall trap. (per 2) */
1002			set_personality(1);
1003			break;
1004		case 0x91d02009:
1005			/* NetBSD/FreeBSD syscall trap. */
1006			fprintf(stderr,"syscall: NetBSD/FreeBSD not supported\n");
1007			return -1;
1008		case 0x91d02027:
1009			/* Solaris 2.x gettimeofday */
1010			set_personality(1);
1011			break;
1012		default:
1013			/* Unknown syscall trap. */
1014			if(tcp->flags & TCB_WAITEXECVE) {
1015				tcp->flags &= ~TCB_WAITEXECVE;
1016				return 0;
1017			}
1018			fprintf(stderr,"syscall: unknown syscall trap %08x %08x\n", trap, regs.r_pc);
1019			return -1;
1020		}
1021
1022		/* Extract the system call number from the registers. */
1023		if (trap == 0x91d02027)
1024			scno = 156;
1025		else
1026			scno = regs.r_g1;
1027		if (scno == 0) {
1028			scno = regs.r_o0;
1029			memmove (&regs.r_o0, &regs.r_o1, 7*sizeof(regs.r_o0));
1030		}
1031	}
1032#elif defined(HPPA)
1033	if (upeek(pid, PT_GR20, &scno) < 0)
1034		return -1;
1035	if (!(tcp->flags & TCB_INSYSCALL)) {
1036		/* Check if we return from execve. */
1037		if ((tcp->flags & TCB_WAITEXECVE)) {
1038			tcp->flags &= ~TCB_WAITEXECVE;
1039			return 0;
1040		}
1041	}
1042#elif defined(SH)
1043       /*
1044        * In the new syscall ABI, the system call number is in R3.
1045        */
1046       if (upeek(pid, 4*(REG_REG0+3), &scno) < 0)
1047               return -1;
1048
1049       if (scno < 0) {
1050           /* Odd as it may seem, a glibc bug has been known to cause
1051              glibc to issue bogus negative syscall numbers.  So for
1052              our purposes, make strace print what it *should* have been */
1053           long correct_scno = (scno & 0xff);
1054           if (debug)
1055               fprintf(stderr,
1056                   "Detected glibc bug: bogus system call number = %ld, "
1057		   "correcting to %ld\n",
1058                   scno,
1059                   correct_scno);
1060           scno = correct_scno;
1061       }
1062
1063
1064       if (!(tcp->flags & TCB_INSYSCALL)) {
1065               /* Check if we return from execve. */
1066               if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1067                       tcp->flags &= ~TCB_WAITEXECVE;
1068                       return 0;
1069               }
1070       }
1071#endif /* SH */
1072#endif /* LINUX */
1073#ifdef SUNOS4
1074	if (upeek(pid, uoff(u_arg[7]), &scno) < 0)
1075		return -1;
1076#elif defined(SH)
1077       /* new syscall ABI returns result in R0 */
1078       if (upeek(pid, 4*REG_REG0, (long *)&r0) < 0)
1079               return -1;
1080#endif
1081#ifdef USE_PROCFS
1082#ifdef HAVE_PR_SYSCALL
1083	scno = tcp->status.PR_SYSCALL;
1084#else /* !HAVE_PR_SYSCALL */
1085#ifndef FREEBSD
1086	scno = tcp->status.PR_WHAT;
1087#else /* FREEBSD */
1088	if (pread(tcp->pfd_reg, &regs, sizeof(regs), 0) < 0) {
1089	        perror("pread");
1090                return -1;
1091        }
1092	switch (regs.r_eax) {
1093	case SYS_syscall:
1094	case SYS___syscall:
1095    	        pread(tcp->pfd, &scno, sizeof(scno), regs.r_esp + sizeof(int));
1096	        break;
1097	default:
1098	        scno = regs.r_eax;
1099	        break;
1100	}
1101#endif /* FREEBSD */
1102#endif /* !HAVE_PR_SYSCALL */
1103#endif /* USE_PROCFS */
1104	if (!(tcp->flags & TCB_INSYSCALL))
1105		tcp->scno = scno;
1106	return 1;
1107}
1108
1109
1110int
1111syscall_fixup(tcp)
1112struct tcb *tcp;
1113{
1114#ifndef USE_PROCFS
1115	int pid = tcp->pid;
1116#else /* USE_PROCFS */
1117	int scno = tcp->scno;
1118
1119	if (!(tcp->flags & TCB_INSYSCALL)) {
1120		if (tcp->status.PR_WHY != PR_SYSENTRY) {
1121			if (
1122			    scno == SYS_fork
1123#ifdef SYS_vfork
1124			    || scno == SYS_vfork
1125#endif /* SYS_vfork */
1126#ifdef SYS_fork1
1127			    || scno == SYS_fork1
1128#endif /* SYS_fork1 */
1129#ifdef SYS_forkall
1130			    || scno == SYS_forkall
1131#endif /* SYS_forkall */
1132#ifdef SYS_rfork1
1133			    || scno == SYS_rfork1
1134#endif /* SYS_fork1 */
1135#ifdef SYS_rforkall
1136			    || scno == SYS_rforkall
1137#endif /* SYS_rforkall */
1138			    ) {
1139				/* We are returning in the child, fake it. */
1140				tcp->status.PR_WHY = PR_SYSENTRY;
1141				trace_syscall(tcp);
1142				tcp->status.PR_WHY = PR_SYSEXIT;
1143			}
1144			else {
1145				fprintf(stderr, "syscall: missing entry\n");
1146				tcp->flags |= TCB_INSYSCALL;
1147			}
1148		}
1149	}
1150	else {
1151		if (tcp->status.PR_WHY != PR_SYSEXIT) {
1152			fprintf(stderr, "syscall: missing exit\n");
1153			tcp->flags &= ~TCB_INSYSCALL;
1154		}
1155	}
1156#endif /* USE_PROCFS */
1157#ifdef SUNOS4
1158	if (!(tcp->flags & TCB_INSYSCALL)) {
1159		if (scno == 0) {
1160			fprintf(stderr, "syscall: missing entry\n");
1161			tcp->flags |= TCB_INSYSCALL;
1162		}
1163	}
1164	else {
1165		if (scno != 0) {
1166			if (debug) {
1167				/*
1168				 * This happens when a signal handler
1169				 * for a signal which interrupted a
1170				 * a system call makes another system call.
1171				 */
1172				fprintf(stderr, "syscall: missing exit\n");
1173			}
1174			tcp->flags &= ~TCB_INSYSCALL;
1175		}
1176	}
1177#endif /* SUNOS4 */
1178#ifdef LINUX
1179#if defined (I386)
1180	if (upeek(pid, 4*EAX, &eax) < 0)
1181		return -1;
1182	if (eax != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1183		if (debug)
1184			fprintf(stderr, "stray syscall exit: eax = %ld\n", eax);
1185		return 0;
1186	}
1187#elif defined (X86_64)
1188	if (upeek(pid, 8*RAX, &rax) < 0)
1189		return -1;
1190	if (rax != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1191		if (debug)
1192			fprintf(stderr, "stray syscall exit: rax = %ld\n", rax);
1193		return 0;
1194	}
1195#elif defined (S390) || defined (S390X)
1196	if (upeek(pid, PT_GPR2, &gpr2) < 0)
1197		return -1;
1198	if (syscall_mode != -ENOSYS)
1199		syscall_mode = tcp->scno;
1200	if (gpr2 != syscall_mode && !(tcp->flags & TCB_INSYSCALL)) {
1201		if (debug)
1202			fprintf(stderr, "stray syscall exit: gpr2 = %ld\n", gpr2);
1203		return 0;
1204	}
1205#elif defined (POWERPC)
1206# define SO_MASK 0x10000000
1207	if (upeek(pid, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1208		return -1;
1209	if (upeek(pid, sizeof(unsigned long)*PT_R3, &result) < 0)
1210		return -1;
1211	if (flags & SO_MASK)
1212		result = -result;
1213#elif defined (M68K)
1214	if (upeek(pid, 4*PT_D0, &d0) < 0)
1215		return -1;
1216	if (d0 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1217		if (debug)
1218			fprintf(stderr, "stray syscall exit: d0 = %ld\n", d0);
1219		return 0;
1220	}
1221#elif defined (ARM)
1222	if (upeek(pid, 4*0, (long *)&r0) < 0)
1223		return -1;
1224	if ( 0 && r0 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1225		if (debug)
1226			fprintf(stderr, "stray syscall exit: d0 = %ld\n", r0);
1227		return 0;
1228	}
1229#elif defined (HPPA)
1230	if (upeek(pid, PT_GR28, &r28) < 0)
1231		return -1;
1232#elif defined(IA64)
1233	if (upeek(pid, PT_R10, &r10) < 0)
1234		return -1;
1235	if (upeek(pid, PT_R8, &r8) < 0)
1236		return -1;
1237	if (ia32 && r8 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1238		if (debug)
1239			fprintf(stderr, "stray syscall exit: r8 = %ld\n", r8);
1240		return 0;
1241	}
1242#endif
1243#endif /* LINUX */
1244	return 1;
1245}
1246
1247int
1248get_error(tcp)
1249struct tcb *tcp;
1250{
1251	int u_error = 0;
1252#ifdef LINUX
1253#if defined(S390) || defined(S390X)
1254		if (gpr2 && (unsigned) -gpr2 < nerrnos) {
1255			tcp->u_rval = -1;
1256			u_error = -gpr2;
1257		}
1258		else {
1259			tcp->u_rval = gpr2;
1260			u_error = 0;
1261		}
1262#else /* !S390 && !S390X */
1263#ifdef I386
1264		if (eax < 0 && -eax < nerrnos) {
1265			tcp->u_rval = -1;
1266			u_error = -eax;
1267		}
1268		else {
1269			tcp->u_rval = eax;
1270			u_error = 0;
1271		}
1272#else /* !I386 */
1273#ifdef X86_64
1274		if (rax < 0 && -rax < nerrnos) {
1275			tcp->u_rval = -1;
1276			u_error = -rax;
1277		}
1278		else {
1279			tcp->u_rval = rax;
1280			u_error = 0;
1281		}
1282#else
1283#ifdef IA64
1284		if (ia32) {
1285			int err;
1286
1287			err = (int)r8;
1288			if (err < 0 && -err < nerrnos) {
1289				tcp->u_rval = -1;
1290				u_error = -err;
1291			}
1292			else {
1293				tcp->u_rval = err;
1294				u_error = 0;
1295			}
1296		} else {
1297			if (r10) {
1298				tcp->u_rval = -1;
1299				u_error = r8;
1300			} else {
1301				tcp->u_rval = r8;
1302				u_error = 0;
1303			}
1304		}
1305#else /* !IA64 */
1306#ifdef MIPS
1307		if (a3) {
1308		  	tcp->u_rval = -1;
1309			u_error = r2;
1310		} else {
1311		  	tcp->u_rval = r2;
1312			u_error = 0;
1313		}
1314#else
1315#ifdef POWERPC
1316		if (result && (unsigned) -result < nerrnos) {
1317			tcp->u_rval = -1;
1318			u_error = -result;
1319		}
1320		else {
1321			tcp->u_rval = result;
1322			u_error = 0;
1323		}
1324#else /* !POWERPC */
1325#ifdef M68K
1326		if (d0 && (unsigned) -d0 < nerrnos) {
1327			tcp->u_rval = -1;
1328			u_error = -d0;
1329		}
1330		else {
1331			tcp->u_rval = d0;
1332			u_error = 0;
1333		}
1334#else /* !M68K */
1335#ifdef ARM
1336		if (r0 && (unsigned) -r0 < nerrnos) {
1337			tcp->u_rval = -1;
1338			u_error = -r0;
1339		}
1340		else {
1341			tcp->u_rval = r0;
1342			u_error = 0;
1343		}
1344#else /* !ARM */
1345#ifdef ALPHA
1346		if (a3) {
1347			tcp->u_rval = -1;
1348			u_error = r0;
1349		}
1350		else {
1351			tcp->u_rval = r0;
1352			u_error = 0;
1353		}
1354#else /* !ALPHA */
1355#ifdef SPARC
1356		if (regs.r_psr & PSR_C) {
1357			tcp->u_rval = -1;
1358			u_error = regs.r_o0;
1359		}
1360		else {
1361			tcp->u_rval = regs.r_o0;
1362			u_error = 0;
1363		}
1364#else /* !SPARC */
1365#ifdef HPPA
1366		if (r28 && (unsigned) -r28 < nerrnos) {
1367			tcp->u_rval = -1;
1368			u_error = -r28;
1369		}
1370		else {
1371			tcp->u_rval = r28;
1372			u_error = 0;
1373		}
1374#else
1375#ifdef SH
1376               /* interpret R0 as return value or error number */
1377               if (r0 && (unsigned) -r0 < nerrnos) {
1378                       tcp->u_rval = -1;
1379                       u_error = -r0;
1380               }
1381               else {
1382                       tcp->u_rval = r0;
1383                       u_error = 0;
1384               }
1385#endif /* SH */
1386#endif /* HPPA */
1387#endif /* SPARC */
1388#endif /* ALPHA */
1389#endif /* ARM */
1390#endif /* M68K */
1391#endif /* POWERPC */
1392#endif /* MIPS */
1393#endif /* IA64 */
1394#endif /* X86_64 */
1395#endif /* I386 */
1396#endif /* S390 || S390X */
1397#endif /* LINUX */
1398#ifdef SUNOS4
1399		/* get error code from user struct */
1400		if (upeek(pid, uoff(u_error), &u_error) < 0)
1401			return -1;
1402		u_error >>= 24; /* u_error is a char */
1403
1404		/* get system call return value */
1405		if (upeek(pid, uoff(u_rval1), &tcp->u_rval) < 0)
1406			return -1;
1407#endif /* SUNOS4 */
1408#ifdef SVR4
1409#ifdef SPARC
1410		/* Judicious guessing goes a long way. */
1411		if (tcp->status.pr_reg[R_PSR] & 0x100000) {
1412			tcp->u_rval = -1;
1413			u_error = tcp->status.pr_reg[R_O0];
1414		}
1415		else {
1416			tcp->u_rval = tcp->status.pr_reg[R_O0];
1417			u_error = 0;
1418		}
1419#endif /* SPARC */
1420#ifdef I386
1421		/* Wanna know how to kill an hour single-stepping? */
1422		if (tcp->status.PR_REG[EFL] & 0x1) {
1423			tcp->u_rval = -1;
1424			u_error = tcp->status.PR_REG[EAX];
1425		}
1426		else {
1427			tcp->u_rval = tcp->status.PR_REG[EAX];
1428#ifdef HAVE_LONG_LONG
1429			tcp->u_lrval =
1430				((unsigned long long) tcp->status.PR_REG[EDX] << 32) +
1431				tcp->status.PR_REG[EAX];
1432#endif
1433			u_error = 0;
1434		}
1435#endif /* I386 */
1436#ifdef X86_64
1437		/* Wanna know how to kill an hour single-stepping? */
1438		if (tcp->status.PR_REG[EFLAGS] & 0x1) {
1439			tcp->u_rval = -1;
1440			u_error = tcp->status.PR_REG[RAX];
1441		}
1442		else {
1443			tcp->u_rval = tcp->status.PR_REG[RAX];
1444			u_error = 0;
1445		}
1446#endif /* X86_64 */
1447#ifdef MIPS
1448		if (tcp->status.pr_reg[CTX_A3]) {
1449			tcp->u_rval = -1;
1450			u_error = tcp->status.pr_reg[CTX_V0];
1451		}
1452		else {
1453			tcp->u_rval = tcp->status.pr_reg[CTX_V0];
1454			u_error = 0;
1455		}
1456#endif /* MIPS */
1457#endif /* SVR4 */
1458#ifdef FREEBSD
1459		if (regs.r_eflags & PSL_C) {
1460 		        tcp->u_rval = -1;
1461		        u_error = regs.r_eax;
1462		} else {
1463		        tcp->u_rval = regs.r_eax;
1464			tcp->u_lrval =
1465			  ((unsigned long long) regs.r_edx << 32) +  regs.r_eax;
1466		        u_error = 0;
1467		}
1468#endif /* FREEBSD */
1469	tcp->u_error = u_error;
1470	return 1;
1471}
1472
1473int
1474force_result(tcp, error, rval)
1475	struct tcb *tcp;
1476	int error;
1477	long rval;
1478{
1479#ifdef LINUX
1480#if defined(S390) || defined(S390X)
1481	gpr2 = error ? -error : rval;
1482	if (upeek(tcp->pid, PT_GPR2, &gpr2) < 0)
1483		return -1;
1484	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)PT_GPR2, gpr2) < 0)
1485		return -1;
1486#else /* !S390 && !S390X */
1487#ifdef I386
1488	eax = error ? -error : rval;
1489	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(EAX * 4), eax) < 0)
1490		return -1;
1491#else /* !I386 */
1492#ifdef X86_64
1493	rax = error ? -error : rval;
1494	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(RAX * 4), rax) < 0)
1495		return -1;
1496#else
1497#ifdef IA64
1498	if (ia32) {
1499		r8 = error ? -error : rval;
1500		if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R8), r8) < 0)
1501			return -1;
1502	}
1503	else {
1504		if (error) {
1505			r8 = error;
1506			r10 = -1;
1507		}
1508		else {
1509			r8 = rval;
1510			r10 = 0;
1511		}
1512		if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R8), r8) < 0 ||
1513		    ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R10), r10) < 0)
1514			return -1;
1515	}
1516#else /* !IA64 */
1517#ifdef MIPS
1518	if (error) {
1519		r2 = error;
1520		a3 = -1;
1521	}
1522	else {
1523		r2 = rval;
1524		a3 = 0;
1525	}
1526	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), a3) < 0 ||
1527	    ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), r2) < 0)
1528	    	return -1;
1529#else
1530#ifdef POWERPC
1531	if (upeek(tcp->pid, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1532		return -1;
1533	if (error) {
1534		flags |= SO_MASK;
1535		result = error;
1536	}
1537	else {
1538		flags &= ~SO_MASK;
1539		result = rval;
1540	}
1541	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(sizeof(unsigned long)*PT_CCR), flags) < 0 ||
1542	    ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(sizeof(unsigned long)*PT_R3), result) < 0)
1543		return -1;
1544#else /* !POWERPC */
1545#ifdef M68K
1546	d0 = error ? -error : rval;
1547	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_D0), d0) < 0)
1548		return -1;
1549#else /* !M68K */
1550#ifdef ARM
1551	r0 = error ? -error : rval;
1552	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*0), r0) < 0)
1553		return -1;
1554#else /* !ARM */
1555#ifdef ALPHA
1556	if (error) {
1557		a3 = -1;
1558		r0 = error;
1559	}
1560	else {
1561		a3 = 0;
1562		r0 = rval;
1563	}
1564	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), a3) < 0 ||
1565	    ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_R0), r0) < 0)
1566		return -1;
1567#else /* !ALPHA */
1568#ifdef SPARC
1569	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1570		return -1;
1571	if (error) {
1572		regs.r_psr |= PSR_C;
1573		regs.r_o0 = error;
1574	}
1575	else {
1576		regs.r_psr &= ~PSR_C;
1577		regs.r_o0 = rval;
1578	}
1579	if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0)
1580		return -1;
1581#else /* !SPARC */
1582#ifdef HPPA
1583	r28 = error ? -error : rval;
1584	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR28), r28) < 0)
1585		return -1;
1586#else
1587#ifdef SH
1588	r0 = error ? -error : rval;
1589	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*REG_REG0), r0) < 0)
1590		return -1;
1591#endif /* SH */
1592#endif /* HPPA */
1593#endif /* SPARC */
1594#endif /* ALPHA */
1595#endif /* ARM */
1596#endif /* M68K */
1597#endif /* POWERPC */
1598#endif /* MIPS */
1599#endif /* IA64 */
1600#endif /* X86_64 */
1601#endif /* I386 */
1602#endif /* S390 || S390X */
1603#endif /* LINUX */
1604#ifdef SUNOS4
1605	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)uoff(u_error),
1606		   error << 24) < 0 ||
1607	    ptrace(PTRACE_POKEUSER, tcp->pid, (char*)uoff(u_rval1), rval) < 0)
1608		return -1;
1609#endif /* SUNOS4 */
1610#ifdef SVR4
1611	/* XXX no clue */
1612	return -1;
1613#endif /* SVR4 */
1614#ifdef FREEBSD
1615	if (pread(tcp->pfd_reg, &regs, sizeof(regs), 0) < 0) {
1616	        perror("pread");
1617                return -1;
1618        }
1619	if (error) {
1620		regs.r_eflags |= PSL_C;
1621		regs.r_eax = error;
1622	}
1623	else {
1624		regs.r_eflags &= ~PSL_C;
1625		regs.r_eax = rval;
1626	}
1627	if (pwrite(tcp->pfd_reg, &regs, sizeof(regs), 0) < 0) {
1628	        perror("pwrite");
1629                return -1;
1630        }
1631#endif /* FREEBSD */
1632
1633	/* All branches reach here on success (only).  */
1634	tcp->u_error = error;
1635	tcp->u_rval = rval;
1636	return 0;
1637}
1638
1639int syscall_enter(tcp)
1640struct tcb *tcp;
1641{
1642#ifndef USE_PROCFS
1643	int pid = tcp->pid;
1644#endif /* !USE_PROCFS */
1645#ifdef LINUX
1646#if defined(S390) || defined(S390X)
1647	{
1648		int i;
1649		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1650			tcp->u_nargs = sysent[tcp->scno].nargs;
1651		else
1652     	        	tcp->u_nargs = MAX_ARGS;
1653		for (i = 0; i < tcp->u_nargs; i++) {
1654			if (upeek(pid,i==0 ? PT_ORIGGPR2:PT_GPR2+i*sizeof(long), &tcp->u_arg[i]) < 0)
1655				return -1;
1656		}
1657	}
1658#elif defined (ALPHA)
1659	{
1660		int i;
1661		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1662			tcp->u_nargs = sysent[tcp->scno].nargs;
1663		else
1664     	        	tcp->u_nargs = MAX_ARGS;
1665		for (i = 0; i < tcp->u_nargs; i++) {
1666			/* WTA: if scno is out-of-bounds this will bomb. Add range-check
1667			 * for scno somewhere above here!
1668			 */
1669			if (upeek(pid, REG_A0+i, &tcp->u_arg[i]) < 0)
1670				return -1;
1671		}
1672	}
1673#elif defined (IA64)
1674	{
1675		if (!ia32) {
1676			unsigned long *out0, *rbs_end, cfm, sof, sol, i;
1677			/* be backwards compatible with kernel < 2.4.4... */
1678#			ifndef PT_RBS_END
1679#			  define PT_RBS_END	PT_AR_BSP
1680#			endif
1681
1682			if (upeek(pid, PT_RBS_END, (long *) &rbs_end) < 0)
1683				return -1;
1684			if (upeek(pid, PT_CFM, (long *) &cfm) < 0)
1685				return -1;
1686
1687			sof = (cfm >> 0) & 0x7f;
1688			sol = (cfm >> 7) & 0x7f;
1689			out0 = ia64_rse_skip_regs(rbs_end, -sof + sol);
1690
1691			if (tcp->scno >= 0 && tcp->scno < nsyscalls
1692			    && sysent[tcp->scno].nargs != -1)
1693				tcp->u_nargs = sysent[tcp->scno].nargs;
1694			else
1695				tcp->u_nargs = MAX_ARGS;
1696			for (i = 0; i < tcp->u_nargs; ++i) {
1697				if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
1698					   sizeof(long), (char *) &tcp->u_arg[i]) < 0)
1699					return -1;
1700			}
1701		} else {
1702			int i;
1703
1704			if (/* EBX = out0 */
1705			    upeek(pid, PT_R11, (long *) &tcp->u_arg[0]) < 0
1706			    /* ECX = out1 */
1707			    || upeek(pid, PT_R9,  (long *) &tcp->u_arg[1]) < 0
1708			    /* EDX = out2 */
1709			    || upeek(pid, PT_R10, (long *) &tcp->u_arg[2]) < 0
1710			    /* ESI = out3 */
1711			    || upeek(pid, PT_R14, (long *) &tcp->u_arg[3]) < 0
1712			    /* EDI = out4 */
1713			    || upeek(pid, PT_R15, (long *) &tcp->u_arg[4]) < 0
1714			    /* EBP = out5 */
1715			    || upeek(pid, PT_R13, (long *) &tcp->u_arg[5]) < 0)
1716				return -1;
1717
1718			for (i = 0; i < 6; ++i)
1719				/* truncate away IVE sign-extension */
1720				tcp->u_arg[i] &= 0xffffffff;
1721
1722			if (tcp->scno >= 0 && tcp->scno < nsyscalls
1723			    && sysent[tcp->scno].nargs != -1)
1724				tcp->u_nargs = sysent[tcp->scno].nargs;
1725			else
1726				tcp->u_nargs = 5;
1727		}
1728	}
1729#elif defined (MIPS)
1730	{
1731	  	long sp;
1732	  	int i, nargs;
1733
1734		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1735			nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
1736		else
1737     	        	nargs = tcp->u_nargs = MAX_ARGS;
1738		if(nargs > 4) {
1739		  	if(upeek(pid, REG_SP, &sp) < 0)
1740			  	return -1;
1741			for(i = 0; i < 4; i++) {
1742			  	if (upeek(pid, REG_A0 + i, &tcp->u_arg[i])<0)
1743				  	return -1;
1744			}
1745			umoven(tcp, sp+16, (nargs-4) * sizeof(tcp->u_arg[0]),
1746			       (char *)(tcp->u_arg + 4));
1747		} else {
1748		  	for(i = 0; i < nargs; i++) {
1749			  	if (upeek(pid, REG_A0 + i, &tcp->u_arg[i]) < 0)
1750				  	return -1;
1751			}
1752		}
1753	}
1754#elif defined (POWERPC)
1755#ifndef PT_ORIG_R3
1756#define PT_ORIG_R3 34
1757#endif
1758	{
1759		int i;
1760		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1761			tcp->u_nargs = sysent[tcp->scno].nargs;
1762		else
1763     	        	tcp->u_nargs = MAX_ARGS;
1764		for (i = 0; i < tcp->u_nargs; i++) {
1765			if (upeek(pid, (i==0) ?
1766				(sizeof(unsigned long)*PT_ORIG_R3) :
1767				((i+PT_R3)*sizeof(unsigned long)),
1768					&tcp->u_arg[i]) < 0)
1769				return -1;
1770		}
1771	}
1772#elif defined (SPARC)
1773	{
1774		int i;
1775
1776		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1777			tcp->u_nargs = sysent[tcp->scno].nargs;
1778		else
1779     	        	tcp->u_nargs = MAX_ARGS;
1780		for (i = 0; i < tcp->u_nargs; i++)
1781			tcp->u_arg[i] = *((&regs.r_o0) + i);
1782	}
1783#elif defined (HPPA)
1784	{
1785		int i;
1786
1787		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1788			tcp->u_nargs = sysent[tcp->scno].nargs;
1789		else
1790     	        	tcp->u_nargs = MAX_ARGS;
1791		for (i = 0; i < tcp->u_nargs; i++) {
1792			if (upeek(pid, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
1793				return -1;
1794		}
1795	}
1796#elif defined(SH)
1797       {
1798               int i;
1799               static int syscall_regs[] = {
1800                   REG_REG0+4, REG_REG0+5, REG_REG0+6, REG_REG0+7,
1801                   REG_REG0, REG_REG0+1, REG_REG0+2
1802                   };
1803
1804               tcp->u_nargs = sysent[tcp->scno].nargs;
1805               for (i = 0; i < tcp->u_nargs; i++) {
1806                       if (upeek(pid, 4*syscall_regs[i], &tcp->u_arg[i]) < 0)
1807                               return -1;
1808               }
1809        }
1810#elif defined(X86_64)
1811	{
1812		int i;
1813		static int argreg[SUPPORTED_PERSONALITIES][MAX_ARGS] = {
1814			{RDI,RSI,RDX,R10,R8,R9},	/* x86-64 ABI */
1815			{RBX,RCX,RDX,RDX,RSI,RDI,RBP}	/* i386 ABI */
1816		};
1817
1818		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1819			tcp->u_nargs = sysent[tcp->scno].nargs;
1820		else
1821     	        	tcp->u_nargs = MAX_ARGS;
1822		for (i = 0; i < tcp->u_nargs; i++) {
1823			if (upeek(pid, argreg[current_personality][i]*8, &tcp->u_arg[i]) < 0)
1824				return -1;
1825		}
1826	}
1827#else /* Other architecture (like i386) (32bits specific) */
1828	{
1829		int i;
1830		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1831			tcp->u_nargs = sysent[tcp->scno].nargs;
1832		else
1833     	        	tcp->u_nargs = MAX_ARGS;
1834		for (i = 0; i < tcp->u_nargs; i++) {
1835			if (upeek(pid, i*4, &tcp->u_arg[i]) < 0)
1836				return -1;
1837		}
1838	}
1839#endif
1840#endif /* LINUX */
1841#ifdef SUNOS4
1842	{
1843		int i;
1844		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1845			tcp->u_nargs = sysent[tcp->scno].nargs;
1846		else
1847     	        	tcp->u_nargs = MAX_ARGS;
1848		for (i = 0; i < tcp->u_nargs; i++) {
1849			struct user *u;
1850
1851			if (upeek(pid, uoff(u_arg[0]) +
1852			    (i*sizeof(u->u_arg[0])), &tcp->u_arg[i]) < 0)
1853				return -1;
1854		}
1855	}
1856#endif /* SUNOS4 */
1857#ifdef SVR4
1858#ifdef MIPS
1859	/*
1860	 * SGI is broken: even though it has pr_sysarg, it doesn't
1861	 * set them on system call entry.  Get a clue.
1862	 */
1863	if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1864		tcp->u_nargs = sysent[tcp->scno].nargs;
1865	else
1866		tcp->u_nargs = tcp->status.pr_nsysarg;
1867	if (tcp->u_nargs > 4) {
1868		memcpy(tcp->u_arg, &tcp->status.pr_reg[CTX_A0],
1869			4*sizeof(tcp->u_arg[0]));
1870		umoven(tcp, tcp->status.pr_reg[CTX_SP] + 16,
1871			(tcp->u_nargs - 4)*sizeof(tcp->u_arg[0]), (char *) (tcp->u_arg + 4));
1872	}
1873	else {
1874		memcpy(tcp->u_arg, &tcp->status.pr_reg[CTX_A0],
1875			tcp->u_nargs*sizeof(tcp->u_arg[0]));
1876	}
1877#elif UNIXWARE >= 2
1878	/*
1879	 * Like SGI, UnixWare doesn't set pr_sysarg until system call exit
1880	 */
1881	if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1882		tcp->u_nargs = sysent[tcp->scno].nargs;
1883	else
1884		tcp->u_nargs = tcp->status.pr_lwp.pr_nsysarg;
1885	umoven(tcp, tcp->status.PR_REG[UESP] + 4,
1886		tcp->u_nargs*sizeof(tcp->u_arg[0]), (char *) tcp->u_arg);
1887#elif defined (HAVE_PR_SYSCALL)
1888	if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1889		tcp->u_nargs = sysent[tcp->scno].nargs;
1890	else
1891		tcp->u_nargs = tcp->status.pr_nsysarg;
1892	{
1893		int i;
1894		for (i = 0; i < tcp->u_nargs; i++)
1895			tcp->u_arg[i] = tcp->status.pr_sysarg[i];
1896	}
1897#elif defined (I386)
1898	if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1899		tcp->u_nargs = sysent[tcp->scno].nargs;
1900	else
1901		tcp->u_nargs = 5;
1902	umoven(tcp, tcp->status.PR_REG[UESP] + 4,
1903		tcp->u_nargs*sizeof(tcp->u_arg[0]), (char *) tcp->u_arg);
1904#else
1905	I DONT KNOW WHAT TO DO
1906#endif /* !HAVE_PR_SYSCALL */
1907#endif /* SVR4 */
1908#ifdef FREEBSD
1909	if (tcp->scno >= 0 && tcp->scno < nsyscalls &&
1910	    sysent[tcp->scno].nargs > tcp->status.val)
1911		tcp->u_nargs = sysent[tcp->scno].nargs;
1912	else
1913	  	tcp->u_nargs = tcp->status.val;
1914	if (tcp->u_nargs < 0)
1915		tcp->u_nargs = 0;
1916	if (tcp->u_nargs > MAX_ARGS)
1917		tcp->u_nargs = MAX_ARGS;
1918	switch(regs.r_eax) {
1919	case SYS___syscall:
1920		pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
1921		      regs.r_esp + sizeof(int) + sizeof(quad_t));
1922	  break;
1923        case SYS_syscall:
1924		pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
1925		      regs.r_esp + 2 * sizeof(int));
1926	  break;
1927        default:
1928		pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
1929		      regs.r_esp + sizeof(int));
1930	  break;
1931	}
1932#endif /* FREEBSD */
1933	return 1;
1934}
1935
1936int
1937trace_syscall(tcp)
1938struct tcb *tcp;
1939{
1940	int sys_res;
1941	struct timeval tv;
1942	int res;
1943
1944	/* Measure the exit time as early as possible to avoid errors. */
1945	if (dtime && (tcp->flags & TCB_INSYSCALL))
1946		gettimeofday(&tv, NULL);
1947
1948	res = get_scno(tcp);
1949	if (res != 1)
1950		return res;
1951
1952	res = syscall_fixup(tcp);
1953	if (res != 1)
1954		return res;
1955
1956	if (tcp->flags & TCB_INSYSCALL) {
1957		long u_error;
1958		res = get_error(tcp);
1959		if (res != 1)
1960			return res;
1961
1962		internal_syscall(tcp);
1963		if (tcp->scno >= 0 && tcp->scno < nsyscalls &&
1964		    !(qual_flags[tcp->scno] & QUAL_TRACE)) {
1965			tcp->flags &= ~TCB_INSYSCALL;
1966			return 0;
1967		}
1968
1969		if (tcp->flags & TCB_REPRINT) {
1970			printleader(tcp);
1971			tprintf("<... ");
1972			if (tcp->scno >= nsyscalls || tcp->scno < 0)
1973				tprintf("syscall_%lu", tcp->scno);
1974			else
1975				tprintf("%s", sysent[tcp->scno].sys_name);
1976			tprintf(" resumed> ");
1977		}
1978
1979		if (cflag && tcp->scno < nsyscalls && tcp->scno >= 0) {
1980			call_count[tcp->scno]++;
1981			if (tcp->u_error)
1982				error_count[tcp->scno]++;
1983			tv_sub(&tv, &tv, &tcp->etime);
1984#ifdef LINUX
1985			if (tv_cmp(&tv, &tcp->dtime) > 0) {
1986				static struct timeval one_tick =
1987					{ 0, 1000000 / HZ };
1988
1989				if (tv_nz(&tcp->dtime))
1990					tv = tcp->dtime;
1991				else if (tv_cmp(&tv, &one_tick) > 0) {
1992					if (tv_cmp(&shortest, &one_tick) < 0)
1993						tv = shortest;
1994					else
1995						tv = one_tick;
1996				}
1997			}
1998#endif /* LINUX */
1999			if (tv_cmp(&tv, &shortest) < 0)
2000				shortest = tv;
2001			tv_add(&tv_count[tcp->scno],
2002				&tv_count[tcp->scno], &tv);
2003			tcp->flags &= ~TCB_INSYSCALL;
2004			return 0;
2005		}
2006
2007		if (tcp->scno >= nsyscalls || tcp->scno < 0
2008		    || (qual_flags[tcp->scno] & QUAL_RAW))
2009			sys_res = printargs(tcp);
2010		else {
2011			if (not_failing_only && tcp->u_error)
2012				return 0;	/* ignore failed syscalls */
2013			sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2014		}
2015		u_error = tcp->u_error;
2016		tprintf(") ");
2017		tabto(acolumn);
2018		if (tcp->scno >= nsyscalls || tcp->scno < 0 ||
2019		    qual_flags[tcp->scno] & QUAL_RAW) {
2020			if (u_error)
2021				tprintf("= -1 (errno %ld)", u_error);
2022			else
2023				tprintf("= %#lx", tcp->u_rval);
2024		}
2025		else if (!(sys_res & RVAL_NONE) && u_error) {
2026			switch (u_error) {
2027#ifdef LINUX
2028			case ERESTARTSYS:
2029				tprintf("= ? ERESTARTSYS (To be restarted)");
2030				break;
2031			case ERESTARTNOINTR:
2032				tprintf("= ? ERESTARTNOINTR (To be restarted)");
2033				break;
2034			case ERESTARTNOHAND:
2035				tprintf("= ? ERESTARTNOHAND (To be restarted)");
2036				break;
2037#endif /* LINUX */
2038			default:
2039				tprintf("= -1 ");
2040				if (u_error < 0)
2041					tprintf("E??? (errno %ld)", u_error);
2042				else if (u_error < nerrnos)
2043					tprintf("%s (%s)", errnoent[u_error],
2044						strerror(u_error));
2045				else
2046					tprintf("ERRNO_%ld (%s)", u_error,
2047						strerror(u_error));
2048				break;
2049			}
2050		}
2051		else {
2052			if (sys_res & RVAL_NONE)
2053				tprintf("= ?");
2054			else {
2055				switch (sys_res & RVAL_MASK) {
2056				case RVAL_HEX:
2057					tprintf("= %#lx", tcp->u_rval);
2058					break;
2059				case RVAL_OCTAL:
2060					tprintf("= %#lo", tcp->u_rval);
2061					break;
2062				case RVAL_UDECIMAL:
2063					tprintf("= %lu", tcp->u_rval);
2064					break;
2065				case RVAL_DECIMAL:
2066					tprintf("= %ld", tcp->u_rval);
2067					break;
2068#ifdef HAVE_LONG_LONG
2069				case RVAL_LHEX:
2070					tprintf("= %#llx", tcp->u_lrval);
2071					break;
2072				case RVAL_LOCTAL:
2073					tprintf("= %#llo", tcp->u_lrval);
2074					break;
2075				case RVAL_LUDECIMAL:
2076					tprintf("= %llu", tcp->u_lrval);
2077					break;
2078				case RVAL_LDECIMAL:
2079					tprintf("= %lld", tcp->u_lrval);
2080					break;
2081#endif
2082				default:
2083					fprintf(stderr,
2084						"invalid rval format\n");
2085					break;
2086				}
2087			}
2088			if ((sys_res & RVAL_STR) && tcp->auxstr)
2089				tprintf(" (%s)", tcp->auxstr);
2090		}
2091		if (dtime) {
2092			tv_sub(&tv, &tv, &tcp->etime);
2093			tprintf(" <%ld.%06ld>",
2094				(long) tv.tv_sec, (long) tv.tv_usec);
2095		}
2096		printtrailer(tcp);
2097
2098		dumpio(tcp);
2099		if (fflush(tcp->outf) == EOF)
2100			return -1;
2101		tcp->flags &= ~TCB_INSYSCALL;
2102		return 0;
2103	}
2104
2105	/* Entering system call */
2106	res = syscall_enter(tcp);
2107	if (res != 1)
2108		return res;
2109
2110	switch (tcp->scno + NR_SYSCALL_BASE) {
2111#ifdef LINUX
2112#if !defined (ALPHA) && !defined(SPARC) && !defined(MIPS) && !defined(HPPA) && !defined(X86_64)
2113	case SYS_socketcall:
2114		decode_subcall(tcp, SYS_socket_subcall,
2115			SYS_socket_nsubcalls, deref_style);
2116		break;
2117	case SYS_ipc:
2118		decode_subcall(tcp, SYS_ipc_subcall,
2119			SYS_ipc_nsubcalls, shift_style);
2120		break;
2121#endif /* !ALPHA && !MIPS && !SPARC && !HPPA && !X86_64 */
2122#ifdef SPARC
2123	case SYS_socketcall:
2124		sparc_socket_decode (tcp);
2125		break;
2126#endif
2127#endif /* LINUX */
2128#ifdef SVR4
2129#ifdef SYS_pgrpsys_subcall
2130	case SYS_pgrpsys:
2131		decode_subcall(tcp, SYS_pgrpsys_subcall,
2132			SYS_pgrpsys_nsubcalls, shift_style);
2133		break;
2134#endif /* SYS_pgrpsys_subcall */
2135#ifdef SYS_sigcall_subcall
2136	case SYS_sigcall:
2137		decode_subcall(tcp, SYS_sigcall_subcall,
2138			SYS_sigcall_nsubcalls, mask_style);
2139		break;
2140#endif /* SYS_sigcall_subcall */
2141	case SYS_msgsys:
2142		decode_subcall(tcp, SYS_msgsys_subcall,
2143			SYS_msgsys_nsubcalls, shift_style);
2144		break;
2145	case SYS_shmsys:
2146		decode_subcall(tcp, SYS_shmsys_subcall,
2147			SYS_shmsys_nsubcalls, shift_style);
2148		break;
2149	case SYS_semsys:
2150		decode_subcall(tcp, SYS_semsys_subcall,
2151			SYS_semsys_nsubcalls, shift_style);
2152		break;
2153#if 0 /* broken */
2154	case SYS_utssys:
2155		decode_subcall(tcp, SYS_utssys_subcall,
2156			SYS_utssys_nsubcalls, shift_style);
2157		break;
2158#endif
2159	case SYS_sysfs:
2160		decode_subcall(tcp, SYS_sysfs_subcall,
2161			SYS_sysfs_nsubcalls, shift_style);
2162		break;
2163	case SYS_spcall:
2164		decode_subcall(tcp, SYS_spcall_subcall,
2165			SYS_spcall_nsubcalls, shift_style);
2166		break;
2167#ifdef SYS_context_subcall
2168	case SYS_context:
2169		decode_subcall(tcp, SYS_context_subcall,
2170			SYS_context_nsubcalls, shift_style);
2171		break;
2172#endif /* SYS_context_subcall */
2173#ifdef SYS_door_subcall
2174	case SYS_door:
2175		decode_subcall(tcp, SYS_door_subcall,
2176			SYS_door_nsubcalls, door_style);
2177		break;
2178#endif /* SYS_door_subcall */
2179#ifdef SYS_kaio_subcall
2180	case SYS_kaio:
2181		decode_subcall(tcp, SYS_kaio_subcall,
2182			SYS_kaio_nsubcalls, shift_style);
2183		break;
2184#endif
2185#endif /* SVR4 */
2186#ifdef FREEBSD
2187	case SYS_msgsys:
2188	case SYS_shmsys:
2189	case SYS_semsys:
2190		decode_subcall(tcp, 0, 0, table_style);
2191		break;
2192#endif
2193#ifdef SUNOS4
2194	case SYS_semsys:
2195		decode_subcall(tcp, SYS_semsys_subcall,
2196			SYS_semsys_nsubcalls, shift_style);
2197		break;
2198	case SYS_msgsys:
2199		decode_subcall(tcp, SYS_msgsys_subcall,
2200			SYS_msgsys_nsubcalls, shift_style);
2201		break;
2202	case SYS_shmsys:
2203		decode_subcall(tcp, SYS_shmsys_subcall,
2204			SYS_shmsys_nsubcalls, shift_style);
2205		break;
2206#endif
2207	}
2208
2209	internal_syscall(tcp);
2210	if (tcp->scno >=0 && tcp->scno < nsyscalls && !(qual_flags[tcp->scno] & QUAL_TRACE)) {
2211		tcp->flags |= TCB_INSYSCALL;
2212		return 0;
2213	}
2214
2215	if (cflag) {
2216		gettimeofday(&tcp->etime, NULL);
2217		tcp->flags |= TCB_INSYSCALL;
2218		return 0;
2219	}
2220
2221	printleader(tcp);
2222	tcp->flags &= ~TCB_REPRINT;
2223	tcp_last = tcp;
2224	if (tcp->scno >= nsyscalls || tcp->scno < 0)
2225		tprintf("syscall_%lu(", tcp->scno);
2226	else
2227		tprintf("%s(", sysent[tcp->scno].sys_name);
2228	if (tcp->scno >= nsyscalls || tcp->scno < 0 ||
2229	    ((qual_flags[tcp->scno] & QUAL_RAW) && tcp->scno != SYS_exit))
2230		sys_res = printargs(tcp);
2231	else
2232		sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2233	if (fflush(tcp->outf) == EOF)
2234		return -1;
2235	tcp->flags |= TCB_INSYSCALL;
2236	/* Measure the entrance time as late as possible to avoid errors. */
2237	if (dtime)
2238		gettimeofday(&tcp->etime, NULL);
2239	return sys_res;
2240}
2241
2242int
2243printargs(tcp)
2244struct tcb *tcp;
2245{
2246	if (entering(tcp)) {
2247		int i;
2248
2249		for (i = 0; i < tcp->u_nargs; i++)
2250			tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
2251	}
2252	return 0;
2253}
2254
2255long
2256getrval2(tcp)
2257struct tcb *tcp;
2258{
2259	long val = -1;
2260
2261#ifdef LINUX
2262#ifdef SPARC
2263	struct regs regs;
2264	if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
2265		return -1;
2266	val = regs.r_o1;
2267#endif /* SPARC */
2268#endif /* LINUX */
2269
2270#ifdef SUNOS4
2271	if (upeek(tcp->pid, uoff(u_rval2), &val) < 0)
2272		return -1;
2273#endif /* SUNOS4 */
2274
2275#ifdef SVR4
2276#ifdef SPARC
2277	val = tcp->status.PR_REG[R_O1];
2278#endif /* SPARC */
2279#ifdef I386
2280	val = tcp->status.PR_REG[EDX];
2281#endif /* I386 */
2282#ifdef X86_64
2283	val = tcp->status.PR_REG[RDX];
2284#endif /* X86_64 */
2285#ifdef MIPS
2286	val = tcp->status.PR_REG[CTX_V1];
2287#endif /* MIPS */
2288#endif /* SVR4 */
2289#ifdef FREEBSD
2290	struct reg regs;
2291	pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
2292	val = regs.r_edx;
2293#endif
2294	return val;
2295}
2296
2297/*
2298 * Apparently, indirect system calls have already be converted by ptrace(2),
2299 * so if you see "indir" this program has gone astray.
2300 */
2301int
2302sys_indir(tcp)
2303struct tcb *tcp;
2304{
2305	int i, scno, nargs;
2306
2307	if (entering(tcp)) {
2308		if ((scno = tcp->u_arg[0]) > nsyscalls) {
2309			fprintf(stderr, "Bogus syscall: %u\n", scno);
2310			return 0;
2311		}
2312		nargs = sysent[scno].nargs;
2313		tprintf("%s", sysent[scno].sys_name);
2314		for (i = 0; i < nargs; i++)
2315			tprintf(", %#lx", tcp->u_arg[i+1]);
2316	}
2317	return 0;
2318}
2319
2320static int
2321time_cmp(a, b)
2322void *a;
2323void *b;
2324{
2325	return -tv_cmp(&tv_count[*((int *) a)], &tv_count[*((int *) b)]);
2326}
2327
2328static int
2329syscall_cmp(a, b)
2330void *a;
2331void *b;
2332{
2333	return strcmp(sysent[*((int *) a)].sys_name,
2334		sysent[*((int *) b)].sys_name);
2335}
2336
2337static int
2338count_cmp(a, b)
2339void *a;
2340void *b;
2341{
2342	int m = call_count[*((int *) a)], n = call_count[*((int *) b)];
2343
2344	return (m < n) ? 1 : (m > n) ? -1 : 0;
2345}
2346
2347static int (*sortfun)();
2348static struct timeval overhead = { -1, -1 };
2349
2350void
2351set_sortby(sortby)
2352char *sortby;
2353{
2354	if (strcmp(sortby, "time") == 0)
2355		sortfun = time_cmp;
2356	else if (strcmp(sortby, "calls") == 0)
2357		sortfun = count_cmp;
2358	else if (strcmp(sortby, "name") == 0)
2359		sortfun = syscall_cmp;
2360	else if (strcmp(sortby, "nothing") == 0)
2361		sortfun = NULL;
2362	else {
2363		fprintf(stderr, "invalid sortby: `%s'\n", sortby);
2364		exit(1);
2365	}
2366}
2367
2368void set_overhead(n)
2369int n;
2370{
2371	overhead.tv_sec = n / 1000000;
2372	overhead.tv_usec = n % 1000000;
2373}
2374
2375void
2376call_summary(outf)
2377FILE *outf;
2378{
2379	int i, j;
2380	int call_cum, error_cum;
2381	struct timeval tv_cum, dtv;
2382	double percent;
2383	char *dashes = "-------------------------";
2384	char error_str[16];
2385
2386	call_cum = error_cum = tv_cum.tv_sec = tv_cum.tv_usec = 0;
2387	if (overhead.tv_sec == -1) {
2388		tv_mul(&overhead, &shortest, 8);
2389		tv_div(&overhead, &overhead, 10);
2390	}
2391	for (i = 0; i < nsyscalls; i++) {
2392		sorted_count[i] = i;
2393		if (call_count[i] == 0)
2394			continue;
2395		tv_mul(&dtv, &overhead, call_count[i]);
2396		tv_sub(&tv_count[i], &tv_count[i], &dtv);
2397		call_cum += call_count[i];
2398		error_cum += error_count[i];
2399		tv_add(&tv_cum, &tv_cum, &tv_count[i]);
2400	}
2401	if (sortfun)
2402		qsort((void *) sorted_count, nsyscalls, sizeof(int), sortfun);
2403	fprintf(outf, "%6.6s %11.11s %11.11s %9.9s %9.9s %s\n",
2404		"% time", "seconds", "usecs/call",
2405		"calls", "errors", "syscall");
2406	fprintf(outf, "%6.6s %11.11s %11.11s %9.9s %9.9s %-16.16s\n",
2407		dashes, dashes, dashes, dashes, dashes, dashes);
2408	for (i = 0; i < nsyscalls; i++) {
2409		j = sorted_count[i];
2410		if (call_count[j] == 0)
2411			continue;
2412		tv_div(&dtv, &tv_count[j], call_count[j]);
2413		if (error_count[j])
2414			sprintf(error_str, "%d", error_count[j]);
2415		else
2416			error_str[0] = '\0';
2417		percent = 100.0*tv_float(&tv_count[j])/tv_float(&tv_cum);
2418		fprintf(outf, "%6.2f %4ld.%06ld %11ld %9d %9.9s %s\n",
2419			percent, (long) tv_count[j].tv_sec,
2420			(long) tv_count[j].tv_usec,
2421			(long) 1000000 * dtv.tv_sec + dtv.tv_usec,
2422			call_count[j], error_str, sysent[j].sys_name);
2423	}
2424	fprintf(outf, "%6.6s %11.11s %11.11s %9.9s %9.9s %-16.16s\n",
2425		dashes, dashes, dashes, dashes, dashes, dashes);
2426	if (error_cum)
2427		sprintf(error_str, "%d", error_cum);
2428	else
2429		error_str[0] = '\0';
2430	fprintf(outf, "%6.6s %4ld.%06ld %11.11s %9d %9.9s %s\n",
2431		"100.00", (long) tv_cum.tv_sec, (long) tv_cum.tv_usec, "",
2432		call_cum, error_str, "total");
2433}
2434