syscall.c revision 0ef43b8189b036fd958dcc1b861013f32ea596f5
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#ifdef HAVE_SYS_REG_H
46#include <sys/reg.h>
47#ifndef PTRACE_PEEKUSR
48# define PTRACE_PEEKUSR PTRACE_PEEKUSER
49#endif
50#elif defined(HAVE_LINUX_PTRACE_H)
51#undef PTRACE_SYSCALL
52# ifdef HAVE_STRUCT_IA64_FPREG
53#  define ia64_fpreg XXX_ia64_fpreg
54# endif
55# ifdef HAVE_STRUCT_PT_ALL_USER_REGS
56#  define pt_all_user_regs XXX_pt_all_user_regs
57# endif
58#include <linux/ptrace.h>
59# undef ia64_fpreg
60# undef pt_all_user_regs
61#endif
62
63#if defined (LINUX) && defined (SPARC64)
64# undef PTRACE_GETREGS
65# define PTRACE_GETREGS PTRACE_GETREGS64
66# undef PTRACE_SETREGS
67# define PTRACE_SETREGS PTRACE_SETREGS64
68#endif /* LINUX && SPARC64 */
69
70#if defined(LINUX) && defined(IA64)
71# include <asm/ptrace_offsets.h>
72# include <asm/rse.h>
73#endif
74
75#define NR_SYSCALL_BASE 0
76#ifdef LINUX
77#ifndef ERESTARTSYS
78#define ERESTARTSYS	512
79#endif
80#ifndef ERESTARTNOINTR
81#define ERESTARTNOINTR	513
82#endif
83#ifndef ERESTARTNOHAND
84#define ERESTARTNOHAND	514	/* restart if no handler.. */
85#endif
86#ifndef ENOIOCTLCMD
87#define ENOIOCTLCMD	515	/* No ioctl command */
88#endif
89#ifndef ERESTART_RESTARTBLOCK
90#define ERESTART_RESTARTBLOCK 516	/* restart by calling sys_restart_syscall */
91#endif
92#ifndef NSIG
93#define NSIG 32
94#endif
95#ifdef ARM
96#undef NSIG
97#define NSIG 32
98#undef NR_SYSCALL_BASE
99#define NR_SYSCALL_BASE __NR_SYSCALL_BASE
100#endif
101#endif /* LINUX */
102
103#include "syscall.h"
104
105/* Define these shorthand notations to simplify the syscallent files. */
106#define TD TRACE_DESC
107#define TF TRACE_FILE
108#define TI TRACE_IPC
109#define TN TRACE_NETWORK
110#define TP TRACE_PROCESS
111#define TS TRACE_SIGNAL
112
113static const struct sysent sysent0[] = {
114#include "syscallent.h"
115};
116static const int nsyscalls0 = sizeof sysent0 / sizeof sysent0[0];
117int qual_flags0[MAX_QUALS];
118
119#if SUPPORTED_PERSONALITIES >= 2
120static const struct sysent sysent1[] = {
121#include "syscallent1.h"
122};
123static const int nsyscalls1 = sizeof sysent1 / sizeof sysent1[0];
124int qual_flags1[MAX_QUALS];
125#endif /* SUPPORTED_PERSONALITIES >= 2 */
126
127#if SUPPORTED_PERSONALITIES >= 3
128static const struct sysent sysent2[] = {
129#include "syscallent2.h"
130};
131static const int nsyscalls2 = sizeof sysent2 / sizeof sysent2[0];
132int qual_flags2[MAX_QUALS];
133#endif /* SUPPORTED_PERSONALITIES >= 3 */
134
135const struct sysent *sysent;
136int *qual_flags;
137int nsyscalls;
138
139/* Now undef them since short defines cause wicked namespace pollution. */
140#undef TD
141#undef TF
142#undef TI
143#undef TN
144#undef TP
145#undef TS
146
147static const char *const errnoent0[] = {
148#include "errnoent.h"
149};
150static const int nerrnos0 = sizeof errnoent0 / sizeof errnoent0[0];
151
152#if SUPPORTED_PERSONALITIES >= 2
153static const char *const errnoent1[] = {
154#include "errnoent1.h"
155};
156static const int nerrnos1 = sizeof errnoent1 / sizeof errnoent1[0];
157#endif /* SUPPORTED_PERSONALITIES >= 2 */
158
159#if SUPPORTED_PERSONALITIES >= 3
160static const char *const errnoent2[] = {
161#include "errnoent2.h"
162};
163static const int nerrnos2 = sizeof errnoent2 / sizeof errnoent2[0];
164#endif /* SUPPORTED_PERSONALITIES >= 3 */
165
166const char *const *errnoent;
167int nerrnos;
168
169int current_personality;
170
171#ifndef PERSONALITY0_WORDSIZE
172# define PERSONALITY0_WORDSIZE sizeof(long)
173#endif
174const int personality_wordsize[SUPPORTED_PERSONALITIES] = {
175	PERSONALITY0_WORDSIZE,
176#if SUPPORTED_PERSONALITIES > 1
177	PERSONALITY1_WORDSIZE,
178#endif
179#if SUPPORTED_PERSONALITIES > 2
180	PERSONALITY2_WORDSIZE,
181#endif
182};;
183
184int
185set_personality(int personality)
186{
187	switch (personality) {
188	case 0:
189		errnoent = errnoent0;
190		nerrnos = nerrnos0;
191		sysent = sysent0;
192		nsyscalls = nsyscalls0;
193		ioctlent = ioctlent0;
194		nioctlents = nioctlents0;
195		signalent = signalent0;
196		nsignals = nsignals0;
197		qual_flags = qual_flags0;
198		break;
199
200#if SUPPORTED_PERSONALITIES >= 2
201	case 1:
202		errnoent = errnoent1;
203		nerrnos = nerrnos1;
204		sysent = sysent1;
205		nsyscalls = nsyscalls1;
206		ioctlent = ioctlent1;
207		nioctlents = nioctlents1;
208		signalent = signalent1;
209		nsignals = nsignals1;
210		qual_flags = qual_flags1;
211		break;
212#endif /* SUPPORTED_PERSONALITIES >= 2 */
213
214#if SUPPORTED_PERSONALITIES >= 3
215	case 2:
216		errnoent = errnoent2;
217		nerrnos = nerrnos2;
218		sysent = sysent2;
219		nsyscalls = nsyscalls2;
220		ioctlent = ioctlent2;
221		nioctlents = nioctlents2;
222		signalent = signalent2;
223		nsignals = nsignals2;
224		qual_flags = qual_flags2;
225		break;
226#endif /* SUPPORTED_PERSONALITIES >= 3 */
227
228	default:
229		return -1;
230	}
231
232	current_personality = personality;
233	return 0;
234}
235
236
237static int qual_syscall(), qual_signal(), qual_fault(), qual_desc();
238
239static const struct qual_options {
240	int bitflag;
241	const char *option_name;
242	int (*qualify)(const char *, const struct qual_options *, int);
243	const char *argument_name;
244} qual_options[] = {
245	{ QUAL_TRACE,	"trace",	qual_syscall,	"system call"	},
246	{ QUAL_TRACE,	"t",		qual_syscall,	"system call"	},
247	{ QUAL_ABBREV,	"abbrev",	qual_syscall,	"system call"	},
248	{ QUAL_ABBREV,	"a",		qual_syscall,	"system call"	},
249	{ QUAL_VERBOSE,	"verbose",	qual_syscall,	"system call"	},
250	{ QUAL_VERBOSE,	"v",		qual_syscall,	"system call"	},
251	{ QUAL_RAW,	"raw",		qual_syscall,	"system call"	},
252	{ QUAL_RAW,	"x",		qual_syscall,	"system call"	},
253	{ QUAL_SIGNAL,	"signal",	qual_signal,	"signal"	},
254	{ QUAL_SIGNAL,	"signals",	qual_signal,	"signal"	},
255	{ QUAL_SIGNAL,	"s",		qual_signal,	"signal"	},
256	{ QUAL_FAULT,	"fault",	qual_fault,	"fault"		},
257	{ QUAL_FAULT,	"faults",	qual_fault,	"fault"		},
258	{ QUAL_FAULT,	"m",		qual_fault,	"fault"		},
259	{ QUAL_READ,	"read",		qual_desc,	"descriptor"	},
260	{ QUAL_READ,	"reads",	qual_desc,	"descriptor"	},
261	{ QUAL_READ,	"r",		qual_desc,	"descriptor"	},
262	{ QUAL_WRITE,	"write",	qual_desc,	"descriptor"	},
263	{ QUAL_WRITE,	"writes",	qual_desc,	"descriptor"	},
264	{ QUAL_WRITE,	"w",		qual_desc,	"descriptor"	},
265	{ 0,		NULL,		NULL,		NULL		},
266};
267
268static void
269qualify_one(n, opt, not, pers)
270	int n;
271	const struct qual_options *opt;
272	int not;
273	int pers;
274{
275	if (pers == 0 || pers < 0) {
276		if (not)
277			qual_flags0[n] &= ~opt->bitflag;
278		else
279			qual_flags0[n] |= opt->bitflag;
280	}
281
282#if SUPPORTED_PERSONALITIES >= 2
283	if (pers == 1 || pers < 0) {
284		if (not)
285			qual_flags1[n] &= ~opt->bitflag;
286		else
287			qual_flags1[n] |= opt->bitflag;
288	}
289#endif /* SUPPORTED_PERSONALITIES >= 2 */
290
291#if SUPPORTED_PERSONALITIES >= 3
292	if (pers == 2 || pers < 0) {
293		if (not)
294			qual_flags2[n] &= ~opt->bitflag;
295		else
296			qual_flags2[n] |= opt->bitflag;
297	}
298#endif /* SUPPORTED_PERSONALITIES >= 3 */
299}
300
301static int
302qual_syscall(const char *s, const struct qual_options *opt, int not)
303{
304	int i;
305	int rc = -1;
306
307	if (isdigit((unsigned char)*s)) {
308		int i = atoi(s);
309		if (i < 0 || i >= MAX_QUALS)
310			return -1;
311		qualify_one(i, opt, not, -1);
312		return 0;
313	}
314	for (i = 0; i < nsyscalls0; i++)
315		if (strcmp(s, sysent0[i].sys_name) == 0) {
316			qualify_one(i, opt, not, 0);
317			rc = 0;
318		}
319
320#if SUPPORTED_PERSONALITIES >= 2
321	for (i = 0; i < nsyscalls1; i++)
322		if (strcmp(s, sysent1[i].sys_name) == 0) {
323			qualify_one(i, opt, not, 1);
324			rc = 0;
325		}
326#endif /* SUPPORTED_PERSONALITIES >= 2 */
327
328#if SUPPORTED_PERSONALITIES >= 3
329	for (i = 0; i < nsyscalls2; i++)
330		if (strcmp(s, sysent2[i].sys_name) == 0) {
331			qualify_one(i, opt, not, 2);
332			rc = 0;
333		}
334#endif /* SUPPORTED_PERSONALITIES >= 3 */
335
336	return rc;
337}
338
339static int
340qual_signal(const char *s, const struct qual_options *opt, int not)
341{
342	int i;
343	char buf[32];
344
345	if (isdigit((unsigned char)*s)) {
346		int signo = atoi(s);
347		if (signo < 0 || signo >= MAX_QUALS)
348			return -1;
349		qualify_one(signo, opt, not, -1);
350		return 0;
351	}
352	if (strlen(s) >= sizeof buf)
353		return -1;
354	strcpy(buf, s);
355	s = buf;
356	if (strncasecmp(s, "SIG", 3) == 0)
357		s += 3;
358	for (i = 0; i <= NSIG; i++)
359		if (strcasecmp(s, signame(i) + 3) == 0) {
360			qualify_one(i, opt, not, -1);
361			return 0;
362		}
363	return -1;
364}
365
366static int
367qual_fault(const char *s, const struct qual_options *opt, int not)
368{
369	return -1;
370}
371
372static int
373qual_desc(const char *s, const struct qual_options *opt, int not)
374{
375	if (isdigit((unsigned char)*s)) {
376		int desc = atoi(s);
377		if (desc < 0 || desc >= MAX_QUALS)
378			return -1;
379		qualify_one(desc, opt, not, -1);
380		return 0;
381	}
382	return -1;
383}
384
385static int
386lookup_class(const char *s)
387{
388	if (strcmp(s, "file") == 0)
389		return TRACE_FILE;
390	if (strcmp(s, "ipc") == 0)
391		return TRACE_IPC;
392	if (strcmp(s, "network") == 0)
393		return TRACE_NETWORK;
394	if (strcmp(s, "process") == 0)
395		return TRACE_PROCESS;
396	if (strcmp(s, "signal") == 0)
397		return TRACE_SIGNAL;
398	if (strcmp(s, "desc") == 0)
399		return TRACE_DESC;
400	return -1;
401}
402
403void
404qualify(const char *s)
405{
406	const struct qual_options *opt;
407	int not;
408	char *copy;
409	const char *p;
410	int i, n;
411
412	opt = &qual_options[0];
413	for (i = 0; (p = qual_options[i].option_name); i++) {
414		n = strlen(p);
415		if (strncmp(s, p, n) == 0 && s[n] == '=') {
416			opt = &qual_options[i];
417			s += n + 1;
418			break;
419		}
420	}
421	not = 0;
422	if (*s == '!') {
423		not = 1;
424		s++;
425	}
426	if (strcmp(s, "none") == 0) {
427		not = 1 - not;
428		s = "all";
429	}
430	if (strcmp(s, "all") == 0) {
431		for (i = 0; i < MAX_QUALS; i++) {
432			qualify_one(i, opt, not, -1);
433		}
434		return;
435	}
436	for (i = 0; i < MAX_QUALS; i++) {
437		qualify_one(i, opt, !not, -1);
438	}
439	if (!(copy = strdup(s))) {
440		fprintf(stderr, "out of memory\n");
441		exit(1);
442	}
443	for (p = strtok(copy, ","); p; p = strtok(NULL, ",")) {
444		if (opt->bitflag == QUAL_TRACE && (n = lookup_class(p)) > 0) {
445			for (i = 0; i < nsyscalls0; i++)
446				if (sysent0[i].sys_flags & n)
447					qualify_one(i, opt, not, 0);
448
449#if SUPPORTED_PERSONALITIES >= 2
450			for (i = 0; i < nsyscalls1; i++)
451				if (sysent1[i].sys_flags & n)
452					qualify_one(i, opt, not, 1);
453#endif /* SUPPORTED_PERSONALITIES >= 2 */
454
455#if SUPPORTED_PERSONALITIES >= 3
456			for (i = 0; i < nsyscalls2; i++)
457				if (sysent2[i].sys_flags & n)
458					qualify_one(i, opt, not, 2);
459#endif /* SUPPORTED_PERSONALITIES >= 3 */
460
461			continue;
462		}
463		if (opt->qualify(p, opt, not)) {
464			fprintf(stderr, "strace: invalid %s `%s'\n",
465				opt->argument_name, p);
466			exit(1);
467		}
468	}
469	free(copy);
470	return;
471}
472
473static void
474dumpio(tcp)
475struct tcb *tcp;
476{
477	if (syserror(tcp))
478		return;
479	if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
480		return;
481	switch (known_scno(tcp)) {
482	case SYS_read:
483#ifdef SYS_pread64
484	case SYS_pread64:
485#endif
486#if defined SYS_pread && SYS_pread64 != SYS_pread
487	case SYS_pread:
488#endif
489#ifdef SYS_recv
490	case SYS_recv:
491#elif defined SYS_sub_recv
492	case SYS_sub_recv:
493#endif
494#ifdef SYS_recvfrom
495	case SYS_recvfrom:
496#elif defined SYS_sub_recvfrom
497	case SYS_sub_recvfrom:
498#endif
499		if (qual_flags[tcp->u_arg[0]] & QUAL_READ)
500			dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
501		break;
502	case SYS_write:
503#ifdef SYS_pwrite64
504	case SYS_pwrite64:
505#endif
506#if defined SYS_pwrite && SYS_pwrite64 != SYS_pwrite
507	case SYS_pwrite:
508#endif
509#ifdef SYS_send
510	case SYS_send:
511#elif defined SYS_sub_send
512	case SYS_sub_send:
513#endif
514#ifdef SYS_sendto
515	case SYS_sendto:
516#elif defined SYS_sub_sendto
517	case SYS_sub_sendto:
518#endif
519		if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE)
520			dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
521		break;
522#ifdef SYS_readv
523	case SYS_readv:
524		if (qual_flags[tcp->u_arg[0]] & QUAL_READ)
525			dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
526		break;
527#endif
528#ifdef SYS_writev
529	case SYS_writev:
530		if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE)
531			dumpiov(tcp, tcp->u_arg[2], tcp->u_arg[1]);
532		break;
533#endif
534	}
535}
536
537#ifndef FREEBSD
538enum subcall_style { shift_style, deref_style, mask_style, door_style };
539#else /* FREEBSD */
540enum subcall_style { shift_style, deref_style, mask_style, door_style, table_style };
541
542struct subcall {
543  int call;
544  int nsubcalls;
545  int subcalls[5];
546};
547
548static const struct subcall subcalls_table[] = {
549  { SYS_shmsys, 5, { SYS_shmat, SYS_shmctl, SYS_shmdt, SYS_shmget, SYS_shmctl } },
550#ifdef SYS_semconfig
551  { SYS_semsys, 4, { SYS___semctl, SYS_semget, SYS_semop, SYS_semconfig } },
552#else
553  { SYS_semsys, 3, { SYS___semctl, SYS_semget, SYS_semop } },
554#endif
555  { SYS_msgsys, 4, { SYS_msgctl, SYS_msgget, SYS_msgsnd, SYS_msgrcv } },
556};
557#endif /* FREEBSD */
558
559#if !(defined(LINUX) && ( defined(ALPHA) || defined(MIPS) || defined(__ARM_EABI__) ))
560
561static void
562decode_subcall(tcp, subcall, nsubcalls, style)
563struct tcb *tcp;
564int subcall;
565int nsubcalls;
566enum subcall_style style;
567{
568	unsigned long addr, mask;
569	int i;
570	int size = personality_wordsize[current_personality];
571
572	switch (style) {
573	case shift_style:
574		if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= nsubcalls)
575			return;
576		tcp->scno = subcall + tcp->u_arg[0];
577		if (sysent[tcp->scno].nargs != -1)
578			tcp->u_nargs = sysent[tcp->scno].nargs;
579		else
580			tcp->u_nargs--;
581		for (i = 0; i < tcp->u_nargs; i++)
582			tcp->u_arg[i] = tcp->u_arg[i + 1];
583		break;
584	case deref_style:
585		if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= nsubcalls)
586			return;
587		tcp->scno = subcall + tcp->u_arg[0];
588		addr = tcp->u_arg[1];
589		for (i = 0; i < sysent[tcp->scno].nargs; i++) {
590			if (size == sizeof(int)) {
591				unsigned int arg;
592				if (umove(tcp, addr, &arg) < 0)
593					arg = 0;
594				tcp->u_arg[i] = arg;
595			}
596			else if (size == sizeof(long)) {
597				unsigned long arg;
598				if (umove(tcp, addr, &arg) < 0)
599					arg = 0;
600				tcp->u_arg[i] = arg;
601			}
602			else
603				abort();
604			addr += size;
605		}
606		tcp->u_nargs = sysent[tcp->scno].nargs;
607		break;
608	case mask_style:
609		mask = (tcp->u_arg[0] >> 8) & 0xff;
610		for (i = 0; mask; i++)
611			mask >>= 1;
612		if (i >= nsubcalls)
613			return;
614		tcp->u_arg[0] &= 0xff;
615		tcp->scno = subcall + i;
616		if (sysent[tcp->scno].nargs != -1)
617			tcp->u_nargs = sysent[tcp->scno].nargs;
618		break;
619	case door_style:
620		/*
621		 * Oh, yuck.  The call code is the *sixth* argument.
622		 * (don't you mean the *last* argument? - JH)
623		 */
624		if (tcp->u_arg[5] < 0 || tcp->u_arg[5] >= nsubcalls)
625			return;
626		tcp->scno = subcall + tcp->u_arg[5];
627		if (sysent[tcp->scno].nargs != -1)
628			tcp->u_nargs = sysent[tcp->scno].nargs;
629		else
630			tcp->u_nargs--;
631		break;
632#ifdef FREEBSD
633	case table_style:
634		for (i = 0; i < sizeof(subcalls_table) / sizeof(struct subcall); i++)
635			if (subcalls_table[i].call == tcp->scno) break;
636		if (i < sizeof(subcalls_table) / sizeof(struct subcall) &&
637		    tcp->u_arg[0] >= 0 && tcp->u_arg[0] < subcalls_table[i].nsubcalls) {
638			tcp->scno = subcalls_table[i].subcalls[tcp->u_arg[0]];
639			for (i = 0; i < tcp->u_nargs; i++)
640				tcp->u_arg[i] = tcp->u_arg[i + 1];
641		}
642		break;
643#endif /* FREEBSD */
644	}
645}
646#endif
647
648struct tcb *tcp_last = NULL;
649
650static int
651internal_syscall(struct tcb *tcp)
652{
653	/*
654	 * We must always trace a few critical system calls in order to
655	 * correctly support following forks in the presence of tracing
656	 * qualifiers.
657	 */
658	int	(*func)();
659
660	if (tcp->scno < 0 || tcp->scno >= nsyscalls)
661		return 0;
662
663	func = sysent[tcp->scno].sys_func;
664
665	if (sys_exit == func)
666		return internal_exit(tcp);
667
668	if (   sys_fork == func
669#if defined(FREEBSD) || defined(LINUX) || defined(SUNOS4)
670	    || sys_vfork == func
671#endif
672#ifdef LINUX
673	    || sys_clone == func
674#endif
675#if UNIXWARE > 2
676	    || sys_rfork == func
677#endif
678	   )
679		return internal_fork(tcp);
680
681	if (   sys_execve == func
682#if defined(SPARC) || defined(SPARC64) || defined(SUNOS4)
683	    || sys_execv == func
684#endif
685#if UNIXWARE > 2
686	    || sys_rexecve == func
687#endif
688	   )
689		return internal_exec(tcp);
690
691	if (   sys_waitpid == func
692	    || sys_wait4 == func
693#if defined(SVR4) || defined(FREEBSD) || defined(SUNOS4)
694	    || sys_wait == func
695#endif
696#ifdef ALPHA
697	    || sys_osf_wait4 == func
698#endif
699	   )
700		return internal_wait(tcp, 2);
701
702#if defined(LINUX) || defined(SVR4)
703	if (sys_waitid == func)
704		return internal_wait(tcp, 3);
705#endif
706
707	return 0;
708}
709
710
711#ifdef LINUX
712#if defined (I386)
713	static long eax;
714#elif defined (IA64)
715	long r8, r10, psr;
716	long ia32 = 0;
717#elif defined (POWERPC)
718	static long result,flags;
719#elif defined (M68K)
720	static long d0;
721#elif defined(BFIN)
722	static long r0;
723#elif defined (ARM)
724	static struct pt_regs regs;
725#elif defined (ALPHA)
726	static long r0;
727	static long a3;
728#elif defined(AVR32)
729	static struct pt_regs regs;
730#elif defined (SPARC) || defined (SPARC64)
731	static struct pt_regs regs;
732	static unsigned long trap;
733#elif defined(LINUX_MIPSN32)
734	static long long a3;
735	static long long r2;
736#elif defined(MIPS)
737	static long a3;
738	static long r2;
739#elif defined(S390) || defined(S390X)
740	static long gpr2;
741	static long pc;
742	static long syscall_mode;
743#elif defined(HPPA)
744	static long r28;
745#elif defined(SH)
746	static long r0;
747#elif defined(SH64)
748	static long r9;
749#elif defined(X86_64)
750	static long rax;
751#elif defined(CRISV10) || defined(CRISV32)
752	static long r10;
753#elif defined(MICROBLAZE)
754	static long r3;
755#endif
756#endif /* LINUX */
757#ifdef FREEBSD
758	struct reg regs;
759#endif /* FREEBSD */
760
761int
762get_scno(struct tcb *tcp)
763{
764	long scno = 0;
765
766#ifdef LINUX
767# if defined(S390) || defined(S390X)
768	if (tcp->flags & TCB_WAITEXECVE) {
769		/*
770		 * When the execve system call completes successfully, the
771		 * new process still has -ENOSYS (old style) or __NR_execve
772		 * (new style) in gpr2.  We cannot recover the scno again
773		 * by disassembly, because the image that executed the
774		 * syscall is gone now.  Fortunately, we don't want it.  We
775		 * leave the flag set so that syscall_fixup can fake the
776		 * result.
777		 */
778		if (tcp->flags & TCB_INSYSCALL)
779			return 1;
780		/*
781		 * This is the SIGTRAP after execve.  We cannot try to read
782		 * the system call here either.
783		 */
784		tcp->flags &= ~TCB_WAITEXECVE;
785		return 0;
786	}
787
788	if (upeek(tcp, PT_GPR2, &syscall_mode) < 0)
789			return -1;
790
791	if (syscall_mode != -ENOSYS) {
792		/*
793		 * Since kernel version 2.5.44 the scno gets passed in gpr2.
794		 */
795		scno = syscall_mode;
796	} else {
797		/*
798		 * Old style of "passing" the scno via the SVC instruction.
799		 */
800
801		long opcode, offset_reg, tmp;
802		void * svc_addr;
803		int gpr_offset[16] = {PT_GPR0,  PT_GPR1,  PT_ORIGGPR2, PT_GPR3,
804				      PT_GPR4,  PT_GPR5,  PT_GPR6,     PT_GPR7,
805				      PT_GPR8,  PT_GPR9,  PT_GPR10,    PT_GPR11,
806				      PT_GPR12, PT_GPR13, PT_GPR14,    PT_GPR15};
807
808		if (upeek(tcp, PT_PSWADDR, &pc) < 0)
809			return -1;
810		errno = 0;
811		opcode = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(pc-sizeof(long)), 0);
812		if (errno) {
813			perror("peektext(pc-oneword)");
814			return -1;
815		}
816
817		/*
818		 *  We have to check if the SVC got executed directly or via an
819		 *  EXECUTE instruction. In case of EXECUTE it is necessary to do
820		 *  instruction decoding to derive the system call number.
821		 *  Unfortunately the opcode sizes of EXECUTE and SVC are differently,
822		 *  so that this doesn't work if a SVC opcode is part of an EXECUTE
823		 *  opcode. Since there is no way to find out the opcode size this
824		 *  is the best we can do...
825		 */
826
827		if ((opcode & 0xff00) == 0x0a00) {
828			/* SVC opcode */
829			scno = opcode & 0xff;
830		}
831		else {
832			/* SVC got executed by EXECUTE instruction */
833
834			/*
835			 *  Do instruction decoding of EXECUTE. If you really want to
836			 *  understand this, read the Principles of Operations.
837			 */
838			svc_addr = (void *) (opcode & 0xfff);
839
840			tmp = 0;
841			offset_reg = (opcode & 0x000f0000) >> 16;
842			if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
843				return -1;
844			svc_addr += tmp;
845
846			tmp = 0;
847			offset_reg = (opcode & 0x0000f000) >> 12;
848			if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
849				return -1;
850			svc_addr += tmp;
851
852			scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, svc_addr, 0);
853			if (errno)
854				return -1;
855#  if defined(S390X)
856			scno >>= 48;
857#  else
858			scno >>= 16;
859#  endif
860			tmp = 0;
861			offset_reg = (opcode & 0x00f00000) >> 20;
862			if (offset_reg && (upeek(tcp, gpr_offset[offset_reg], &tmp) < 0))
863				return -1;
864
865			scno = (scno | tmp) & 0xff;
866		}
867	}
868# elif defined (POWERPC)
869	if (upeek(tcp, sizeof(unsigned long)*PT_R0, &scno) < 0)
870		return -1;
871	if (!(tcp->flags & TCB_INSYSCALL)) {
872		/* Check if we return from execve. */
873		if (scno == 0 && (tcp->flags & TCB_WAITEXECVE)) {
874			tcp->flags &= ~TCB_WAITEXECVE;
875			return 0;
876		}
877	}
878
879#  ifdef POWERPC64
880	if (!(tcp->flags & TCB_INSYSCALL)) {
881		static int currpers = -1;
882		long val;
883		int pid = tcp->pid;
884
885		/* Check for 64/32 bit mode. */
886		if (upeek(tcp, sizeof (unsigned long)*PT_MSR, &val) < 0)
887			return -1;
888		/* SF is bit 0 of MSR */
889		if (val < 0)
890			currpers = 0;
891		else
892			currpers = 1;
893		if (currpers != current_personality) {
894			static const char *const names[] = {"64 bit", "32 bit"};
895			set_personality(currpers);
896			printf("[ Process PID=%d runs in %s mode. ]\n",
897					pid, names[current_personality]);
898		}
899	}
900#  endif
901# elif defined(AVR32)
902	/*
903	 * Read complete register set in one go.
904	 */
905	if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, &regs) < 0)
906		return -1;
907
908	/*
909	 * We only need to grab the syscall number on syscall entry.
910	 */
911	if (!(tcp->flags & TCB_INSYSCALL)) {
912		scno = regs.r8;
913
914		/* Check if we return from execve. */
915		if (tcp->flags & TCB_WAITEXECVE) {
916			tcp->flags &= ~TCB_WAITEXECVE;
917			return 0;
918		}
919	}
920# elif defined(BFIN)
921	if (upeek(tcp, PT_ORIG_P0, &scno))
922		return -1;
923# elif defined (I386)
924	if (upeek(tcp, 4*ORIG_EAX, &scno) < 0)
925		return -1;
926# elif defined (X86_64)
927	if (upeek(tcp, 8*ORIG_RAX, &scno) < 0)
928		return -1;
929
930	if (!(tcp->flags & TCB_INSYSCALL)) {
931		static int currpers = -1;
932		long val;
933		int pid = tcp->pid;
934
935		/* Check CS register value. On x86-64 linux it is:
936		 * 	0x33	for long mode (64 bit)
937		 * 	0x23	for compatibility mode (32 bit)
938		 * It takes only one ptrace and thus doesn't need
939		 * to be cached.
940		 */
941		if (upeek(tcp, 8*CS, &val) < 0)
942			return -1;
943		switch (val) {
944			case 0x23: currpers = 1; break;
945			case 0x33: currpers = 0; break;
946			default:
947				fprintf(stderr, "Unknown value CS=0x%02X while "
948					 "detecting personality of process "
949					 "PID=%d\n", (int)val, pid);
950				currpers = current_personality;
951				break;
952		}
953#  if 0
954		/* This version analyzes the opcode of a syscall instruction.
955		 * (int 0x80 on i386 vs. syscall on x86-64)
956		 * It works, but is too complicated.
957		 */
958		unsigned long val, rip, i;
959
960		if (upeek(tcp, 8*RIP, &rip) < 0)
961			perror("upeek(RIP)");
962
963		/* sizeof(syscall) == sizeof(int 0x80) == 2 */
964		rip -= 2;
965		errno = 0;
966
967		call = ptrace(PTRACE_PEEKTEXT, pid, (char *)rip, (char *)0);
968		if (errno)
969			printf("ptrace_peektext failed: %s\n",
970					strerror(errno));
971		switch (call & 0xffff) {
972			/* x86-64: syscall = 0x0f 0x05 */
973			case 0x050f: currpers = 0; break;
974			/* i386: int 0x80 = 0xcd 0x80 */
975			case 0x80cd: currpers = 1; break;
976			default:
977				currpers = current_personality;
978				fprintf(stderr,
979					"Unknown syscall opcode (0x%04X) while "
980					"detecting personality of process "
981					"PID=%d\n", (int)call, pid);
982				break;
983		}
984#  endif
985		if (currpers != current_personality) {
986			static const char *const names[] = {"64 bit", "32 bit"};
987			set_personality(currpers);
988			printf("[ Process PID=%d runs in %s mode. ]\n",
989					pid, names[current_personality]);
990		}
991	}
992# elif defined(IA64)
993#	define IA64_PSR_IS	((long)1 << 34)
994	if (upeek (tcp, PT_CR_IPSR, &psr) >= 0)
995		ia32 = (psr & IA64_PSR_IS) != 0;
996	if (!(tcp->flags & TCB_INSYSCALL)) {
997		if (ia32) {
998			if (upeek(tcp, PT_R1, &scno) < 0)	/* orig eax */
999				return -1;
1000		} else {
1001			if (upeek (tcp, PT_R15, &scno) < 0)
1002				return -1;
1003		}
1004		/* Check if we return from execve. */
1005		if (tcp->flags & TCB_WAITEXECVE) {
1006			tcp->flags &= ~TCB_WAITEXECVE;
1007			return 0;
1008		}
1009	} else {
1010		/* syscall in progress */
1011		if (upeek (tcp, PT_R8, &r8) < 0)
1012			return -1;
1013		if (upeek (tcp, PT_R10, &r10) < 0)
1014			return -1;
1015	}
1016# elif defined (ARM)
1017	/*
1018	 * Read complete register set in one go.
1019	 */
1020	if (ptrace(PTRACE_GETREGS, tcp->pid, NULL, (void *)&regs) == -1)
1021		return -1;
1022
1023	/*
1024	 * We only need to grab the syscall number on syscall entry.
1025	 */
1026	if (regs.ARM_ip == 0) {
1027		if (!(tcp->flags & TCB_INSYSCALL)) {
1028			/* Check if we return from execve. */
1029			if (tcp->flags & TCB_WAITEXECVE) {
1030				tcp->flags &= ~TCB_WAITEXECVE;
1031				return 0;
1032			}
1033		}
1034
1035		/*
1036		 * Note: we only deal with only 32-bit CPUs here.
1037		 */
1038		if (regs.ARM_cpsr & 0x20) {
1039			/*
1040			 * Get the Thumb-mode system call number
1041			 */
1042			scno = regs.ARM_r7;
1043		} else {
1044			/*
1045			 * Get the ARM-mode system call number
1046			 */
1047			errno = 0;
1048			scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (void *)(regs.ARM_pc - 4), NULL);
1049			if (errno)
1050				return -1;
1051
1052			if (scno == 0 && (tcp->flags & TCB_WAITEXECVE)) {
1053				tcp->flags &= ~TCB_WAITEXECVE;
1054				return 0;
1055			}
1056
1057			/* Handle the EABI syscall convention.  We do not
1058			   bother converting structures between the two
1059			   ABIs, but basic functionality should work even
1060			   if strace and the traced program have different
1061			   ABIs.  */
1062			if (scno == 0xef000000) {
1063				scno = regs.ARM_r7;
1064			} else {
1065				if ((scno & 0x0ff00000) != 0x0f900000) {
1066					fprintf(stderr, "syscall: unknown syscall trap 0x%08lx\n",
1067						scno);
1068					return -1;
1069				}
1070
1071				/*
1072				 * Fixup the syscall number
1073				 */
1074				scno &= 0x000fffff;
1075			}
1076		}
1077		if (scno & 0x0f0000) {
1078			/*
1079			 * Handle ARM specific syscall
1080			 */
1081			set_personality(1);
1082			scno &= 0x0000ffff;
1083		} else
1084			set_personality(0);
1085
1086		if (tcp->flags & TCB_INSYSCALL) {
1087			fprintf(stderr, "pid %d stray syscall entry\n", tcp->pid);
1088			tcp->flags &= ~TCB_INSYSCALL;
1089		}
1090	} else {
1091		if (!(tcp->flags & TCB_INSYSCALL)) {
1092			fprintf(stderr, "pid %d stray syscall exit\n", tcp->pid);
1093			tcp->flags |= TCB_INSYSCALL;
1094		}
1095	}
1096# elif defined (M68K)
1097	if (upeek(tcp, 4*PT_ORIG_D0, &scno) < 0)
1098		return -1;
1099# elif defined (LINUX_MIPSN32)
1100	unsigned long long regs[38];
1101
1102	if (ptrace (PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
1103		return -1;
1104	a3 = regs[REG_A3];
1105	r2 = regs[REG_V0];
1106
1107	if(!(tcp->flags & TCB_INSYSCALL)) {
1108		scno = r2;
1109
1110		/* Check if we return from execve. */
1111		if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1112			tcp->flags &= ~TCB_WAITEXECVE;
1113			return 0;
1114		}
1115
1116		if (scno < 0 || scno > nsyscalls) {
1117			if(a3 == 0 || a3 == -1) {
1118				if(debug)
1119					fprintf (stderr, "stray syscall exit: v0 = %ld\n", scno);
1120				return 0;
1121			}
1122		}
1123	}
1124# elif defined (MIPS)
1125	if (upeek(tcp, REG_A3, &a3) < 0)
1126		return -1;
1127	if(!(tcp->flags & TCB_INSYSCALL)) {
1128		if (upeek(tcp, REG_V0, &scno) < 0)
1129			return -1;
1130
1131		/* Check if we return from execve. */
1132		if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1133			tcp->flags &= ~TCB_WAITEXECVE;
1134			return 0;
1135		}
1136
1137		if (scno < 0 || scno > nsyscalls) {
1138			if(a3 == 0 || a3 == -1) {
1139				if(debug)
1140					fprintf (stderr, "stray syscall exit: v0 = %ld\n", scno);
1141				return 0;
1142			}
1143		}
1144	} else {
1145		if (upeek(tcp, REG_V0, &r2) < 0)
1146			return -1;
1147	}
1148# elif defined (ALPHA)
1149	if (upeek(tcp, REG_A3, &a3) < 0)
1150		return -1;
1151
1152	if (!(tcp->flags & TCB_INSYSCALL)) {
1153		if (upeek(tcp, REG_R0, &scno) < 0)
1154			return -1;
1155
1156		/* Check if we return from execve. */
1157		if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1158			tcp->flags &= ~TCB_WAITEXECVE;
1159			return 0;
1160		}
1161
1162		/*
1163		 * Do some sanity checks to figure out if it's
1164		 * really a syscall entry
1165		 */
1166		if (scno < 0 || scno > nsyscalls) {
1167			if (a3 == 0 || a3 == -1) {
1168				if (debug)
1169					fprintf (stderr, "stray syscall exit: r0 = %ld\n", scno);
1170				return 0;
1171			}
1172		}
1173	}
1174	else {
1175		if (upeek(tcp, REG_R0, &r0) < 0)
1176			return -1;
1177	}
1178# elif defined (SPARC) || defined (SPARC64)
1179	/* Everything we need is in the current register set. */
1180	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1181		return -1;
1182
1183	/* If we are entering, then disassemble the syscall trap. */
1184	if (!(tcp->flags & TCB_INSYSCALL)) {
1185		/* Retrieve the syscall trap instruction. */
1186		errno = 0;
1187#  if defined(SPARC64)
1188		trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.tpc, 0);
1189		trap >>= 32;
1190#  else
1191		trap = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)regs.pc, 0);
1192#  endif
1193		if (errno)
1194			return -1;
1195
1196		/* Disassemble the trap to see what personality to use. */
1197		switch (trap) {
1198		case 0x91d02010:
1199			/* Linux/SPARC syscall trap. */
1200			set_personality(0);
1201			break;
1202		case 0x91d0206d:
1203			/* Linux/SPARC64 syscall trap. */
1204			set_personality(2);
1205			break;
1206		case 0x91d02000:
1207			/* SunOS syscall trap. (pers 1) */
1208			fprintf(stderr,"syscall: SunOS no support\n");
1209			return -1;
1210		case 0x91d02008:
1211			/* Solaris 2.x syscall trap. (per 2) */
1212			set_personality(1);
1213			break;
1214		case 0x91d02009:
1215			/* NetBSD/FreeBSD syscall trap. */
1216			fprintf(stderr,"syscall: NetBSD/FreeBSD not supported\n");
1217			return -1;
1218		case 0x91d02027:
1219			/* Solaris 2.x gettimeofday */
1220			set_personality(1);
1221			break;
1222		default:
1223			/* Unknown syscall trap. */
1224			if(tcp->flags & TCB_WAITEXECVE) {
1225				tcp->flags &= ~TCB_WAITEXECVE;
1226				return 0;
1227			}
1228#  if defined (SPARC64)
1229			fprintf(stderr,"syscall: unknown syscall trap %08lx %016lx\n", trap, regs.tpc);
1230#  else
1231			fprintf(stderr,"syscall: unknown syscall trap %08lx %08lx\n", trap, regs.pc);
1232#  endif
1233			return -1;
1234		}
1235
1236		/* Extract the system call number from the registers. */
1237		if (trap == 0x91d02027)
1238			scno = 156;
1239		else
1240			scno = regs.u_regs[U_REG_G1];
1241		if (scno == 0) {
1242			scno = regs.u_regs[U_REG_O0];
1243			memmove (&regs.u_regs[U_REG_O0], &regs.u_regs[U_REG_O1], 7*sizeof(regs.u_regs[0]));
1244		}
1245	}
1246# elif defined(HPPA)
1247	if (upeek(tcp, PT_GR20, &scno) < 0)
1248		return -1;
1249	if (!(tcp->flags & TCB_INSYSCALL)) {
1250		/* Check if we return from execve. */
1251		if ((tcp->flags & TCB_WAITEXECVE)) {
1252			tcp->flags &= ~TCB_WAITEXECVE;
1253			return 0;
1254		}
1255	}
1256# elif defined(SH)
1257	/*
1258	 * In the new syscall ABI, the system call number is in R3.
1259	 */
1260	if (upeek(tcp, 4*(REG_REG0+3), &scno) < 0)
1261		return -1;
1262
1263	if (scno < 0) {
1264		/* Odd as it may seem, a glibc bug has been known to cause
1265		   glibc to issue bogus negative syscall numbers.  So for
1266		   our purposes, make strace print what it *should* have been */
1267		long correct_scno = (scno & 0xff);
1268		if (debug)
1269			fprintf(stderr,
1270				"Detected glibc bug: bogus system call"
1271				" number = %ld, correcting to %ld\n",
1272				scno,
1273				correct_scno);
1274		scno = correct_scno;
1275	}
1276
1277	if (!(tcp->flags & TCB_INSYSCALL)) {
1278		/* Check if we return from execve. */
1279		if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
1280			tcp->flags &= ~TCB_WAITEXECVE;
1281			return 0;
1282		}
1283	}
1284# elif defined(SH64)
1285	if (upeek(tcp, REG_SYSCALL, &scno) < 0)
1286		return -1;
1287	scno &= 0xFFFF;
1288
1289	if (!(tcp->flags & TCB_INSYSCALL)) {
1290		/* Check if we return from execve. */
1291		if (tcp->flags & TCB_WAITEXECVE) {
1292			tcp->flags &= ~TCB_WAITEXECVE;
1293			return 0;
1294		}
1295	}
1296# elif defined(CRISV10) || defined(CRISV32)
1297	if (upeek(tcp, 4*PT_R9, &scno) < 0)
1298		return -1;
1299# elif defined(TILE)
1300	if (upeek(tcp, PTREGS_OFFSET_REG(10), &scno) < 0)
1301		return -1;
1302
1303	if (!(tcp->flags & TCB_INSYSCALL)) {
1304		/* Check if we return from execve. */
1305		if (tcp->flags & TCB_WAITEXECVE) {
1306			tcp->flags &= ~TCB_WAITEXECVE;
1307			return 0;
1308		}
1309	}
1310# elif defined(MICROBLAZE)
1311	if (upeek(tcp, 0, &scno) < 0)
1312		return -1;
1313# endif
1314#endif /* LINUX */
1315
1316#ifdef SUNOS4
1317	if (upeek(tcp, uoff(u_arg[7]), &scno) < 0)
1318		return -1;
1319#elif defined(SH)
1320	/* new syscall ABI returns result in R0 */
1321	if (upeek(tcp, 4*REG_REG0, (long *)&r0) < 0)
1322		return -1;
1323#elif defined(SH64)
1324	/* ABI defines result returned in r9 */
1325	if (upeek(tcp, REG_GENERAL(9), (long *)&r9) < 0)
1326		return -1;
1327#endif
1328
1329#ifdef USE_PROCFS
1330# ifdef HAVE_PR_SYSCALL
1331	scno = tcp->status.PR_SYSCALL;
1332# else
1333#  ifndef FREEBSD
1334	scno = tcp->status.PR_WHAT;
1335#  else
1336	if (pread(tcp->pfd_reg, &regs, sizeof(regs), 0) < 0) {
1337		perror("pread");
1338		return -1;
1339	}
1340	switch (regs.r_eax) {
1341	case SYS_syscall:
1342	case SYS___syscall:
1343		pread(tcp->pfd, &scno, sizeof(scno), regs.r_esp + sizeof(int));
1344		break;
1345	default:
1346		scno = regs.r_eax;
1347		break;
1348	}
1349#  endif /* FREEBSD */
1350# endif /* !HAVE_PR_SYSCALL */
1351#endif /* USE_PROCFS */
1352
1353	if (!(tcp->flags & TCB_INSYSCALL))
1354		tcp->scno = scno;
1355	return 1;
1356}
1357
1358
1359long
1360known_scno(tcp)
1361struct tcb *tcp;
1362{
1363	long scno = tcp->scno;
1364	if (scno >= 0 && scno < nsyscalls && sysent[scno].native_scno != 0)
1365		scno = sysent[scno].native_scno;
1366	else
1367		scno += NR_SYSCALL_BASE;
1368	return scno;
1369}
1370
1371/* Called in trace_syscall() at each syscall entry and exit.
1372 * Returns:
1373 * 0: "ignore this syscall", bail out of trace_syscall() silently.
1374 * 1: ok, continue in trace_syscall().
1375 * other: error, trace_syscall() should print error indicator
1376 *    ("????" etc) and bail out.
1377 */
1378static int
1379syscall_fixup(struct tcb *tcp)
1380{
1381#ifdef USE_PROCFS
1382	int scno = known_scno(tcp);
1383
1384	if (!(tcp->flags & TCB_INSYSCALL)) {
1385		if (tcp->status.PR_WHY != PR_SYSENTRY) {
1386			if (
1387			    scno == SYS_fork
1388#ifdef SYS_vfork
1389			    || scno == SYS_vfork
1390#endif /* SYS_vfork */
1391#ifdef SYS_fork1
1392			    || scno == SYS_fork1
1393#endif /* SYS_fork1 */
1394#ifdef SYS_forkall
1395			    || scno == SYS_forkall
1396#endif /* SYS_forkall */
1397#ifdef SYS_rfork1
1398			    || scno == SYS_rfork1
1399#endif /* SYS_fork1 */
1400#ifdef SYS_rforkall
1401			    || scno == SYS_rforkall
1402#endif /* SYS_rforkall */
1403			    ) {
1404				/* We are returning in the child, fake it. */
1405				tcp->status.PR_WHY = PR_SYSENTRY;
1406				trace_syscall(tcp);
1407				tcp->status.PR_WHY = PR_SYSEXIT;
1408			}
1409			else {
1410				fprintf(stderr, "syscall: missing entry\n");
1411				tcp->flags |= TCB_INSYSCALL;
1412			}
1413		}
1414	}
1415	else {
1416		if (tcp->status.PR_WHY != PR_SYSEXIT) {
1417			fprintf(stderr, "syscall: missing exit\n");
1418			tcp->flags &= ~TCB_INSYSCALL;
1419		}
1420	}
1421#endif /* USE_PROCFS */
1422#ifdef SUNOS4
1423	if (!(tcp->flags & TCB_INSYSCALL)) {
1424		if (scno == 0) {
1425			fprintf(stderr, "syscall: missing entry\n");
1426			tcp->flags |= TCB_INSYSCALL;
1427		}
1428	}
1429	else {
1430		if (scno != 0) {
1431			if (debug) {
1432				/*
1433				 * This happens when a signal handler
1434				 * for a signal which interrupted a
1435				 * a system call makes another system call.
1436				 */
1437				fprintf(stderr, "syscall: missing exit\n");
1438			}
1439			tcp->flags &= ~TCB_INSYSCALL;
1440		}
1441	}
1442#endif /* SUNOS4 */
1443#ifdef LINUX
1444#if defined (I386)
1445	if (upeek(tcp, 4*EAX, &eax) < 0)
1446		return -1;
1447	if (eax != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1448		if (debug)
1449			fprintf(stderr, "stray syscall exit: eax = %ld\n", eax);
1450		return 0;
1451	}
1452#elif defined (X86_64)
1453	if (upeek(tcp, 8*RAX, &rax) < 0)
1454		return -1;
1455	if (current_personality == 1)
1456		rax = (long int)(int)rax; /* sign extend from 32 bits */
1457	if (rax != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1458		if (debug)
1459			fprintf(stderr, "stray syscall exit: rax = %ld\n", rax);
1460		return 0;
1461	}
1462#elif defined (S390) || defined (S390X)
1463	if (upeek(tcp, PT_GPR2, &gpr2) < 0)
1464		return -1;
1465	if (syscall_mode != -ENOSYS)
1466		syscall_mode = tcp->scno;
1467	if (gpr2 != syscall_mode && !(tcp->flags & TCB_INSYSCALL)) {
1468		if (debug)
1469			fprintf(stderr, "stray syscall exit: gpr2 = %ld\n", gpr2);
1470		return 0;
1471	}
1472	else if (((tcp->flags & (TCB_INSYSCALL|TCB_WAITEXECVE))
1473		  == (TCB_INSYSCALL|TCB_WAITEXECVE))
1474		 && (gpr2 == -ENOSYS || gpr2 == tcp->scno)) {
1475		/*
1476		 * Fake a return value of zero.  We leave the TCB_WAITEXECVE
1477		 * flag set for the post-execve SIGTRAP to see and reset.
1478		 */
1479		gpr2 = 0;
1480	}
1481#elif defined (POWERPC)
1482# define SO_MASK 0x10000000
1483	if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1484		return -1;
1485	if (upeek(tcp, sizeof(unsigned long)*PT_R3, &result) < 0)
1486		return -1;
1487	if (flags & SO_MASK)
1488		result = -result;
1489#elif defined (M68K)
1490	if (upeek(tcp, 4*PT_D0, &d0) < 0)
1491		return -1;
1492	if (d0 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1493		if (debug)
1494			fprintf(stderr, "stray syscall exit: d0 = %ld\n", d0);
1495		return 0;
1496	}
1497#elif defined (ARM)
1498	/*
1499	 * Nothing required
1500	 */
1501#elif defined(BFIN)
1502	if (upeek(tcp, PT_R0, &r0) < 0)
1503		return -1;
1504#elif defined (HPPA)
1505	if (upeek(tcp, PT_GR28, &r28) < 0)
1506		return -1;
1507#elif defined(IA64)
1508	if (upeek(tcp, PT_R10, &r10) < 0)
1509		return -1;
1510	if (upeek(tcp, PT_R8, &r8) < 0)
1511		return -1;
1512	if (ia32 && r8 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1513		if (debug)
1514			fprintf(stderr, "stray syscall exit: r8 = %ld\n", r8);
1515		return 0;
1516	}
1517#elif defined(CRISV10) || defined(CRISV32)
1518	if (upeek(tcp, 4*PT_R10, &r10) < 0)
1519		return -1;
1520	if (r10 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1521		if (debug)
1522			fprintf(stderr, "stray syscall exit: r10 = %ld\n", r10);
1523		return 0;
1524	}
1525#elif defined(MICROBLAZE)
1526	if (upeek(tcp, 3 * 4, &r3) < 0)
1527		return -1;
1528	if (r3 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1529		if (debug)
1530			fprintf(stderr, "stray syscall exit: r3 = %ld\n", r3);
1531		return 0;
1532	}
1533#endif
1534#endif /* LINUX */
1535	return 1;
1536}
1537
1538#ifdef LINUX
1539/*
1540 * Check the syscall return value register value for whether it is
1541 * a negated errno code indicating an error, or a success return value.
1542 */
1543static inline int
1544is_negated_errno(unsigned long int val)
1545{
1546	unsigned long int max = -(long int) nerrnos;
1547	if (personality_wordsize[current_personality] < sizeof(val)) {
1548		val = (unsigned int) val;
1549		max = (unsigned int) max;
1550	}
1551	return val > max;
1552}
1553#endif
1554
1555static int
1556get_error(struct tcb *tcp)
1557{
1558	int u_error = 0;
1559#ifdef LINUX
1560# if defined(S390) || defined(S390X)
1561	if (is_negated_errno(gpr2)) {
1562		tcp->u_rval = -1;
1563		u_error = -gpr2;
1564	}
1565	else {
1566		tcp->u_rval = gpr2;
1567		u_error = 0;
1568	}
1569# elif defined(I386)
1570	if (is_negated_errno(eax)) {
1571		tcp->u_rval = -1;
1572		u_error = -eax;
1573	}
1574	else {
1575		tcp->u_rval = eax;
1576		u_error = 0;
1577	}
1578# elif defined(X86_64)
1579	if (is_negated_errno(rax)) {
1580		tcp->u_rval = -1;
1581		u_error = -rax;
1582	}
1583	else {
1584		tcp->u_rval = rax;
1585		u_error = 0;
1586	}
1587# elif defined(IA64)
1588	if (ia32) {
1589		int err;
1590
1591		err = (int)r8;
1592		if (is_negated_errno(err)) {
1593			tcp->u_rval = -1;
1594			u_error = -err;
1595		}
1596		else {
1597			tcp->u_rval = err;
1598			u_error = 0;
1599		}
1600	} else {
1601		if (r10) {
1602			tcp->u_rval = -1;
1603			u_error = r8;
1604		} else {
1605			tcp->u_rval = r8;
1606			u_error = 0;
1607		}
1608	}
1609# elif defined(MIPS)
1610		if (a3) {
1611			tcp->u_rval = -1;
1612			u_error = r2;
1613		} else {
1614			tcp->u_rval = r2;
1615			u_error = 0;
1616		}
1617# elif defined(POWERPC)
1618		if (is_negated_errno(result)) {
1619			tcp->u_rval = -1;
1620			u_error = -result;
1621		}
1622		else {
1623			tcp->u_rval = result;
1624			u_error = 0;
1625		}
1626# elif defined(M68K)
1627		if (is_negated_errno(d0)) {
1628			tcp->u_rval = -1;
1629			u_error = -d0;
1630		}
1631		else {
1632			tcp->u_rval = d0;
1633			u_error = 0;
1634		}
1635# elif defined(ARM)
1636		if (is_negated_errno(regs.ARM_r0)) {
1637			tcp->u_rval = -1;
1638			u_error = -regs.ARM_r0;
1639		}
1640		else {
1641			tcp->u_rval = regs.ARM_r0;
1642			u_error = 0;
1643		}
1644# elif defined(AVR32)
1645		if (regs.r12 && (unsigned) -regs.r12 < nerrnos) {
1646			tcp->u_rval = -1;
1647			u_error = -regs.r12;
1648		}
1649		else {
1650			tcp->u_rval = regs.r12;
1651			u_error = 0;
1652		}
1653# elif defined(BFIN)
1654		if (is_negated_errno(r0)) {
1655			tcp->u_rval = -1;
1656			u_error = -r0;
1657		} else {
1658			tcp->u_rval = r0;
1659			u_error = 0;
1660		}
1661# elif defined(ALPHA)
1662		if (a3) {
1663			tcp->u_rval = -1;
1664			u_error = r0;
1665		}
1666		else {
1667			tcp->u_rval = r0;
1668			u_error = 0;
1669		}
1670# elif defined(SPARC)
1671		if (regs.psr & PSR_C) {
1672			tcp->u_rval = -1;
1673			u_error = regs.u_regs[U_REG_O0];
1674		}
1675		else {
1676			tcp->u_rval = regs.u_regs[U_REG_O0];
1677			u_error = 0;
1678		}
1679# elif defined(SPARC64)
1680		if (regs.tstate & 0x1100000000UL) {
1681			tcp->u_rval = -1;
1682			u_error = regs.u_regs[U_REG_O0];
1683		}
1684		else {
1685			tcp->u_rval = regs.u_regs[U_REG_O0];
1686			u_error = 0;
1687		}
1688# elif defined(HPPA)
1689		if (is_negated_errno(r28)) {
1690			tcp->u_rval = -1;
1691			u_error = -r28;
1692		}
1693		else {
1694			tcp->u_rval = r28;
1695			u_error = 0;
1696		}
1697# elif defined(SH)
1698		/* interpret R0 as return value or error number */
1699		if (is_negated_errno(r0)) {
1700			tcp->u_rval = -1;
1701			u_error = -r0;
1702		}
1703		else {
1704			tcp->u_rval = r0;
1705			u_error = 0;
1706		}
1707# elif defined(SH64)
1708		/* interpret result as return value or error number */
1709		if (is_negated_errno(r9)) {
1710			tcp->u_rval = -1;
1711			u_error = -r9;
1712		}
1713		else {
1714			tcp->u_rval = r9;
1715			u_error = 0;
1716		}
1717# elif defined(CRISV10) || defined(CRISV32)
1718		if (r10 && (unsigned) -r10 < nerrnos) {
1719			tcp->u_rval = -1;
1720			u_error = -r10;
1721		}
1722		else {
1723			tcp->u_rval = r10;
1724			u_error = 0;
1725		}
1726# elif defined(TILE)
1727		long rval;
1728		/* interpret result as return value or error number */
1729		if (upeek(tcp, PTREGS_OFFSET_REG(0), &rval) < 0)
1730			return -1;
1731		if (rval < 0 && rval > -nerrnos) {
1732			tcp->u_rval = -1;
1733			u_error = -rval;
1734		}
1735		else {
1736			tcp->u_rval = rval;
1737			u_error = 0;
1738		}
1739# elif defined(MICROBLAZE)
1740		/* interpret result as return value or error number */
1741		if (is_negated_errno(r3)) {
1742			tcp->u_rval = -1;
1743			u_error = -r3;
1744		}
1745		else {
1746			tcp->u_rval = r3;
1747			u_error = 0;
1748		}
1749# endif
1750#endif /* LINUX */
1751#ifdef SUNOS4
1752		/* get error code from user struct */
1753		if (upeek(tcp, uoff(u_error), &u_error) < 0)
1754			return -1;
1755		u_error >>= 24; /* u_error is a char */
1756
1757		/* get system call return value */
1758		if (upeek(tcp, uoff(u_rval1), &tcp->u_rval) < 0)
1759			return -1;
1760#endif /* SUNOS4 */
1761#ifdef SVR4
1762#ifdef SPARC
1763		/* Judicious guessing goes a long way. */
1764		if (tcp->status.pr_reg[R_PSR] & 0x100000) {
1765			tcp->u_rval = -1;
1766			u_error = tcp->status.pr_reg[R_O0];
1767		}
1768		else {
1769			tcp->u_rval = tcp->status.pr_reg[R_O0];
1770			u_error = 0;
1771		}
1772#endif /* SPARC */
1773#ifdef I386
1774		/* Wanna know how to kill an hour single-stepping? */
1775		if (tcp->status.PR_REG[EFL] & 0x1) {
1776			tcp->u_rval = -1;
1777			u_error = tcp->status.PR_REG[EAX];
1778		}
1779		else {
1780			tcp->u_rval = tcp->status.PR_REG[EAX];
1781#ifdef HAVE_LONG_LONG
1782			tcp->u_lrval =
1783				((unsigned long long) tcp->status.PR_REG[EDX] << 32) +
1784				tcp->status.PR_REG[EAX];
1785#endif
1786			u_error = 0;
1787		}
1788#endif /* I386 */
1789#ifdef X86_64
1790		/* Wanna know how to kill an hour single-stepping? */
1791		if (tcp->status.PR_REG[EFLAGS] & 0x1) {
1792			tcp->u_rval = -1;
1793			u_error = tcp->status.PR_REG[RAX];
1794		}
1795		else {
1796			tcp->u_rval = tcp->status.PR_REG[RAX];
1797			u_error = 0;
1798		}
1799#endif /* X86_64 */
1800#ifdef MIPS
1801		if (tcp->status.pr_reg[CTX_A3]) {
1802			tcp->u_rval = -1;
1803			u_error = tcp->status.pr_reg[CTX_V0];
1804		}
1805		else {
1806			tcp->u_rval = tcp->status.pr_reg[CTX_V0];
1807			u_error = 0;
1808		}
1809#endif /* MIPS */
1810#endif /* SVR4 */
1811#ifdef FREEBSD
1812		if (regs.r_eflags & PSL_C) {
1813			tcp->u_rval = -1;
1814		        u_error = regs.r_eax;
1815		} else {
1816			tcp->u_rval = regs.r_eax;
1817			tcp->u_lrval =
1818			  ((unsigned long long) regs.r_edx << 32) +  regs.r_eax;
1819		        u_error = 0;
1820		}
1821#endif /* FREEBSD */
1822	tcp->u_error = u_error;
1823	return 1;
1824}
1825
1826int
1827force_result(tcp, error, rval)
1828	struct tcb *tcp;
1829	int error;
1830	long rval;
1831{
1832#ifdef LINUX
1833# if defined(S390) || defined(S390X)
1834	gpr2 = error ? -error : rval;
1835	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)PT_GPR2, gpr2) < 0)
1836		return -1;
1837# elif defined(I386)
1838	eax = error ? -error : rval;
1839	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(EAX * 4), eax) < 0)
1840		return -1;
1841# elif defined(X86_64)
1842	rax = error ? -error : rval;
1843	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(RAX * 8), rax) < 0)
1844		return -1;
1845# elif defined(IA64)
1846	if (ia32) {
1847		r8 = error ? -error : rval;
1848		if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R8), r8) < 0)
1849			return -1;
1850	}
1851	else {
1852		if (error) {
1853			r8 = error;
1854			r10 = -1;
1855		}
1856		else {
1857			r8 = rval;
1858			r10 = 0;
1859		}
1860		if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R8), r8) < 0 ||
1861		    ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_R10), r10) < 0)
1862			return -1;
1863	}
1864# elif defined(BFIN)
1865	r0 = error ? -error : rval;
1866	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)PT_R0, r0) < 0)
1867		return -1;
1868# elif defined(MIPS)
1869	if (error) {
1870		r2 = error;
1871		a3 = -1;
1872	}
1873	else {
1874		r2 = rval;
1875		a3 = 0;
1876	}
1877	/* PTRACE_POKEUSER is OK even for n32 since rval is only a long.  */
1878	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), a3) < 0 ||
1879	    ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_V0), r2) < 0)
1880		return -1;
1881# elif defined(POWERPC)
1882	if (upeek(tcp, sizeof(unsigned long)*PT_CCR, &flags) < 0)
1883		return -1;
1884	if (error) {
1885		flags |= SO_MASK;
1886		result = error;
1887	}
1888	else {
1889		flags &= ~SO_MASK;
1890		result = rval;
1891	}
1892	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(sizeof(unsigned long)*PT_CCR), flags) < 0 ||
1893	    ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(sizeof(unsigned long)*PT_R3), result) < 0)
1894		return -1;
1895# elif defined(M68K)
1896	d0 = error ? -error : rval;
1897	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*PT_D0), d0) < 0)
1898		return -1;
1899# elif defined(ARM)
1900	regs.ARM_r0 = error ? -error : rval;
1901	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*0), regs.ARM_r0) < 0)
1902		return -1;
1903# elif defined(AVR32)
1904	regs.r12 = error ? -error : rval;
1905	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)REG_R12, regs.r12) < 0)
1906		return -1;
1907# elif defined(ALPHA)
1908	if (error) {
1909		a3 = -1;
1910		r0 = error;
1911	}
1912	else {
1913		a3 = 0;
1914		r0 = rval;
1915	}
1916	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_A3), a3) < 0 ||
1917	    ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(REG_R0), r0) < 0)
1918		return -1;
1919# elif defined(SPARC)
1920	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1921		return -1;
1922	if (error) {
1923		regs.psr |= PSR_C;
1924		regs.u_regs[U_REG_O0] = error;
1925	}
1926	else {
1927		regs.psr &= ~PSR_C;
1928		regs.u_regs[U_REG_O0] = rval;
1929	}
1930	if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0)
1931		return -1;
1932# elif defined(SPARC64)
1933	if (ptrace(PTRACE_GETREGS, tcp->pid, (char *)&regs, 0) < 0)
1934		return -1;
1935	if (error) {
1936		regs.tstate |= 0x1100000000UL;
1937		regs.u_regs[U_REG_O0] = error;
1938	}
1939	else {
1940		regs.tstate &= ~0x1100000000UL;
1941		regs.u_regs[U_REG_O0] = rval;
1942	}
1943	if (ptrace(PTRACE_SETREGS, tcp->pid, (char *)&regs, 0) < 0)
1944		return -1;
1945# elif defined(HPPA)
1946	r28 = error ? -error : rval;
1947	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(PT_GR28), r28) < 0)
1948		return -1;
1949# elif defined(SH)
1950	r0 = error ? -error : rval;
1951	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)(4*REG_REG0), r0) < 0)
1952		return -1;
1953# elif defined(SH64)
1954	r9 = error ? -error : rval;
1955	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)REG_GENERAL(9), r9) < 0)
1956		return -1;
1957# endif
1958#endif /* LINUX */
1959
1960#ifdef SUNOS4
1961	if (ptrace(PTRACE_POKEUSER, tcp->pid, (char*)uoff(u_error),
1962		   error << 24) < 0 ||
1963	    ptrace(PTRACE_POKEUSER, tcp->pid, (char*)uoff(u_rval1), rval) < 0)
1964		return -1;
1965#endif /* SUNOS4 */
1966
1967#ifdef SVR4
1968	/* XXX no clue */
1969	return -1;
1970#endif /* SVR4 */
1971
1972#ifdef FREEBSD
1973	if (pread(tcp->pfd_reg, &regs, sizeof(regs), 0) < 0) {
1974		perror("pread");
1975		return -1;
1976	}
1977	if (error) {
1978		regs.r_eflags |= PSL_C;
1979		regs.r_eax = error;
1980	}
1981	else {
1982		regs.r_eflags &= ~PSL_C;
1983		regs.r_eax = rval;
1984	}
1985	if (pwrite(tcp->pfd_reg, &regs, sizeof(regs), 0) < 0) {
1986		perror("pwrite");
1987		return -1;
1988	}
1989#endif /* FREEBSD */
1990
1991	/* All branches reach here on success (only).  */
1992	tcp->u_error = error;
1993	tcp->u_rval = rval;
1994	return 0;
1995}
1996
1997static int
1998syscall_enter(struct tcb *tcp)
1999{
2000#ifdef LINUX
2001#if defined(S390) || defined(S390X)
2002	{
2003		int i;
2004		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2005			tcp->u_nargs = sysent[tcp->scno].nargs;
2006		else
2007			tcp->u_nargs = MAX_ARGS;
2008		for (i = 0; i < tcp->u_nargs; i++) {
2009			if (upeek(tcp,i==0 ? PT_ORIGGPR2:PT_GPR2+i*sizeof(long), &tcp->u_arg[i]) < 0)
2010				return -1;
2011		}
2012	}
2013#elif defined (ALPHA)
2014	{
2015		int i;
2016		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2017			tcp->u_nargs = sysent[tcp->scno].nargs;
2018		else
2019			tcp->u_nargs = MAX_ARGS;
2020		for (i = 0; i < tcp->u_nargs; i++) {
2021			/* WTA: if scno is out-of-bounds this will bomb. Add range-check
2022			 * for scno somewhere above here!
2023			 */
2024			if (upeek(tcp, REG_A0+i, &tcp->u_arg[i]) < 0)
2025				return -1;
2026		}
2027	}
2028#elif defined (IA64)
2029	{
2030		if (!ia32) {
2031			unsigned long *out0, cfm, sof, sol, i;
2032			long rbs_end;
2033			/* be backwards compatible with kernel < 2.4.4... */
2034#			ifndef PT_RBS_END
2035#			  define PT_RBS_END	PT_AR_BSP
2036#			endif
2037
2038			if (upeek(tcp, PT_RBS_END, &rbs_end) < 0)
2039				return -1;
2040			if (upeek(tcp, PT_CFM, (long *) &cfm) < 0)
2041				return -1;
2042
2043			sof = (cfm >> 0) & 0x7f;
2044			sol = (cfm >> 7) & 0x7f;
2045			out0 = ia64_rse_skip_regs((unsigned long *) rbs_end, -sof + sol);
2046
2047			if (tcp->scno >= 0 && tcp->scno < nsyscalls
2048			    && sysent[tcp->scno].nargs != -1)
2049				tcp->u_nargs = sysent[tcp->scno].nargs;
2050			else
2051				tcp->u_nargs = MAX_ARGS;
2052			for (i = 0; i < tcp->u_nargs; ++i) {
2053				if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
2054					   sizeof(long), (char *) &tcp->u_arg[i]) < 0)
2055					return -1;
2056			}
2057		} else {
2058			int i;
2059
2060			if (/* EBX = out0 */
2061			    upeek(tcp, PT_R11, (long *) &tcp->u_arg[0]) < 0
2062			    /* ECX = out1 */
2063			    || upeek(tcp, PT_R9,  (long *) &tcp->u_arg[1]) < 0
2064			    /* EDX = out2 */
2065			    || upeek(tcp, PT_R10, (long *) &tcp->u_arg[2]) < 0
2066			    /* ESI = out3 */
2067			    || upeek(tcp, PT_R14, (long *) &tcp->u_arg[3]) < 0
2068			    /* EDI = out4 */
2069			    || upeek(tcp, PT_R15, (long *) &tcp->u_arg[4]) < 0
2070			    /* EBP = out5 */
2071			    || upeek(tcp, PT_R13, (long *) &tcp->u_arg[5]) < 0)
2072				return -1;
2073
2074			for (i = 0; i < 6; ++i)
2075				/* truncate away IVE sign-extension */
2076				tcp->u_arg[i] &= 0xffffffff;
2077
2078			if (tcp->scno >= 0 && tcp->scno < nsyscalls
2079			    && sysent[tcp->scno].nargs != -1)
2080				tcp->u_nargs = sysent[tcp->scno].nargs;
2081			else
2082				tcp->u_nargs = 5;
2083		}
2084	}
2085#elif defined (LINUX_MIPSN32) || defined (LINUX_MIPSN64)
2086	/* N32 and N64 both use up to six registers.  */
2087	{
2088		unsigned long long regs[38];
2089		int i, nargs;
2090
2091		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2092			nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
2093		else
2094			nargs = tcp->u_nargs = MAX_ARGS;
2095
2096		if (ptrace (PTRACE_GETREGS, tcp->pid, NULL, (long) &regs) < 0)
2097			return -1;
2098
2099		for(i = 0; i < nargs; i++) {
2100			tcp->u_arg[i] = regs[REG_A0 + i];
2101# if defined (LINUX_MIPSN32)
2102			tcp->ext_arg[i] = regs[REG_A0 + i];
2103# endif
2104		}
2105	}
2106#elif defined (MIPS)
2107	{
2108		long sp;
2109		int i, nargs;
2110
2111		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2112			nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
2113		else
2114			nargs = tcp->u_nargs = MAX_ARGS;
2115		if(nargs > 4) {
2116			if(upeek(tcp, REG_SP, &sp) < 0)
2117				return -1;
2118			for(i = 0; i < 4; i++) {
2119				if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i])<0)
2120					return -1;
2121			}
2122			umoven(tcp, sp+16, (nargs-4) * sizeof(tcp->u_arg[0]),
2123			       (char *)(tcp->u_arg + 4));
2124		} else {
2125			for(i = 0; i < nargs; i++) {
2126				if (upeek(tcp, REG_A0 + i, &tcp->u_arg[i]) < 0)
2127					return -1;
2128			}
2129		}
2130	}
2131#elif defined (POWERPC)
2132# ifndef PT_ORIG_R3
2133#  define PT_ORIG_R3 34
2134# endif
2135	{
2136		int i;
2137		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2138			tcp->u_nargs = sysent[tcp->scno].nargs;
2139		else
2140			tcp->u_nargs = MAX_ARGS;
2141		for (i = 0; i < tcp->u_nargs; i++) {
2142			if (upeek(tcp, (i==0) ?
2143				(sizeof(unsigned long)*PT_ORIG_R3) :
2144				((i+PT_R3)*sizeof(unsigned long)),
2145					&tcp->u_arg[i]) < 0)
2146				return -1;
2147		}
2148	}
2149#elif defined (SPARC) || defined (SPARC64)
2150	{
2151		int i;
2152
2153		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2154			tcp->u_nargs = sysent[tcp->scno].nargs;
2155		else
2156			tcp->u_nargs = MAX_ARGS;
2157		for (i = 0; i < tcp->u_nargs; i++)
2158			tcp->u_arg[i] = regs.u_regs[U_REG_O0 + i];
2159	}
2160#elif defined (HPPA)
2161	{
2162		int i;
2163
2164		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2165			tcp->u_nargs = sysent[tcp->scno].nargs;
2166		else
2167			tcp->u_nargs = MAX_ARGS;
2168		for (i = 0; i < tcp->u_nargs; i++) {
2169			if (upeek(tcp, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
2170				return -1;
2171		}
2172	}
2173#elif defined(ARM)
2174	{
2175		int i;
2176
2177		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2178			tcp->u_nargs = sysent[tcp->scno].nargs;
2179		else
2180			tcp->u_nargs = MAX_ARGS;
2181		for (i = 0; i < tcp->u_nargs; i++)
2182			tcp->u_arg[i] = regs.uregs[i];
2183	}
2184#elif defined(AVR32)
2185	tcp->u_nargs = sysent[tcp->scno].nargs;
2186	tcp->u_arg[0] = regs.r12;
2187	tcp->u_arg[1] = regs.r11;
2188	tcp->u_arg[2] = regs.r10;
2189	tcp->u_arg[3] = regs.r9;
2190	tcp->u_arg[4] = regs.r5;
2191	tcp->u_arg[5] = regs.r3;
2192#elif defined(BFIN)
2193	{
2194		int i;
2195		int argreg[] = {PT_R0, PT_R1, PT_R2, PT_R3, PT_R4, PT_R5};
2196
2197		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2198			tcp->u_nargs = sysent[tcp->scno].nargs;
2199		else
2200			tcp->u_nargs = sizeof(argreg) / sizeof(argreg[0]);
2201
2202		for (i = 0; i < tcp->u_nargs; ++i)
2203			if (upeek(tcp, argreg[i], &tcp->u_arg[i]) < 0)
2204				return -1;
2205	}
2206#elif defined(SH)
2207	{
2208		int i;
2209		static int syscall_regs[] = {
2210			REG_REG0+4, REG_REG0+5, REG_REG0+6, REG_REG0+7,
2211			REG_REG0, REG_REG0+1, REG_REG0+2
2212		};
2213
2214		tcp->u_nargs = sysent[tcp->scno].nargs;
2215		for (i = 0; i < tcp->u_nargs; i++) {
2216			if (upeek(tcp, 4*syscall_regs[i], &tcp->u_arg[i]) < 0)
2217				return -1;
2218		}
2219	}
2220#elif defined(SH64)
2221	{
2222		int i;
2223		/* Registers used by SH5 Linux system calls for parameters */
2224		static int syscall_regs[] = { 2, 3, 4, 5, 6, 7 };
2225
2226		/*
2227		 * TODO: should also check that the number of arguments encoded
2228		 *       in the trap number matches the number strace expects.
2229		 */
2230		/*
2231		assert(sysent[tcp->scno].nargs <
2232		       sizeof(syscall_regs)/sizeof(syscall_regs[0]));
2233		 */
2234
2235		tcp->u_nargs = sysent[tcp->scno].nargs;
2236		for (i = 0; i < tcp->u_nargs; i++) {
2237			if (upeek(tcp, REG_GENERAL(syscall_regs[i]), &tcp->u_arg[i]) < 0)
2238				return -1;
2239		}
2240	}
2241
2242#elif defined(X86_64)
2243	{
2244		int i;
2245		static int argreg[SUPPORTED_PERSONALITIES][MAX_ARGS] = {
2246			{RDI,RSI,RDX,R10,R8,R9},	/* x86-64 ABI */
2247			{RBX,RCX,RDX,RSI,RDI,RBP}	/* i386 ABI */
2248		};
2249
2250		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2251			tcp->u_nargs = sysent[tcp->scno].nargs;
2252		else
2253			tcp->u_nargs = MAX_ARGS;
2254		for (i = 0; i < tcp->u_nargs; i++) {
2255			if (upeek(tcp, argreg[current_personality][i]*8, &tcp->u_arg[i]) < 0)
2256				return -1;
2257		}
2258	}
2259#elif defined(MICROBLAZE)
2260	{
2261		int i;
2262		if (tcp->scno >= 0 && tcp->scno < nsyscalls)
2263			tcp->u_nargs = sysent[tcp->scno].nargs;
2264		else
2265			tcp->u_nargs = 0;
2266		for (i = 0; i < tcp->u_nargs; i++) {
2267			if (upeek(tcp, (5 + i) * 4, &tcp->u_arg[i]) < 0)
2268				return -1;
2269		}
2270	}
2271#elif defined(CRISV10) || defined(CRISV32)
2272	{
2273		int i;
2274		static const int crisregs[] = {
2275			4*PT_ORIG_R10, 4*PT_R11, 4*PT_R12,
2276			4*PT_R13, 4*PT_MOF, 4*PT_SRP
2277		};
2278
2279		if (tcp->scno >= 0 && tcp->scno < nsyscalls)
2280			tcp->u_nargs = sysent[tcp->scno].nargs;
2281		else
2282			tcp->u_nargs = 0;
2283		for (i = 0; i < tcp->u_nargs; i++) {
2284			if (upeek(tcp, crisregs[i], &tcp->u_arg[i]) < 0)
2285				return -1;
2286		}
2287	}
2288#elif defined(TILE)
2289	{
2290		int i;
2291		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2292			tcp->u_nargs = sysent[tcp->scno].nargs;
2293		else
2294			tcp->u_nargs = MAX_ARGS;
2295		for (i = 0; i < tcp->u_nargs; ++i) {
2296			if (upeek(tcp, PTREGS_OFFSET_REG(i), &tcp->u_arg[i]) < 0)
2297				return -1;
2298		}
2299	}
2300#elif defined (M68K)
2301	{
2302		int i;
2303		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2304			tcp->u_nargs = sysent[tcp->scno].nargs;
2305		else
2306			tcp->u_nargs = MAX_ARGS;
2307		for (i = 0; i < tcp->u_nargs; i++) {
2308			if (upeek(tcp, (i < 5 ? i : i + 2)*4, &tcp->u_arg[i]) < 0)
2309				return -1;
2310		}
2311	}
2312#else /* Other architecture (like i386) (32bits specific) */
2313	{
2314		int i;
2315		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2316			tcp->u_nargs = sysent[tcp->scno].nargs;
2317		else
2318			tcp->u_nargs = MAX_ARGS;
2319		for (i = 0; i < tcp->u_nargs; i++) {
2320			if (upeek(tcp, i*4, &tcp->u_arg[i]) < 0)
2321				return -1;
2322		}
2323	}
2324#endif
2325#endif /* LINUX */
2326#ifdef SUNOS4
2327	{
2328		int i;
2329		if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2330			tcp->u_nargs = sysent[tcp->scno].nargs;
2331		else
2332			tcp->u_nargs = MAX_ARGS;
2333		for (i = 0; i < tcp->u_nargs; i++) {
2334			struct user *u;
2335
2336			if (upeek(tcp, uoff(u_arg[0]) +
2337			    (i*sizeof(u->u_arg[0])), &tcp->u_arg[i]) < 0)
2338				return -1;
2339		}
2340	}
2341#endif /* SUNOS4 */
2342#ifdef SVR4
2343#ifdef MIPS
2344	/*
2345	 * SGI is broken: even though it has pr_sysarg, it doesn't
2346	 * set them on system call entry.  Get a clue.
2347	 */
2348	if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2349		tcp->u_nargs = sysent[tcp->scno].nargs;
2350	else
2351		tcp->u_nargs = tcp->status.pr_nsysarg;
2352	if (tcp->u_nargs > 4) {
2353		memcpy(tcp->u_arg, &tcp->status.pr_reg[CTX_A0],
2354			4*sizeof(tcp->u_arg[0]));
2355		umoven(tcp, tcp->status.pr_reg[CTX_SP] + 16,
2356			(tcp->u_nargs - 4)*sizeof(tcp->u_arg[0]), (char *) (tcp->u_arg + 4));
2357	}
2358	else {
2359		memcpy(tcp->u_arg, &tcp->status.pr_reg[CTX_A0],
2360			tcp->u_nargs*sizeof(tcp->u_arg[0]));
2361	}
2362#elif UNIXWARE >= 2
2363	/*
2364	 * Like SGI, UnixWare doesn't set pr_sysarg until system call exit
2365	 */
2366	if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2367		tcp->u_nargs = sysent[tcp->scno].nargs;
2368	else
2369		tcp->u_nargs = tcp->status.pr_lwp.pr_nsysarg;
2370	umoven(tcp, tcp->status.PR_REG[UESP] + 4,
2371		tcp->u_nargs*sizeof(tcp->u_arg[0]), (char *) tcp->u_arg);
2372#elif defined (HAVE_PR_SYSCALL)
2373	if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2374		tcp->u_nargs = sysent[tcp->scno].nargs;
2375	else
2376		tcp->u_nargs = tcp->status.pr_nsysarg;
2377	{
2378		int i;
2379		for (i = 0; i < tcp->u_nargs; i++)
2380			tcp->u_arg[i] = tcp->status.pr_sysarg[i];
2381	}
2382#elif defined (I386)
2383	if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
2384		tcp->u_nargs = sysent[tcp->scno].nargs;
2385	else
2386		tcp->u_nargs = 5;
2387	umoven(tcp, tcp->status.PR_REG[UESP] + 4,
2388		tcp->u_nargs*sizeof(tcp->u_arg[0]), (char *) tcp->u_arg);
2389#else
2390	I DONT KNOW WHAT TO DO
2391#endif /* !HAVE_PR_SYSCALL */
2392#endif /* SVR4 */
2393#ifdef FREEBSD
2394	if (tcp->scno >= 0 && tcp->scno < nsyscalls &&
2395	    sysent[tcp->scno].nargs > tcp->status.val)
2396		tcp->u_nargs = sysent[tcp->scno].nargs;
2397	else
2398		tcp->u_nargs = tcp->status.val;
2399	if (tcp->u_nargs < 0)
2400		tcp->u_nargs = 0;
2401	if (tcp->u_nargs > MAX_ARGS)
2402		tcp->u_nargs = MAX_ARGS;
2403	switch(regs.r_eax) {
2404	case SYS___syscall:
2405		pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
2406		      regs.r_esp + sizeof(int) + sizeof(quad_t));
2407		break;
2408	case SYS_syscall:
2409		pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
2410		      regs.r_esp + 2 * sizeof(int));
2411		break;
2412	default:
2413		pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
2414		      regs.r_esp + sizeof(int));
2415		break;
2416	}
2417#endif /* FREEBSD */
2418	return 1;
2419}
2420
2421static int
2422trace_syscall_exiting(struct tcb *tcp)
2423{
2424	int sys_res;
2425	struct timeval tv;
2426	int res, scno_good;
2427	long u_error;
2428
2429	/* Measure the exit time as early as possible to avoid errors. */
2430	if (dtime || cflag)
2431		gettimeofday(&tv, NULL);
2432
2433	/* BTW, why we don't just memorize syscall no. on entry
2434	 * in tcp->something?
2435	 */
2436	scno_good = res = get_scno(tcp);
2437	if (res == 0)
2438		return res;
2439	if (res == 1)
2440		res = syscall_fixup(tcp);
2441	if (res == 0)
2442		return res;
2443	if (res == 1)
2444		res = get_error(tcp);
2445	if (res == 0)
2446		return res;
2447	if (res == 1)
2448		internal_syscall(tcp);
2449
2450	if (res == 1 && tcp->scno >= 0 && tcp->scno < nsyscalls &&
2451	    !(qual_flags[tcp->scno] & QUAL_TRACE)) {
2452		tcp->flags &= ~TCB_INSYSCALL;
2453		return 0;
2454	}
2455
2456	if (tcp->flags & TCB_REPRINT) {
2457		printleader(tcp);
2458		tprintf("<... ");
2459		if (scno_good != 1)
2460			tprintf("????");
2461		else if (tcp->scno >= nsyscalls || tcp->scno < 0)
2462			tprintf("syscall_%lu", tcp->scno);
2463		else
2464			tprintf("%s", sysent[tcp->scno].sys_name);
2465		tprintf(" resumed> ");
2466	}
2467
2468	if (cflag) {
2469		struct timeval t = tv;
2470		int rc = count_syscall(tcp, &t);
2471		if (cflag == CFLAG_ONLY_STATS)
2472		{
2473			tcp->flags &= ~TCB_INSYSCALL;
2474			return rc;
2475		}
2476	}
2477
2478	if (res != 1) {
2479		tprintf(") ");
2480		tabto(acolumn);
2481		tprintf("= ? <unavailable>");
2482		printtrailer();
2483		tcp->flags &= ~TCB_INSYSCALL;
2484		return res;
2485	}
2486
2487	if (tcp->scno >= nsyscalls || tcp->scno < 0
2488	    || (qual_flags[tcp->scno] & QUAL_RAW))
2489		sys_res = printargs(tcp);
2490	else {
2491		if (not_failing_only && tcp->u_error)
2492			return 0;	/* ignore failed syscalls */
2493		sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2494	}
2495
2496	u_error = tcp->u_error;
2497	tprintf(") ");
2498	tabto(acolumn);
2499	if (tcp->scno >= nsyscalls || tcp->scno < 0 ||
2500	    qual_flags[tcp->scno] & QUAL_RAW) {
2501		if (u_error)
2502			tprintf("= -1 (errno %ld)", u_error);
2503		else
2504			tprintf("= %#lx", tcp->u_rval);
2505	}
2506	else if (!(sys_res & RVAL_NONE) && u_error) {
2507		switch (u_error) {
2508#ifdef LINUX
2509		case ERESTARTSYS:
2510			tprintf("= ? ERESTARTSYS (To be restarted)");
2511			break;
2512		case ERESTARTNOINTR:
2513			tprintf("= ? ERESTARTNOINTR (To be restarted)");
2514			break;
2515		case ERESTARTNOHAND:
2516			tprintf("= ? ERESTARTNOHAND (To be restarted)");
2517			break;
2518		case ERESTART_RESTARTBLOCK:
2519			tprintf("= ? ERESTART_RESTARTBLOCK (To be restarted)");
2520			break;
2521#endif /* LINUX */
2522		default:
2523			tprintf("= -1 ");
2524			if (u_error < 0)
2525				tprintf("E??? (errno %ld)", u_error);
2526			else if (u_error < nerrnos)
2527				tprintf("%s (%s)", errnoent[u_error],
2528					strerror(u_error));
2529			else
2530				tprintf("ERRNO_%ld (%s)", u_error,
2531					strerror(u_error));
2532			break;
2533		}
2534		if ((sys_res & RVAL_STR) && tcp->auxstr)
2535			tprintf(" (%s)", tcp->auxstr);
2536	}
2537	else {
2538		if (sys_res & RVAL_NONE)
2539			tprintf("= ?");
2540		else {
2541			switch (sys_res & RVAL_MASK) {
2542			case RVAL_HEX:
2543				tprintf("= %#lx", tcp->u_rval);
2544				break;
2545			case RVAL_OCTAL:
2546				tprintf("= %#lo", tcp->u_rval);
2547				break;
2548			case RVAL_UDECIMAL:
2549				tprintf("= %lu", tcp->u_rval);
2550				break;
2551			case RVAL_DECIMAL:
2552				tprintf("= %ld", tcp->u_rval);
2553				break;
2554#ifdef HAVE_LONG_LONG
2555			case RVAL_LHEX:
2556				tprintf("= %#llx", tcp->u_lrval);
2557				break;
2558			case RVAL_LOCTAL:
2559				tprintf("= %#llo", tcp->u_lrval);
2560				break;
2561			case RVAL_LUDECIMAL:
2562				tprintf("= %llu", tcp->u_lrval);
2563				break;
2564			case RVAL_LDECIMAL:
2565				tprintf("= %lld", tcp->u_lrval);
2566				break;
2567#endif
2568			default:
2569				fprintf(stderr,
2570					"invalid rval format\n");
2571				break;
2572			}
2573		}
2574		if ((sys_res & RVAL_STR) && tcp->auxstr)
2575			tprintf(" (%s)", tcp->auxstr);
2576	}
2577	if (dtime) {
2578		tv_sub(&tv, &tv, &tcp->etime);
2579		tprintf(" <%ld.%06ld>",
2580			(long) tv.tv_sec, (long) tv.tv_usec);
2581	}
2582	printtrailer();
2583
2584	dumpio(tcp);
2585	if (fflush(tcp->outf) == EOF)
2586		return -1;
2587	tcp->flags &= ~TCB_INSYSCALL;
2588	return 0;
2589}
2590
2591static int
2592trace_syscall_entering(struct tcb *tcp)
2593{
2594	int sys_res;
2595	int res, scno_good;
2596
2597	scno_good = res = get_scno(tcp);
2598	if (res == 0)
2599		return res;
2600	if (res == 1)
2601		res = syscall_fixup(tcp);
2602	if (res == 0)
2603		return res;
2604	if (res == 1)
2605		res = syscall_enter(tcp);
2606	if (res == 0)
2607		return res;
2608
2609	if (res != 1) {
2610		printleader(tcp);
2611		tcp->flags &= ~TCB_REPRINT;
2612		tcp_last = tcp;
2613		if (scno_good != 1)
2614			tprintf("????" /* anti-trigraph gap */ "(");
2615		else if (tcp->scno >= nsyscalls || tcp->scno < 0)
2616			tprintf("syscall_%lu(", tcp->scno);
2617		else
2618			tprintf("%s(", sysent[tcp->scno].sys_name);
2619		/*
2620		 * " <unavailable>" will be added later by the code which
2621		 * detects ptrace errors.
2622		 */
2623		tcp->flags |= TCB_INSYSCALL;
2624		return res;
2625	}
2626
2627	switch (known_scno(tcp)) {
2628#ifdef SYS_socket_subcall
2629	case SYS_socketcall:
2630		decode_subcall(tcp, SYS_socket_subcall,
2631			SYS_socket_nsubcalls, deref_style);
2632		break;
2633#endif
2634#ifdef SYS_ipc_subcall
2635	case SYS_ipc:
2636		decode_subcall(tcp, SYS_ipc_subcall,
2637			SYS_ipc_nsubcalls, shift_style);
2638		break;
2639#endif
2640#ifdef SVR4
2641#ifdef SYS_pgrpsys_subcall
2642	case SYS_pgrpsys:
2643		decode_subcall(tcp, SYS_pgrpsys_subcall,
2644			SYS_pgrpsys_nsubcalls, shift_style);
2645		break;
2646#endif /* SYS_pgrpsys_subcall */
2647#ifdef SYS_sigcall_subcall
2648	case SYS_sigcall:
2649		decode_subcall(tcp, SYS_sigcall_subcall,
2650			SYS_sigcall_nsubcalls, mask_style);
2651		break;
2652#endif /* SYS_sigcall_subcall */
2653	case SYS_msgsys:
2654		decode_subcall(tcp, SYS_msgsys_subcall,
2655			SYS_msgsys_nsubcalls, shift_style);
2656		break;
2657	case SYS_shmsys:
2658		decode_subcall(tcp, SYS_shmsys_subcall,
2659			SYS_shmsys_nsubcalls, shift_style);
2660		break;
2661	case SYS_semsys:
2662		decode_subcall(tcp, SYS_semsys_subcall,
2663			SYS_semsys_nsubcalls, shift_style);
2664		break;
2665	case SYS_sysfs:
2666		decode_subcall(tcp, SYS_sysfs_subcall,
2667			SYS_sysfs_nsubcalls, shift_style);
2668		break;
2669	case SYS_spcall:
2670		decode_subcall(tcp, SYS_spcall_subcall,
2671			SYS_spcall_nsubcalls, shift_style);
2672		break;
2673#ifdef SYS_context_subcall
2674	case SYS_context:
2675		decode_subcall(tcp, SYS_context_subcall,
2676			SYS_context_nsubcalls, shift_style);
2677		break;
2678#endif /* SYS_context_subcall */
2679#ifdef SYS_door_subcall
2680	case SYS_door:
2681		decode_subcall(tcp, SYS_door_subcall,
2682			SYS_door_nsubcalls, door_style);
2683		break;
2684#endif /* SYS_door_subcall */
2685#ifdef SYS_kaio_subcall
2686	case SYS_kaio:
2687		decode_subcall(tcp, SYS_kaio_subcall,
2688			SYS_kaio_nsubcalls, shift_style);
2689		break;
2690#endif
2691#endif /* SVR4 */
2692#ifdef FREEBSD
2693	case SYS_msgsys:
2694	case SYS_shmsys:
2695	case SYS_semsys:
2696		decode_subcall(tcp, 0, 0, table_style);
2697		break;
2698#endif
2699#ifdef SUNOS4
2700	case SYS_semsys:
2701		decode_subcall(tcp, SYS_semsys_subcall,
2702			SYS_semsys_nsubcalls, shift_style);
2703		break;
2704	case SYS_msgsys:
2705		decode_subcall(tcp, SYS_msgsys_subcall,
2706			SYS_msgsys_nsubcalls, shift_style);
2707		break;
2708	case SYS_shmsys:
2709		decode_subcall(tcp, SYS_shmsys_subcall,
2710			SYS_shmsys_nsubcalls, shift_style);
2711		break;
2712#endif
2713	}
2714
2715	internal_syscall(tcp);
2716	if (tcp->scno >=0 && tcp->scno < nsyscalls && !(qual_flags[tcp->scno] & QUAL_TRACE)) {
2717		tcp->flags |= TCB_INSYSCALL;
2718		return 0;
2719	}
2720
2721	if (cflag == CFLAG_ONLY_STATS) {
2722		tcp->flags |= TCB_INSYSCALL;
2723		gettimeofday(&tcp->etime, NULL);
2724		return 0;
2725	}
2726
2727	printleader(tcp);
2728	tcp->flags &= ~TCB_REPRINT;
2729	tcp_last = tcp;
2730	if (tcp->scno >= nsyscalls || tcp->scno < 0)
2731		tprintf("syscall_%lu(", tcp->scno);
2732	else
2733		tprintf("%s(", sysent[tcp->scno].sys_name);
2734	if (tcp->scno >= nsyscalls || tcp->scno < 0 ||
2735	    ((qual_flags[tcp->scno] & QUAL_RAW) && tcp->scno != SYS_exit))
2736		sys_res = printargs(tcp);
2737	else
2738		sys_res = (*sysent[tcp->scno].sys_func)(tcp);
2739	if (fflush(tcp->outf) == EOF)
2740		return -1;
2741	tcp->flags |= TCB_INSYSCALL;
2742	/* Measure the entrance time as late as possible to avoid errors. */
2743	if (dtime || cflag)
2744		gettimeofday(&tcp->etime, NULL);
2745	return sys_res;
2746}
2747
2748int
2749trace_syscall(struct tcb *tcp)
2750{
2751	return exiting(tcp) ?
2752		trace_syscall_exiting(tcp) : trace_syscall_entering(tcp);
2753}
2754
2755int
2756printargs(tcp)
2757struct tcb *tcp;
2758{
2759	if (entering(tcp)) {
2760		int i;
2761
2762		for (i = 0; i < tcp->u_nargs; i++)
2763			tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
2764	}
2765	return 0;
2766}
2767
2768long
2769getrval2(tcp)
2770struct tcb *tcp;
2771{
2772	long val = -1;
2773
2774#ifdef LINUX
2775#if defined (SPARC) || defined (SPARC64)
2776	struct pt_regs regs;
2777	if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
2778		return -1;
2779	val = regs.u_regs[U_REG_O1];
2780#elif defined(SH)
2781	if (upeek(tcp, 4*(REG_REG0+1), &val) < 0)
2782		return -1;
2783#elif defined(IA64)
2784	if (upeek(tcp, PT_R9, &val) < 0)
2785		return -1;
2786#endif
2787#endif /* LINUX */
2788
2789#ifdef SUNOS4
2790	if (upeek(tcp, uoff(u_rval2), &val) < 0)
2791		return -1;
2792#endif /* SUNOS4 */
2793
2794#ifdef SVR4
2795#ifdef SPARC
2796	val = tcp->status.PR_REG[R_O1];
2797#endif /* SPARC */
2798#ifdef I386
2799	val = tcp->status.PR_REG[EDX];
2800#endif /* I386 */
2801#ifdef X86_64
2802	val = tcp->status.PR_REG[RDX];
2803#endif /* X86_64 */
2804#ifdef MIPS
2805	val = tcp->status.PR_REG[CTX_V1];
2806#endif /* MIPS */
2807#endif /* SVR4 */
2808
2809#ifdef FREEBSD
2810	struct reg regs;
2811	pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
2812	val = regs.r_edx;
2813#endif
2814	return val;
2815}
2816
2817#ifdef SUNOS4
2818/*
2819 * Apparently, indirect system calls have already be converted by ptrace(2),
2820 * so if you see "indir" this program has gone astray.
2821 */
2822int
2823sys_indir(tcp)
2824struct tcb *tcp;
2825{
2826	int i, scno, nargs;
2827
2828	if (entering(tcp)) {
2829		if ((scno = tcp->u_arg[0]) > nsyscalls) {
2830			fprintf(stderr, "Bogus syscall: %u\n", scno);
2831			return 0;
2832		}
2833		nargs = sysent[scno].nargs;
2834		tprintf("%s", sysent[scno].sys_name);
2835		for (i = 0; i < nargs; i++)
2836			tprintf(", %#lx", tcp->u_arg[i+1]);
2837	}
2838	return 0;
2839}
2840#endif /* SUNOS4 */
2841
2842int
2843is_restart_error(struct tcb *tcp)
2844{
2845#ifdef LINUX
2846	if (!syserror(tcp))
2847		return 0;
2848	switch (tcp->u_error) {
2849		case ERESTARTSYS:
2850		case ERESTARTNOINTR:
2851		case ERESTARTNOHAND:
2852		case ERESTART_RESTARTBLOCK:
2853			return 1;
2854		default:
2855			break;
2856	}
2857#endif /* LINUX */
2858	return 0;
2859}
2860