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