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