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