]> granicus.if.org Git - strace/blob - syscall.c
Cleaned up __NR_SYSCALL_BASE: less number of #ifdef's in main code is
[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 #include <asm/reg.h>
47 #endif
48
49 #if HAVE_LINUX_PTRACE_H
50 #undef PTRACE_SYSCALL
51 #include <linux/ptrace.h>
52 #endif 
53
54 #ifdef HAVE_SYS_REG_H
55 #include <sys/reg.h>
56 #ifndef PTRACE_PEEKUSR
57 # define PTRACE_PEEKUSR PTRACE_PEEKUSER
58 #endif
59 #endif
60
61 #ifndef SYS_ERRLIST_DECLARED
62 extern int sys_nerr;
63 extern char *sys_errlist[];
64 #endif /* SYS_ERRLIST_DECLARED */
65
66 #define NR_SYSCALL_BASE 0
67 #ifdef LINUX
68 #ifndef ERESTARTSYS
69 #define ERESTARTSYS     512
70 #endif
71 #ifndef ERESTARTNOINTR
72 #define ERESTARTNOINTR  513
73 #endif
74 #ifndef ERESTARTNOHAND
75 #define ERESTARTNOHAND  514     /* restart if no handler.. */
76 #endif
77 #ifndef ENOIOCTLCMD
78 #define ENOIOCTLCMD     515     /* No ioctl command */
79 #endif
80 #ifndef NSIG
81 #define NSIG 32
82 #endif
83 #ifdef ARM
84 #undef NSIG
85 #define NSIG 32
86 #undef NR_SYSCALL_BASE
87 #define NR_SYSCALL_BASE __NR_SYSCALL_BASE
88 #endif
89 #endif /* LINUX */
90
91 #include "syscall.h"
92
93 /* Define these shorthand notations to simplify the syscallent files. */
94 #define TF TRACE_FILE
95 #define TI TRACE_IPC
96 #define TN TRACE_NETWORK
97 #define TP TRACE_PROCESS
98 #define TS TRACE_SIGNAL
99
100 struct sysent sysent0[] = {
101 #include "syscallent.h"
102 };
103 int nsyscalls0 = sizeof sysent0 / sizeof sysent0[0];
104
105 #if SUPPORTED_PERSONALITIES >= 2
106 struct sysent sysent1[] = {
107 #include "syscallent1.h"
108 };
109 int nsyscalls1 = sizeof sysent1 / sizeof sysent1[0];
110 #endif /* SUPPORTED_PERSONALITIES >= 2 */
111
112 #if SUPPORTED_PERSONALITIES >= 3
113 struct sysent sysent2[] = {
114 #include "syscallent2.h"
115 };
116 int nsyscalls2 = sizeof sysent2 / sizeof sysent2[0];
117 #endif /* SUPPORTED_PERSONALITIES >= 3 */
118
119 struct sysent *sysent;
120 int nsyscalls;
121
122 /* Now undef them since short defines cause wicked namespace pollution. */
123 #undef TF
124 #undef TI
125 #undef TN
126 #undef TP
127 #undef TS
128
129 char *errnoent0[] = {
130 #include "errnoent.h"
131 };
132 int nerrnos0 = sizeof errnoent0 / sizeof errnoent0[0];
133
134 #if SUPPORTED_PERSONALITIES >= 2
135 char *errnoent1[] = {
136 #include "errnoent1.h"
137 };
138 int nerrnos1 = sizeof errnoent1 / sizeof errnoent1[0];
139 #endif /* SUPPORTED_PERSONALITIES >= 2 */
140
141 #if SUPPORTED_PERSONALITIES >= 3
142 char *errnoent2[] = {
143 #include "errnoent2.h"
144 };
145 int nerrnos2 = sizeof errnoent2 / sizeof errnoent2[0];
146 #endif /* SUPPORTED_PERSONALITIES >= 3 */
147
148 char **errnoent;
149 int nerrnos;
150
151 int current_personality;
152
153 int
154 set_personality(personality)
155 int personality;
156 {
157         switch (personality) {
158         case 0:
159                 errnoent = errnoent0;
160                 nerrnos = nerrnos0;
161                 sysent = sysent0;
162                 nsyscalls = nsyscalls0;
163                 ioctlent = ioctlent0;
164                 nioctlents = nioctlents0;
165                 signalent = signalent0;
166                 nsignals = nsignals0;
167                 break;
168
169 #if SUPPORTED_PERSONALITIES >= 2
170         case 1:
171                 errnoent = errnoent1;
172                 nerrnos = nerrnos1;
173                 sysent = sysent1;
174                 nsyscalls = nsyscalls1;
175                 ioctlent = ioctlent1;
176                 nioctlents = nioctlents1;
177                 signalent = signalent1;
178                 nsignals = nsignals1;
179                 break;
180 #endif /* SUPPORTED_PERSONALITIES >= 2 */
181
182 #if SUPPORTED_PERSONALITIES >= 3
183         case 2:
184                 errnoent = errnoent2;
185                 nerrnos = nerrnos2;
186                 sysent = sysent2;
187                 nsyscalls = nsyscalls2;
188                 ioctlent = ioctlent2;
189                 nioctlents = nioctlents2;
190                 signalent = signalent2;
191                 nsignals = nsignals2;
192                 break;
193 #endif /* SUPPORTED_PERSONALITIES >= 3 */
194
195         default:
196                 return -1;
197         }
198
199         current_personality = personality;
200         return 0;
201 }
202
203 int qual_flags[MAX_QUALS];
204
205 static int call_count[MAX_QUALS];
206 static int error_count[MAX_QUALS];
207 static struct timeval tv_count[MAX_QUALS];
208 static int sorted_count[MAX_QUALS];
209
210 static struct timeval shortest = { 1000000, 0 };
211
212 static int lookup_syscall(), lookup_signal(), lookup_fault(), lookup_desc();
213
214 static struct qual_options {
215         int bitflag;
216         char *option_name;
217         int (*lookup)();
218         char *argument_name;
219 } qual_options[] = {
220         { QUAL_TRACE,   "trace",        lookup_syscall, "system call"   },
221         { QUAL_TRACE,   "t",            lookup_syscall, "system call"   },
222         { QUAL_ABBREV,  "abbrev",       lookup_syscall, "system call"   },
223         { QUAL_ABBREV,  "a",            lookup_syscall, "system call"   },
224         { QUAL_VERBOSE, "verbose",      lookup_syscall, "system call"   },
225         { QUAL_VERBOSE, "v",            lookup_syscall, "system call"   },
226         { QUAL_RAW,     "raw",          lookup_syscall, "system call"   },
227         { QUAL_RAW,     "x",            lookup_syscall, "system call"   },
228         { QUAL_SIGNAL,  "signal",       lookup_signal,  "signal"        },
229         { QUAL_SIGNAL,  "signals",      lookup_signal,  "signal"        },
230         { QUAL_SIGNAL,  "s",            lookup_signal,  "signal"        },
231         { QUAL_FAULT,   "fault",        lookup_fault,   "fault"         },
232         { QUAL_FAULT,   "faults",       lookup_fault,   "fault"         },
233         { QUAL_FAULT,   "m",            lookup_fault,   "fault"         },
234         { QUAL_READ,    "read",         lookup_desc,    "descriptor"    },
235         { QUAL_READ,    "reads",        lookup_desc,    "descriptor"    },
236         { QUAL_READ,    "r",            lookup_desc,    "descriptor"    },
237         { QUAL_WRITE,   "write",        lookup_desc,    "descriptor"    },
238         { QUAL_WRITE,   "writes",       lookup_desc,    "descriptor"    },
239         { QUAL_WRITE,   "w",            lookup_desc,    "descriptor"    },
240         { 0,            NULL,           NULL,           NULL            },
241 };
242
243 static int
244 lookup_syscall(s)
245 char *s;
246 {
247         int i;
248
249         for (i = 0; i < nsyscalls; i++) {
250                 if (strcmp(s, sysent[i].sys_name) == 0)
251                         return i;
252         }
253         return -1;
254 }
255
256 static int
257 lookup_signal(s)
258 char *s;
259 {
260         int i;
261         char buf[32];
262
263         if (s && *s && isdigit(*s))
264                 return atoi(s);
265         strcpy(buf, s);
266         s = buf;
267         for (i = 0; s[i]; i++)
268                 s[i] = toupper(s[i]);
269         if (strncmp(s, "SIG", 3) == 0)
270                 s += 3;
271         for (i = 0; i <= NSIG; i++) {
272                 if (strcmp(s, signame(i) + 3) == 0)
273                         return i;
274         }
275         return -1;
276 }
277
278 static int
279 lookup_fault(s)
280 char *s;
281 {
282         return -1;
283 }
284
285 static int
286 lookup_desc(s)
287 char *s;
288 {
289         if (s && *s && isdigit(*s))
290                 return atoi(s);
291         return -1;
292 }
293
294 static int
295 lookup_class(s)
296 char *s;
297 {
298         if (strcmp(s, "file") == 0)
299                 return TRACE_FILE;
300         if (strcmp(s, "ipc") == 0)
301                 return TRACE_IPC;
302         if (strcmp(s, "network") == 0)
303                 return TRACE_NETWORK;
304         if (strcmp(s, "process") == 0)
305                 return TRACE_PROCESS;
306         if (strcmp(s, "signal") == 0)
307                 return TRACE_SIGNAL;
308         return -1;
309 }
310
311 void
312 qualify(s)
313 char *s;
314 {
315         struct qual_options *opt;
316         int not;
317         char *p;
318         int i, n;
319
320         opt = &qual_options[0];
321         for (i = 0; (p = qual_options[i].option_name); i++) {
322                 n = strlen(p);
323                 if (strncmp(s, p, n) == 0 && s[n] == '=') {
324                         opt = &qual_options[i];
325                         s += n + 1;
326                         break;
327                 }
328         }
329         not = 0;
330         if (*s == '!') {
331                 not = 1;
332                 s++;
333         }
334         if (strcmp(s, "none") == 0) {
335                 not = 1 - not;
336                 s = "all";
337         }
338         if (strcmp(s, "all") == 0) {
339                 for (i = 0; i < MAX_QUALS; i++) {
340                         if (not)
341                                 qual_flags[i] &= ~opt->bitflag;
342                         else
343                                 qual_flags[i] |= opt->bitflag;
344                 }
345                 return;
346         }
347         for (i = 0; i < MAX_QUALS; i++) {
348                 if (not)
349                         qual_flags[i] |= opt->bitflag;
350                 else
351                         qual_flags[i] &= ~opt->bitflag;
352         }
353         for (p = strtok(s, ","); p; p = strtok(NULL, ",")) {
354                 if (opt->bitflag == QUAL_TRACE && (n = lookup_class(p)) > 0) {
355                         for (i = 0; i < MAX_QUALS; i++) {
356                                 if (sysent[i].sys_flags & n) {
357                                         if (not)
358                                                 qual_flags[i] &= ~opt->bitflag;
359                                         else
360                                                 qual_flags[i] |= opt->bitflag;
361                                 }
362                         }
363                         continue;
364                 }
365                 if ((n = (*opt->lookup)(p)) < 0) {
366                         fprintf(stderr, "strace: invalid %s `%s'\n",
367                                 opt->argument_name, p);
368                         exit(1);
369                 }
370                 if (not)
371                         qual_flags[n] &= ~opt->bitflag;
372                 else
373                         qual_flags[n] |= opt->bitflag;
374         }
375         return;
376 }
377
378 static void
379 dumpio(tcp)
380 struct tcb *tcp;
381 {
382         if (syserror(tcp))
383                 return;
384         if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= MAX_QUALS)
385                 return;
386         switch (tcp->scno + NR_SYSCALL_BASE) {
387         case SYS_read:
388 #ifdef SYS_recv
389         case SYS_recv:
390 #endif
391 #ifdef SYS_recvfrom
392         case SYS_recvfrom:
393 #endif
394                 if (qual_flags[tcp->u_arg[0]] & QUAL_READ)
395                         dumpstr(tcp, tcp->u_arg[1], tcp->u_rval);
396                 break;
397         case SYS_write:
398 #ifdef SYS_send
399         case SYS_send:
400 #endif
401 #ifdef SYS_sendto
402         case SYS_sendto:
403 #endif
404                 if (qual_flags[tcp->u_arg[0]] & QUAL_WRITE)
405                         dumpstr(tcp, tcp->u_arg[1], tcp->u_arg[2]);
406                 break;
407         }
408 }
409
410 enum subcall_style { shift_style, deref_style, mask_style, door_style };
411
412 #if !(defined(LINUX) && ( defined(ALPHA) || defined(MIPS) ))
413
414 const int socket_map [] = {
415                /* SYS_SOCKET      */ 97,
416                /* SYS_BIND        */ 104,
417                /* SYS_CONNECT     */ 98,
418                /* SYS_LISTEN      */ 106,
419                /* SYS_ACCEPT      */ 99,
420                /* SYS_GETSOCKNAME */ 150,
421                /* SYS_GETPEERNAME */ 141,
422                /* SYS_SOCKETPAIR  */ 135,
423                /* SYS_SEND        */ 101,
424                /* SYS_RECV        */ 102,
425                /* SYS_SENDTO      */ 133,
426                /* SYS_RECVFROM    */ 125,
427                /* SYS_SHUTDOWN    */ 134,
428                /* SYS_SETSOCKOPT  */ 105,
429                /* SYS_GETSOCKOPT  */ 118,
430                /* SYS_SENDMSG     */ 114,
431                /* SYS_RECVMSG     */ 113
432 };
433
434 void
435 sparc_socket_decode (tcp)
436 struct tcb *tcp;
437 {
438         volatile long addr;
439         volatile int i, n;
440
441         if (tcp->u_arg [0] < 1 || tcp->u_arg [0] > sizeof(socket_map)/sizeof(int)+1){
442                 return;
443         }
444         tcp->scno = socket_map [tcp->u_arg [0]-1];
445         n = tcp->u_nargs = sysent [tcp->scno].nargs;
446         addr = tcp->u_arg [1];
447         for (i = 0; i < n; i++){
448                 int arg;
449                 if (umoven (tcp, addr, sizeof (arg), (void *) &arg) < 0)
450                         arg = 0;
451                 tcp->u_arg [i] = arg;
452                 addr += sizeof (arg);
453         }
454 }
455
456 static void
457 decode_subcall(tcp, subcall, nsubcalls, style)
458 struct tcb *tcp;
459 int subcall;
460 int nsubcalls;
461 enum subcall_style style;
462 {
463         int i, addr, mask, arg;
464
465         if (tcp->u_arg[0] < 0 || tcp->u_arg[0] >= nsubcalls)
466                 return;
467         switch (style) {
468         case shift_style:
469                 tcp->scno = subcall + tcp->u_arg[0];
470                 if (sysent[tcp->scno].nargs != -1)
471                         tcp->u_nargs = sysent[tcp->scno].nargs;
472                 else
473                         tcp->u_nargs--;
474                 for (i = 0; i < tcp->u_nargs; i++)
475                         tcp->u_arg[i] = tcp->u_arg[i + 1];
476                 break;
477         case deref_style:
478                 tcp->scno = subcall + tcp->u_arg[0];
479                 addr = tcp->u_arg[1];
480                 for (i = 0; i < sysent[tcp->scno].nargs; i++) {
481                         if (umove(tcp, addr, &arg) < 0)
482                                 arg = 0;
483                         tcp->u_arg[i] = arg;
484                         addr += sizeof(arg);
485                 }
486                 tcp->u_nargs = sysent[tcp->scno].nargs;
487                 break;
488         case mask_style:
489                 mask = (tcp->u_arg[0] >> 8) & 0xff;
490                 tcp->u_arg[0] &= 0xff;
491                 for (i = 0; mask; i++)
492                         mask >>= 1;
493                 tcp->scno = subcall + i;
494                 if (sysent[tcp->scno].nargs != -1)
495                         tcp->u_nargs = sysent[tcp->scno].nargs;
496                 break;
497         case door_style:
498                 /*
499                  * Oh, yuck.  The call code is the *sixth* argument.
500                  */
501                 tcp->scno = subcall + tcp->u_arg[5];
502                 if (sysent[tcp->scno].nargs != -1)
503                         tcp->u_nargs = sysent[tcp->scno].nargs;
504                 else
505                         tcp->u_nargs--;
506                 break;
507         }
508 }
509 #endif
510
511 struct tcb *tcp_last = NULL;
512
513 static int
514 internal_syscall(tcp)
515 struct tcb *tcp;
516 {
517         /*
518          * We must always trace a few critical system calls in order to
519          * correctly support following forks in the presence of tracing
520          * qualifiers.
521          */
522         switch (tcp->scno + NR_SYSCALL_BASE) {
523 #ifdef SYS_fork
524         case SYS_fork:
525 #endif
526 #ifdef SYS_vfork
527         case SYS_vfork:
528 #endif
529                 internal_fork(tcp);
530                 break;
531 #ifdef SYS_clone
532         case SYS_clone:
533                 internal_clone(tcp);
534                 break;
535 #endif
536 #ifdef SYS_execv
537         case SYS_execv:
538 #endif
539 #ifdef SYS_execve
540         case SYS_execve:
541 #endif
542                 internal_exec(tcp);
543                 break;
544
545 #ifdef SYS_wait
546         case SYS_wait:
547 #endif
548 #ifdef SYS_wait4
549         case SYS_wait4:
550 #endif
551 #ifdef SYS_waitpid
552         case SYS_waitpid:
553 #endif
554 #ifdef SYS_waitsys
555         case SYS_waitsys:
556 #endif
557                 internal_wait(tcp);
558                 break;
559
560 #ifdef SYS_exit
561         case SYS_exit:
562 #endif
563                 internal_exit(tcp);
564                 break;
565         }
566         return 0;
567 }
568
569 int
570 trace_syscall(tcp)
571 struct tcb *tcp;
572 {
573         int sys_res;
574         struct timeval tv;
575         long scno = 0;
576 #ifdef LINUX
577 #if defined (I386)
578         long eax;
579 #elif defined (POWERPC)
580         long result,flags;
581 #elif defined (M68K)
582         int d0;
583 #elif defined (ARM)
584         int r0;
585 #elif defined (ALPHA)
586         long r0;
587         long a3;
588 #elif defined(MIPS)
589         long r2,a3;
590 #elif defined (SPARC)
591         struct regs regs;
592         unsigned long trap;
593 #elif defined(S390)
594         long gpr2;
595         long pc;
596 #endif 
597 #endif /* LINUX */
598
599 #ifndef SVR4
600         int pid = tcp->pid;
601 #endif /* !SVR4 */
602
603         /* Measure the exit time as early as possible to avoid errors. */
604         if (dtime && (tcp->flags & TCB_INSYSCALL))
605                 gettimeofday(&tv, NULL);
606 #ifdef LINUX
607 #if defined(S390)
608         if (upeek(tcp->pid,PT_PSWADDR,&pc) < 0)
609                 return -1;
610         scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(pc-4),0);
611         if (errno)
612                 return -1;
613         scno&=0xFF;
614 #elif defined (POWERPC)
615         if (upeek(pid, 4*PT_R0, &scno) < 0)
616                 return -1;
617         if (!(tcp->flags & TCB_INSYSCALL)) {
618                 /* Check if we return from execve. */
619                 if (scno == 0 && (tcp->flags & TCB_WAITEXECVE)) {
620                         tcp->flags &= ~TCB_WAITEXECVE;
621                         return 0;
622                 }
623         }
624 #elif defined (I386)
625         if (upeek(pid, 4*ORIG_EAX, &scno) < 0)
626                 return -1;
627 #elif defined (ARM)
628         { 
629             long pc;
630             upeek(pid, 4*15, &pc);
631             umoven(tcp, pc-4, 4, (char *)&scno);
632             scno &= 0x000fffff;
633         }
634 #elif defined (M68K)
635         if (upeek(pid, 4*PT_ORIG_D0, &scno) < 0)
636                 return -1;
637 #elif defined (MIPS)
638         if (upeek(pid, REG_A3, &a3) < 0)
639                 return -1;
640
641         if(!(tcp->flags & TCB_INSYSCALL)) {
642                 if (upeek(pid, REG_V0, &scno) < 0)
643                         return -1;
644
645                 if (scno < 0 || scno > nsyscalls) {
646                         if(a3 == 0 || a3 == -1) {
647                                 if(debug)
648                                         fprintf (stderr, "stray syscall exit: v0 = %ld\n", scno);
649                                 return 0;
650                         }
651                 }
652         } else {
653                 if (upeek(pid, REG_V0, &r2) < 0)
654                         return -1;
655         }
656 #elif defined (ALPHA)
657         if (upeek(pid, REG_A3, &a3) < 0)
658                 return -1;
659
660         if (!(tcp->flags & TCB_INSYSCALL)) {
661                 if (upeek(pid, REG_R0, &scno) < 0)
662                         return -1;
663
664                 /* Check if we return from execve. */
665                 if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
666                         tcp->flags &= ~TCB_WAITEXECVE;
667                         return 0;
668                 }
669
670                 /*
671                  * Do some sanity checks to figure out if it's
672                  * really a syscall entry
673                  */
674                 if (scno < 0 || scno > nsyscalls) {
675                         if (a3 == 0 || a3 == -1) {
676                                 if (debug)
677                                         fprintf (stderr, "stray syscall exit: r0 = %ld\n", scno);
678                                 return 0;
679                         }
680                 }
681         }
682         else {
683                 if (upeek(pid, REG_R0, &r0) < 0)
684                         return -1;
685         }
686 #elif defined (SPARC)
687         /* Everything we need is in the current register set. */
688         if (ptrace(PTRACE_GETREGS,pid,(char *)&regs,0) < 0)
689                 return -1;
690
691         /* If we are entering, then disassemble the syscall trap. */
692         if (!(tcp->flags & TCB_INSYSCALL)) {
693                 /* Retrieve the syscall trap instruction. */
694                 errno = 0;
695                 trap = ptrace(PTRACE_PEEKTEXT,pid,(char *)regs.r_pc,0);
696                 if (errno)
697                         return -1;
698
699                 /* Disassemble the trap to see what personality to use. */
700                 switch (trap) {
701                 case 0x91d02010:
702                         /* Linux/SPARC syscall trap. */
703                         set_personality(0);
704                         break;
705                 case 0x91d0206d:
706                         /* Linux/SPARC64 syscall trap. */
707                         fprintf(stderr,"syscall: Linux/SPARC64 not supported yet\n");
708                         return -1;
709                 case 0x91d02000:
710                         /* SunOS syscall trap. (pers 1) */
711                         fprintf(stderr,"syscall: SunOS no support\n");
712                         return -1;
713                 case 0x91d02008:
714                         /* Solaris 2.x syscall trap. (per 2) */
715                         set_personality(1);
716                         break; 
717                 case 0x91d02009:
718                         /* NetBSD/FreeBSD syscall trap. */
719                         fprintf(stderr,"syscall: NetBSD/FreeBSD not supported\n");
720                         return -1;
721                 case 0x91d02027:
722                         /* Solaris 2.x gettimeofday */
723                         set_personality(1);
724                         break;
725                 default:
726                         /* Unknown syscall trap. */
727                         if(tcp->flags & TCB_WAITEXECVE) {
728                                 tcp->flags &= ~TCB_WAITEXECVE;
729                                 return 0;
730                         }
731                         fprintf(stderr,"syscall: unknown syscall trap %08x %08x\n", trap, regs.r_pc);
732                         return -1;
733                 }
734
735                 /* Extract the system call number from the registers. */
736                 if (trap == 0x91d02027)
737                         scno = 156;
738                 else
739                         scno = regs.r_g1;
740                 if (scno == 0) {
741                         scno = regs.r_o0;
742                         memmove (&regs.r_o0, &regs.r_o1, 7*sizeof(regs.r_o0));
743                 }
744         }
745 #endif 
746 #endif /* LINUX */
747 #ifdef SUNOS4
748         if (upeek(pid, uoff(u_arg[7]), &scno) < 0)
749                 return -1;
750 #endif
751 #ifdef SVR4
752 #ifdef HAVE_PR_SYSCALL
753         scno = tcp->status.pr_syscall;
754 #else /* !HAVE_PR_SYSCALL */
755         scno = tcp->status.PR_WHAT;
756 #endif /* !HAVE_PR_SYSCALL */
757         if (!(tcp->flags & TCB_INSYSCALL)) {
758                 if (tcp->status.PR_WHY != PR_SYSENTRY) {
759                         if (
760                             scno == SYS_fork
761 #ifdef SYS_vfork
762                             || scno == SYS_vfork
763 #endif /* SYS_vfork */
764                             ) {
765                                 /* We are returning in the child, fake it. */
766                                 tcp->status.PR_WHY = PR_SYSENTRY;
767                                 trace_syscall(tcp);
768                                 tcp->status.PR_WHY = PR_SYSEXIT;
769                         }
770                         else {
771                                 fprintf(stderr, "syscall: missing entry\n");
772                                 tcp->flags |= TCB_INSYSCALL;
773                         }
774                 }
775         }
776         else {
777                 if (tcp->status.PR_WHY != PR_SYSEXIT) {
778                         fprintf(stderr, "syscall: missing exit\n");
779                         tcp->flags &= ~TCB_INSYSCALL;
780                 }
781         }
782 #endif /* SVR4 */
783 #ifdef SUNOS4
784         if (!(tcp->flags & TCB_INSYSCALL)) {
785                 if (scno == 0) {
786                         fprintf(stderr, "syscall: missing entry\n");
787                         tcp->flags |= TCB_INSYSCALL;
788                 }
789         }
790         else {
791                 if (scno != 0) {
792                         if (debug) {
793                                 /*
794                                  * This happens when a signal handler
795                                  * for a signal which interrupted a
796                                  * a system call makes another system call.
797                                  */
798                                 fprintf(stderr, "syscall: missing exit\n");
799                         }
800                         tcp->flags &= ~TCB_INSYSCALL;
801                 }
802         }
803 #endif /* SUNOS4 */
804 #ifdef LINUX
805 #if defined (I386)
806         if (upeek(pid, 4*EAX, &eax) < 0)
807                 return -1;
808         if (eax != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
809                 if (debug)
810                         fprintf(stderr, "stray syscall exit: eax = %ld\n", eax);
811                 return 0;
812         }
813 #elif defined (POWERPC)
814 # define SO_MASK 0x10000000
815         if (upeek(pid, 4*PT_CCR, &flags) < 0)
816                 return -1;
817         if (upeek(pid, 4*PT_R3, &result) < 0)
818                 return -1;
819         if (flags & SO_MASK)
820                 result = -result;
821 #elif defined (M68K)
822         if (upeek(pid, 4*PT_D0, &d0) < 0)
823                 return -1;
824         if (d0 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
825                 if (debug)
826                         fprintf(stderr, "stray syscall exit: d0 = %ld\n", d0);
827                 return 0;
828         }
829 #elif defined (ARM)
830         if (upeek(pid, 4*0, (long *)&r0) < 0)
831                 return -1;
832         if ( 0 && r0 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
833                 if (debug)
834                         fprintf(stderr, "stray syscall exit: d0 = %ld\n", r0);
835                 return 0;
836         }
837 #else
838 #endif
839 #endif /* LINUX */
840
841         if (tcp->flags & TCB_INSYSCALL) {
842                 long u_error;
843
844 #ifdef LINUX
845 #ifdef I386
846                 if (eax < 0 && -eax < nerrnos) {
847                         tcp->u_rval = -1;
848                         u_error = -eax;
849                 }
850                 else {
851                         tcp->u_rval = eax;
852                         u_error = 0;
853                 }
854 #else /* !I386 */
855 #ifdef MIPS
856                 if (a3) {
857                         tcp->u_rval = -1;
858                         u_error = r2;
859                 } else {
860                         tcp->u_rval = r2;
861                         u_error = 0;
862                 }
863 #else
864 #ifdef POWERPC
865                 if (result && (unsigned) -result < nerrnos) {
866                         tcp->u_rval = -1;
867                         u_error = -result;
868                 }
869                 else {
870                         tcp->u_rval = result;
871                         u_error = 0;
872                 }
873 #else /* !POWERPC */
874 #ifdef M68K
875                 if (d0 && (unsigned) -d0 < nerrnos) {
876                         tcp->u_rval = -1;
877                         u_error = -d0;
878                 }
879                 else {
880                         tcp->u_rval = d0;
881                         u_error = 0;
882                 }
883 #else /* !M68K */
884 #ifdef ARM
885                 if (r0 && (unsigned) -r0 < nerrnos) {
886                         tcp->u_rval = -1;
887                         u_error = -r0;
888                 }
889                 else {
890                         tcp->u_rval = r0;
891                         u_error = 0;
892                 }
893 #else /* !ARM */
894 #ifdef ALPHA
895                 if (a3) {
896                         tcp->u_rval = -1;
897                         u_error = r0;
898                 }
899                 else {
900                         tcp->u_rval = r0;
901                         u_error = 0;
902                 }
903 #else /* !ALPHA */
904 #ifdef SPARC
905                 if (regs.r_psr & PSR_C) {
906                         tcp->u_rval = -1;
907                         u_error = regs.r_o0;
908                 }
909                 else {
910                         tcp->u_rval = regs.r_o0;
911                         u_error = 0;
912                 }
913 #endif /* SPARC */
914 #endif /* ALPHA */
915 #endif /* ARM */
916 #endif /* M68K */
917 #endif /* POWERPC */
918 #endif /* MIPS */
919 #endif /* I386 */
920 #endif /* LINUX */
921 #ifdef SUNOS4
922                 /* get error code from user struct */
923                 if (upeek(pid, uoff(u_error), &u_error) < 0)
924                         return -1;
925                 u_error >>= 24; /* u_error is a char */
926
927                 /* get system call return value */
928                 if (upeek(pid, uoff(u_rval1), &tcp->u_rval) < 0)
929                         return -1;
930 #endif /* SUNOS4 */
931 #ifdef SVR4
932 #ifdef SPARC
933                 /* Judicious guessing goes a long way. */
934                 if (tcp->status.pr_reg[R_PSR] & 0x100000) {
935                         tcp->u_rval = -1;
936                         u_error = tcp->status.pr_reg[R_O0];
937                 }
938                 else {
939                         tcp->u_rval = tcp->status.pr_reg[R_O0];
940                         u_error = 0;
941                 }
942 #endif /* SPARC */
943 #ifdef I386
944                 /* Wanna know how to kill an hour single-stepping? */
945                 if (tcp->status.PR_REG[EFL] & 0x1) {
946                         tcp->u_rval = -1;
947                         u_error = tcp->status.PR_REG[EAX];
948                 }
949                 else {
950                         tcp->u_rval = tcp->status.PR_REG[EAX];
951                         u_error = 0;
952                 }
953 #endif /* I386 */
954 #ifdef MIPS
955                 if (tcp->status.pr_reg[CTX_A3]) {
956                         tcp->u_rval = -1;
957                         u_error = tcp->status.pr_reg[CTX_V0];
958                 }
959                 else {
960                         tcp->u_rval = tcp->status.pr_reg[CTX_V0];
961                         u_error = 0;
962                 }
963 #endif /* MIPS */
964 #endif /* SVR4 */
965                 tcp->u_error = u_error;
966
967                 internal_syscall(tcp);
968                 if (!(qual_flags[tcp->scno] & QUAL_TRACE)) {
969                         tcp->flags &= ~TCB_INSYSCALL;
970                         return 0;
971                 }
972
973                 if (tcp->flags & TCB_REPRINT) {
974                         printleader(tcp);
975                         tprintf("<... ");
976                         if (tcp->scno >= nsyscalls)
977                                 tprintf("syscall_%lu", tcp->scno);
978                         else
979                                 tprintf("%s", sysent[tcp->scno].sys_name);
980                         tprintf(" resumed> ");
981                 }
982
983                 if (cflag) {
984                         call_count[tcp->scno]++;
985                         if (u_error)
986                                 error_count[tcp->scno]++;
987                         tv_sub(&tv, &tv, &tcp->etime);
988 #ifdef LINUX
989                         if (tv_cmp(&tv, &tcp->dtime) > 0) {
990                                 static struct timeval one_tick =
991                                         { 0, 1000000 / HZ };
992
993                                 if (tv_nz(&tcp->dtime))
994                                         tv = tcp->dtime;
995                                 else if (tv_cmp(&tv, &one_tick) > 0) {
996                                         if (tv_cmp(&shortest, &one_tick) < 0)
997                                                 tv = shortest;
998                                         else
999                                                 tv = one_tick;
1000                                 }
1001                         }
1002 #endif /* LINUX */
1003                         if (tv_cmp(&tv, &shortest) < 0)
1004                                 shortest = tv;
1005                         tv_add(&tv_count[tcp->scno],
1006                                 &tv_count[tcp->scno], &tv);
1007                         tcp->flags &= ~TCB_INSYSCALL;
1008                         return 0;
1009                 }
1010
1011                 if (tcp->scno >= nsyscalls
1012                     || (qual_flags[tcp->scno] & QUAL_RAW))
1013                         sys_res = printargs(tcp);
1014                 else
1015                         sys_res = (*sysent[tcp->scno].sys_func)(tcp);
1016                 u_error = tcp->u_error;
1017                 tprintf(") ");
1018                 tabto(acolumn);
1019                 if (qual_flags[tcp->scno] & QUAL_RAW) {
1020                         if (u_error)
1021                                 tprintf("= -1 (errno %ld)", u_error);
1022                         else
1023                                 tprintf("= %#lx", tcp->u_rval);
1024                 }
1025                 else if (!(sys_res & RVAL_NONE) && u_error) {
1026 #ifdef LINUX
1027                         switch (u_error) {
1028                         case ERESTARTSYS:
1029                                 tprintf("= ? ERESTARTSYS (To be restarted)");
1030                                 break;
1031                         case ERESTARTNOINTR:
1032                                 tprintf("= ? ERESTARTNOINTR (To be restarted)");
1033                                 break;
1034                         case ERESTARTNOHAND:
1035                                 tprintf("= ? ERESTARTNOHAND (To be restarted)");
1036                                 break;
1037                         default:
1038 #endif /* LINUX */
1039                                 tprintf("= -1 ");
1040                                 if (u_error < nerrnos && u_error < sys_nerr)
1041                                         tprintf("%s (%s)", errnoent[u_error],
1042                                                 sys_errlist[u_error]);
1043                                 else if (u_error < nerrnos)
1044                                         tprintf("%s (errno %ld)",
1045                                                 errnoent[u_error], u_error);
1046                                 else if (u_error < sys_nerr)
1047                                         tprintf("ERRNO_%ld (%s)", u_error,
1048                                                 sys_errlist[u_error]);
1049                                 else
1050                                         tprintf("E??? (errno %ld)", u_error);
1051 #ifdef LINUX
1052                                 break;
1053                         }
1054 #endif /* LINUX */
1055                 }
1056                 else {
1057                         if (sys_res & RVAL_NONE)
1058                                 tprintf("= ?");
1059                         else {
1060                                 switch (sys_res & RVAL_MASK) {
1061                                 case RVAL_HEX:
1062                                         tprintf("= %#lx", tcp->u_rval);
1063                                         break;
1064                                 case RVAL_OCTAL:
1065                                         tprintf("= %#lo", tcp->u_rval);
1066                                         break;
1067                                 case RVAL_UDECIMAL:
1068                                         tprintf("= %lu", tcp->u_rval);
1069                                         break;
1070                                 case RVAL_DECIMAL:
1071                                         tprintf("= %ld", tcp->u_rval);
1072                                         break;
1073                                 default:
1074                                         fprintf(stderr,
1075                                                 "invalid rval format\n");
1076                                         break;
1077                                 }
1078                         }
1079                         if ((sys_res & RVAL_STR) && tcp->auxstr)
1080                                 tprintf(" (%s)", tcp->auxstr);
1081                 }
1082                 if (dtime) {
1083                         tv_sub(&tv, &tv, &tcp->etime);
1084                         tprintf(" <%ld.%06ld>",
1085                                 (long) tv.tv_sec, (long) tv.tv_usec);
1086                 }
1087                 printtrailer(tcp);
1088
1089                 dumpio(tcp);
1090                 if (fflush(tcp->outf) == EOF)
1091                         return -1;
1092                 tcp->flags &= ~TCB_INSYSCALL;
1093                 return 0;
1094         }
1095
1096         /* Entering system call */
1097         tcp->scno = scno;
1098 #ifdef LINUX
1099 #if defined(S390)
1100         {
1101                 int i;
1102                 tcp->u_nargs = sysent[tcp->scno].nargs;
1103                 for (i = 0; i < tcp->u_nargs; i++) {
1104                         if (upeek(pid,i==0 ? PT_ORIGGPR2:PT_GPR2+(i<<2), &tcp->u_arg[i]) < 0)
1105                                 return -1;
1106                 }
1107         }
1108 #elif defined (ALPHA)
1109         {
1110                 int i;
1111                 tcp->u_nargs = sysent[tcp->scno].nargs;
1112                 for (i = 0; i < tcp->u_nargs; i++) {
1113                         /* WTA: if scno is out-of-bounds this will bomb. Add range-check
1114                          * for scno somewhere above here!
1115                          */
1116                         if (upeek(pid, REG_A0+i, &tcp->u_arg[i]) < 0)
1117                                 return -1;
1118                 }
1119         }
1120 #elif defined (MIPS)
1121         {
1122                 long sp;
1123                 int i, nargs;
1124
1125                 nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
1126                 if(nargs > 4) {
1127                         if(upeek(pid, REG_SP, &sp) < 0)
1128                                 return -1;
1129                         for(i = 0; i < 4; i++) {
1130                                 if (upeek(pid, REG_A0 + i, &tcp->u_arg[i])<0)
1131                                         return -1;
1132                         }
1133                         umoven(tcp, sp+16, (nargs-4) * sizeof(tcp->u_arg[0]),
1134                                (char *)(tcp->u_arg + 4));
1135                 } else {
1136                         for(i = 0; i < nargs; i++) {
1137                                 if (upeek(pid, REG_A0 + i, &tcp->u_arg[i]) < 0)
1138                                         return -1;
1139                         }
1140                 }
1141         }
1142 #elif defined (POWERPC)
1143         {
1144                 int i;
1145                 tcp->u_nargs = sysent[tcp->scno].nargs;
1146                 for (i = 0; i < tcp->u_nargs; i++) {
1147                         if (upeek(pid, (i==0) ? (4*PT_ORIG_R3) : ((i+PT_R3)*4), &tcp->u_arg[i]) < 0)
1148                                 return -1;
1149                 }
1150         }
1151 #elif defined (SPARC)
1152         {
1153                 int i;
1154                  
1155                 tcp->u_nargs = sysent[tcp->scno].nargs;
1156                 for (i = 0; i < tcp->u_nargs; i++)
1157                         tcp->u_arg[i] = *((&regs.r_o0) + i);
1158         }
1159 #else 
1160         {
1161                 int i;
1162                 tcp->u_nargs = sysent[tcp->scno].nargs;
1163                 for (i = 0; i < tcp->u_nargs; i++) {
1164                         if (upeek(pid, i*4, &tcp->u_arg[i]) < 0)
1165                                 return -1;
1166                 }
1167         }
1168 #endif 
1169 #endif /* LINUX */
1170 #ifdef SUNOS4
1171         {
1172                 int i;
1173                 tcp->u_nargs = sysent[tcp->scno].nargs;
1174                 for (i = 0; i < tcp->u_nargs; i++) {
1175                         struct user *u;
1176
1177                         if (upeek(pid, uoff(u_arg[0]) +
1178                             (i*sizeof(u->u_arg[0])), &tcp->u_arg[i]) < 0)
1179                                 return -1;
1180                 }
1181         }
1182 #endif /* SUNOS4 */
1183 #ifdef SVR4
1184 #ifdef MIPS
1185         /*
1186          * SGI is broken: even though it has pr_sysarg, it doesn't
1187          * set them on system call entry.  Get a clue.
1188          */
1189         if (sysent[tcp->scno].nargs != -1)
1190                 tcp->u_nargs = sysent[tcp->scno].nargs;
1191         else
1192                 tcp->u_nargs = tcp->status.pr_nsysarg;
1193         if (tcp->u_nargs > 4) {
1194                 memcpy(tcp->u_arg, &tcp->status.pr_reg[CTX_A0],
1195                         4*sizeof(tcp->u_arg[0]));
1196                 umoven(tcp, tcp->status.pr_reg[CTX_SP] + 16,
1197                         (tcp->u_nargs - 4)*sizeof(tcp->u_arg[0]), (char *) (tcp->u_arg + 4));
1198         }
1199         else {
1200                 memcpy(tcp->u_arg, &tcp->status.pr_reg[CTX_A0],
1201                         tcp->u_nargs*sizeof(tcp->u_arg[0]));
1202         }
1203 #else /* !MIPS */
1204 #ifdef HAVE_PR_SYSCALL
1205         if (sysent[tcp->scno].nargs != -1)
1206                 tcp->u_nargs = sysent[tcp->scno].nargs;
1207         else
1208                 tcp->u_nargs = tcp->status.pr_nsysarg;
1209         {
1210                 int i;
1211                 for (i = 0; i < tcp->u_nargs; i++)
1212                         tcp->u_arg[i] = tcp->status.pr_sysarg[i];
1213         }
1214 #else /* !HAVE_PR_SYSCALL */
1215 #ifdef I386
1216         if (sysent[tcp->scno].nargs != -1)
1217                 tcp->u_nargs = sysent[tcp->scno].nargs;
1218         else
1219 #if UNIXWARE >= 2
1220                 tcp->u_nargs = tcp->status.pr_lwp.pr_nsysarg;
1221 #else
1222                 tcp->u_nargs = 5;
1223 #endif
1224         umoven(tcp, tcp->status.PR_REG[UESP] + 4,
1225                 tcp->u_nargs*sizeof(tcp->u_arg[0]), (char *) tcp->u_arg);
1226 #endif /* I386 */
1227 #endif /* !HAVE_PR_SYSCALL */
1228 #endif /* !MIPS */
1229 #endif /* SVR4 */
1230         switch (tcp->scno + NR_SYSCALL_BASE) {
1231 #ifdef LINUX
1232 #if !defined (ALPHA) && !defined(SPARC) && !defined(MIPS)
1233         case SYS_socketcall:
1234                 decode_subcall(tcp, SYS_socket_subcall,
1235                         SYS_socket_nsubcalls, deref_style);
1236                 break;
1237         case SYS_ipc:
1238                 decode_subcall(tcp, SYS_ipc_subcall,
1239                         SYS_ipc_nsubcalls, shift_style);
1240                 break;
1241 #endif /* !ALPHA && !SPARC */
1242 #ifdef SPARC
1243         case SYS_socketcall:
1244                 sparc_socket_decode (tcp);
1245                 break;
1246 #endif
1247 #endif /* LINUX */
1248 #ifdef SVR4
1249 #ifdef SYS_pgrpsys_subcall
1250         case SYS_pgrpsys:
1251                 decode_subcall(tcp, SYS_pgrpsys_subcall,
1252                         SYS_pgrpsys_nsubcalls, shift_style);
1253                 break;
1254 #endif /* SYS_pgrpsys_subcall */
1255 #ifdef SYS_sigcall_subcall
1256         case SYS_sigcall:
1257                 decode_subcall(tcp, SYS_sigcall_subcall,
1258                         SYS_sigcall_nsubcalls, mask_style);
1259                 break;
1260 #endif /* SYS_sigcall_subcall */
1261         case SYS_msgsys:
1262                 decode_subcall(tcp, SYS_msgsys_subcall,
1263                         SYS_msgsys_nsubcalls, shift_style);
1264                 break;
1265         case SYS_shmsys:
1266                 decode_subcall(tcp, SYS_shmsys_subcall,
1267                         SYS_shmsys_nsubcalls, shift_style);
1268                 break;
1269         case SYS_semsys:
1270                 decode_subcall(tcp, SYS_semsys_subcall,
1271                         SYS_semsys_nsubcalls, shift_style);
1272                 break;
1273 #if 0 /* broken */
1274         case SYS_utssys:
1275                 decode_subcall(tcp, SYS_utssys_subcall,
1276                         SYS_utssys_nsubcalls, shift_style);
1277                 break;
1278 #endif
1279         case SYS_sysfs:
1280                 decode_subcall(tcp, SYS_sysfs_subcall,
1281                         SYS_sysfs_nsubcalls, shift_style);
1282                 break;
1283         case SYS_spcall:
1284                 decode_subcall(tcp, SYS_spcall_subcall,
1285                         SYS_spcall_nsubcalls, shift_style);
1286                 break;
1287 #ifdef SYS_context_subcall
1288         case SYS_context:
1289                 decode_subcall(tcp, SYS_context_subcall,
1290                         SYS_context_nsubcalls, shift_style);
1291                 break;
1292 #endif /* SYS_context_subcall */
1293 #ifdef SYS_door_subcall
1294         case SYS_door:
1295                 decode_subcall(tcp, SYS_door_subcall,
1296                         SYS_door_nsubcalls, door_style);
1297                 break;
1298 #endif /* SYS_door_subcall */
1299 #endif /* SVR4 */
1300 #ifdef SUNOS4
1301         case SYS_semsys:
1302                 decode_subcall(tcp, SYS_semsys_subcall,
1303                         SYS_semsys_nsubcalls, shift_style);
1304                 break;
1305         case SYS_msgsys:
1306                 decode_subcall(tcp, SYS_msgsys_subcall,
1307                         SYS_msgsys_nsubcalls, shift_style);
1308                 break;
1309         case SYS_shmsys:
1310                 decode_subcall(tcp, SYS_shmsys_subcall,
1311                         SYS_shmsys_nsubcalls, shift_style);
1312                 break;
1313 #endif
1314         }
1315
1316         internal_syscall(tcp);
1317         if (!(qual_flags[tcp->scno] & QUAL_TRACE)) {
1318                 tcp->flags |= TCB_INSYSCALL;
1319                 return 0;
1320         }
1321
1322         if (cflag) {
1323                 gettimeofday(&tcp->etime, NULL);
1324                 tcp->flags |= TCB_INSYSCALL;
1325                 return 0;
1326         }
1327
1328         printleader(tcp);
1329         tcp->flags &= ~TCB_REPRINT;
1330         tcp_last = tcp;
1331         if (tcp->scno >= nsyscalls)
1332                 tprintf("syscall_%lu(", tcp->scno);
1333         else
1334                 tprintf("%s(", sysent[tcp->scno].sys_name);
1335         if (tcp->scno >= nsyscalls ||
1336             ((qual_flags[tcp->scno] & QUAL_RAW) && tcp->scno != SYS_exit))
1337                 sys_res = printargs(tcp);
1338         else
1339                 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
1340         if (fflush(tcp->outf) == EOF)
1341                 return -1;
1342         tcp->flags |= TCB_INSYSCALL;
1343         /* Measure the entrance time as late as possible to avoid errors. */
1344         if (dtime)
1345                 gettimeofday(&tcp->etime, NULL);
1346         return sys_res;
1347 }
1348
1349 int
1350 printargs(tcp)
1351 struct tcb *tcp;
1352 {
1353         if (entering(tcp)) {
1354                 int i;
1355
1356                 for (i = 0; i < tcp->u_nargs; i++)
1357                         tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
1358         }
1359         return 0;
1360 }
1361
1362 long
1363 getrval2(tcp)
1364 struct tcb *tcp;
1365 {
1366         long val = -1;
1367
1368 #ifdef LINUX
1369 #ifdef SPARC
1370         struct regs regs;
1371         if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
1372                 return -1;
1373         val = regs.r_o1;
1374 #endif /* SPARC */
1375 #endif /* LINUX */
1376
1377 #ifdef SUNOS4
1378         if (upeek(tcp->pid, uoff(u_rval2), &val) < 0)
1379                 return -1;
1380 #endif /* SUNOS4 */
1381
1382 #ifdef SVR4
1383 #ifdef SPARC
1384         val = tcp->status.PR_REG[R_O1];
1385 #endif /* SPARC */
1386 #ifdef I386
1387         val = tcp->status.PR_REG[EDX];
1388 #endif /* I386 */
1389 #ifdef MIPS
1390         val = tcp->status.PR_REG[CTX_V1];
1391 #endif /* MIPS */
1392 #endif /* SVR4 */
1393
1394         return val;
1395 }
1396
1397 /*
1398  * Apparently, indirect system calls have already be converted by ptrace(2),
1399  * so if you see "indir" this program has gone astray.
1400  */
1401 int
1402 sys_indir(tcp)
1403 struct tcb *tcp;
1404 {
1405         int i, scno, nargs;
1406
1407         if (entering(tcp)) {
1408                 if ((scno = tcp->u_arg[0]) > nsyscalls) {
1409                         fprintf(stderr, "Bogus syscall: %u\n", scno);
1410                         return 0;
1411                 }
1412                 nargs = sysent[scno].nargs;
1413                 tprintf("%s", sysent[scno].sys_name);
1414                 for (i = 0; i < nargs; i++)
1415                         tprintf(", %#lx", tcp->u_arg[i+1]);
1416         }
1417         return 0;
1418 }
1419
1420 static int
1421 time_cmp(a, b)
1422 void *a;
1423 void *b;
1424 {
1425         return -tv_cmp(&tv_count[*((int *) a)], &tv_count[*((int *) b)]);
1426 }
1427
1428 static int
1429 syscall_cmp(a, b)
1430 void *a;
1431 void *b;
1432 {
1433         return strcmp(sysent[*((int *) a)].sys_name,
1434                 sysent[*((int *) b)].sys_name);
1435 }
1436
1437 static int
1438 count_cmp(a, b)
1439 void *a;
1440 void *b;
1441 {
1442         int m = call_count[*((int *) a)], n = call_count[*((int *) b)];
1443
1444         return (m < n) ? 1 : (m > n) ? -1 : 0;
1445 }
1446
1447 static int (*sortfun)();
1448 static struct timeval overhead = { -1, -1 };
1449
1450 void
1451 set_sortby(sortby)
1452 char *sortby;
1453 {
1454         if (strcmp(sortby, "time") == 0)
1455                 sortfun = time_cmp;
1456         else if (strcmp(sortby, "calls") == 0)
1457                 sortfun = count_cmp;
1458         else if (strcmp(sortby, "name") == 0)
1459                 sortfun = syscall_cmp;
1460         else if (strcmp(sortby, "nothing") == 0)
1461                 sortfun = NULL;
1462         else {
1463                 fprintf(stderr, "invalid sortby: `%s'\n", sortby);
1464                 exit(1);
1465         }
1466 }
1467
1468 void set_overhead(n)
1469 int n;
1470 {
1471         overhead.tv_sec = n / 1000000;
1472         overhead.tv_usec = n % 1000000;
1473 }
1474
1475 void
1476 call_summary(outf)
1477 FILE *outf;
1478 {
1479         int i, j;
1480         int call_cum, error_cum;
1481         struct timeval tv_cum, dtv;
1482         double percent;
1483         char *dashes = "-------------------------";
1484         char error_str[16];
1485
1486         call_cum = error_cum = tv_cum.tv_sec = tv_cum.tv_usec = 0;
1487         if (overhead.tv_sec == -1) {
1488                 tv_mul(&overhead, &shortest, 8);
1489                 tv_div(&overhead, &overhead, 10);
1490         }
1491         for (i = 0; i < nsyscalls; i++) {
1492                 sorted_count[i] = i;
1493                 if (call_count[i] == 0)
1494                         continue;
1495                 tv_mul(&dtv, &overhead, call_count[i]);
1496                 tv_sub(&tv_count[i], &tv_count[i], &dtv);
1497                 call_cum += call_count[i];
1498                 error_cum += error_count[i];
1499                 tv_add(&tv_cum, &tv_cum, &tv_count[i]);
1500         }
1501         if (sortfun)
1502                 qsort((void *) sorted_count, nsyscalls, sizeof(int), sortfun);
1503         fprintf(outf, "%6.6s %11.11s %11.11s %9.9s %9.9s %s\n",
1504                 "% time", "seconds", "usecs/call",
1505                 "calls", "errors", "syscall");
1506         fprintf(outf, "%6.6s %11.11s %11.11s %9.9s %9.9s %-16.16s\n",
1507                 dashes, dashes, dashes, dashes, dashes, dashes);
1508         for (i = 0; i < nsyscalls; i++) {
1509                 j = sorted_count[i];
1510                 if (call_count[j] == 0)
1511                         continue;
1512                 tv_div(&dtv, &tv_count[j], call_count[j]);
1513                 if (error_count[j])
1514                         sprintf(error_str, "%d", error_count[j]);
1515                 else
1516                         error_str[0] = '\0';
1517                 percent = 100.0*tv_float(&tv_count[j])/tv_float(&tv_cum);
1518                 fprintf(outf, "%6.2f %4ld.%06ld %11ld %9d %9.9s %s\n",
1519                         percent, (long) tv_count[j].tv_sec,
1520                         (long) tv_count[j].tv_usec,
1521                         (long) 1000000 * dtv.tv_sec + dtv.tv_usec,
1522                         call_count[j], error_str, sysent[j].sys_name);
1523         }
1524         fprintf(outf, "%6.6s %11.11s %11.11s %9.9s %9.9s %-16.16s\n",
1525                 dashes, dashes, dashes, dashes, dashes, dashes);
1526         if (error_cum)
1527                 sprintf(error_str, "%d", error_cum);
1528         else
1529                 error_str[0] = '\0';
1530         fprintf(outf, "%6.6s %4ld.%06ld %11.11s %9d %9.9s %s\n",
1531                 "100.00", (long) tv_cum.tv_sec, (long) tv_cum.tv_usec, "",
1532                 call_cum, error_str, "total");
1533 }