]> granicus.if.org Git - strace/blob - syscall.c
Fix signed/unsigned problems
[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 static 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 #endif 
688 #endif /* LINUX */
689 #ifdef FREEBSD
690         struct reg regs;
691 #endif /* FREEBSD */    
692
693 int
694 get_scno(tcp)
695 struct tcb *tcp;
696 {
697         long scno = 0;
698 #ifndef USE_PROCFS
699         int pid = tcp->pid;
700 #endif /* !PROCFS */    
701
702 #ifdef LINUX
703 #if defined(S390)
704         if (upeek(tcp->pid,PT_PSWADDR,&pc) < 0)
705                 return -1;
706         scno = ptrace(PTRACE_PEEKTEXT, tcp->pid, (char *)(pc-4),0);
707         if (errno)
708                 return -1;
709         scno&=0xFF;
710 #elif defined (POWERPC)
711         if (upeek(pid, 4*PT_R0, &scno) < 0)
712                 return -1;
713         if (!(tcp->flags & TCB_INSYSCALL)) {
714                 /* Check if we return from execve. */
715                 if (scno == 0 && (tcp->flags & TCB_WAITEXECVE)) {
716                         tcp->flags &= ~TCB_WAITEXECVE;
717                         return 0;
718                 }
719         }
720 #elif defined (I386)
721         if (upeek(pid, 4*ORIG_EAX, &scno) < 0)
722                 return -1;
723 #elif defined(IA64)
724 #       define IA64_PSR_IS      ((long)1 << 34)
725         if (upeek (pid, PT_CR_IPSR, &psr) >= 0)
726                 ia32 = (psr & IA64_PSR_IS) != 0;
727         if (!(tcp->flags & TCB_INSYSCALL)) {
728                 if (ia32) {
729                         if (upeek(pid, PT_R1, &scno) < 0)       /* orig eax */
730                                 return -1;
731                         /* Check if we return from execve. */
732                 } else {
733                         if (upeek (pid, PT_R15, &scno) < 0)
734                                 return -1;
735                 }
736         } else {
737                 /* syscall in progress */
738                 if (upeek (pid, PT_R8, &r8) < 0)
739                         return -1;
740                 if (upeek (pid, PT_R10, &r10) < 0)
741                         return -1;
742         }
743         if (tcp->flags & TCB_WAITEXECVE) {
744                 tcp->flags &= ~TCB_WAITEXECVE;
745                 return 0;
746         }
747
748 #elif defined (ARM)
749         { 
750             long pc;
751             upeek(pid, 4*15, &pc);
752             umoven(tcp, pc-4, 4, (char *)&scno);
753             scno &= 0x000fffff;
754         }
755 #elif defined (M68K)
756         if (upeek(pid, 4*PT_ORIG_D0, &scno) < 0)
757                 return -1;
758 #elif defined (MIPS)
759         if (upeek(pid, REG_A3, &a3) < 0)
760                 return -1;
761
762         if(!(tcp->flags & TCB_INSYSCALL)) {
763                 if (upeek(pid, REG_V0, &scno) < 0)
764                         return -1;
765
766                 if (scno < 0 || scno > nsyscalls) {
767                         if(a3 == 0 || a3 == -1) {
768                                 if(debug)
769                                         fprintf (stderr, "stray syscall exit: v0 = %ld\n", scno);
770                                 return 0;
771                         }
772                 }
773         } else {
774                 if (upeek(pid, REG_V0, &r2) < 0)
775                         return -1;
776         }
777 #elif defined (ALPHA)
778         if (upeek(pid, REG_A3, &a3) < 0)
779                 return -1;
780
781         if (!(tcp->flags & TCB_INSYSCALL)) {
782                 if (upeek(pid, REG_R0, &scno) < 0)
783                         return -1;
784
785                 /* Check if we return from execve. */
786                 if (scno == 0 && tcp->flags & TCB_WAITEXECVE) {
787                         tcp->flags &= ~TCB_WAITEXECVE;
788                         return 0;
789                 }
790
791                 /*
792                  * Do some sanity checks to figure out if it's
793                  * really a syscall entry
794                  */
795                 if (scno < 0 || scno > nsyscalls) {
796                         if (a3 == 0 || a3 == -1) {
797                                 if (debug)
798                                         fprintf (stderr, "stray syscall exit: r0 = %ld\n", scno);
799                                 return 0;
800                         }
801                 }
802         }
803         else {
804                 if (upeek(pid, REG_R0, &r0) < 0)
805                         return -1;
806         }
807 #elif defined (SPARC)
808         /* Everything we need is in the current register set. */
809         if (ptrace(PTRACE_GETREGS,pid,(char *)&regs,0) < 0)
810                 return -1;
811
812         /* If we are entering, then disassemble the syscall trap. */
813         if (!(tcp->flags & TCB_INSYSCALL)) {
814                 /* Retrieve the syscall trap instruction. */
815                 errno = 0;
816                 trap = ptrace(PTRACE_PEEKTEXT,pid,(char *)regs.r_pc,0);
817                 if (errno)
818                         return -1;
819
820                 /* Disassemble the trap to see what personality to use. */
821                 switch (trap) {
822                 case 0x91d02010:
823                         /* Linux/SPARC syscall trap. */
824                         set_personality(0);
825                         break;
826                 case 0x91d0206d:
827                         /* Linux/SPARC64 syscall trap. */
828                         fprintf(stderr,"syscall: Linux/SPARC64 not supported yet\n");
829                         return -1;
830                 case 0x91d02000:
831                         /* SunOS syscall trap. (pers 1) */
832                         fprintf(stderr,"syscall: SunOS no support\n");
833                         return -1;
834                 case 0x91d02008:
835                         /* Solaris 2.x syscall trap. (per 2) */
836                         set_personality(1);
837                         break; 
838                 case 0x91d02009:
839                         /* NetBSD/FreeBSD syscall trap. */
840                         fprintf(stderr,"syscall: NetBSD/FreeBSD not supported\n");
841                         return -1;
842                 case 0x91d02027:
843                         /* Solaris 2.x gettimeofday */
844                         set_personality(1);
845                         break;
846                 default:
847                         /* Unknown syscall trap. */
848                         if(tcp->flags & TCB_WAITEXECVE) {
849                                 tcp->flags &= ~TCB_WAITEXECVE;
850                                 return 0;
851                         }
852                         fprintf(stderr,"syscall: unknown syscall trap %08x %08x\n", trap, regs.r_pc);
853                         return -1;
854                 }
855
856                 /* Extract the system call number from the registers. */
857                 if (trap == 0x91d02027)
858                         scno = 156;
859                 else
860                         scno = regs.r_g1;
861                 if (scno == 0) {
862                         scno = regs.r_o0;
863                         memmove (&regs.r_o0, &regs.r_o1, 7*sizeof(regs.r_o0));
864                 }
865         }
866 #elif defined(HPPA)
867         if (upeek(pid, PT_GR20, &scno) < 0)
868                 return -1;
869         if (!(tcp->flags & TCB_INSYSCALL)) {
870                 /* Check if we return from execve. */
871                 if ((tcp->flags & TCB_WAITEXECVE)) {
872                         tcp->flags &= ~TCB_WAITEXECVE;
873                         return 0;
874                 }
875         }
876 #endif 
877 #endif /* LINUX */
878 #ifdef SUNOS4
879         if (upeek(pid, uoff(u_arg[7]), &scno) < 0)
880                 return -1;
881 #endif
882 #ifdef USE_PROCFS
883 #ifdef HAVE_PR_SYSCALL
884         scno = tcp->status.PR_SYSCALL;
885 #else /* !HAVE_PR_SYSCALL */
886 #ifndef FREEBSD
887         scno = tcp->status.PR_WHAT;
888 #else /* FREEBSD */
889         if (pread(tcp->pfd_reg, &regs, sizeof(regs), 0) < 0) {
890                 perror("pread");
891                 return -1;
892         }
893         switch (regs.r_eax) {
894         case SYS_syscall:
895         case SYS___syscall:
896                 pread(tcp->pfd, &scno, sizeof(scno), regs.r_esp + sizeof(int));
897                 break;
898         default:
899                 scno = regs.r_eax;
900                 break;
901         }
902 #endif /* FREEBSD */
903 #endif /* !HAVE_PR_SYSCALL */
904 #endif /* USE_PROCFS */
905         if (!(tcp->flags & TCB_INSYSCALL))
906                 tcp->scno = scno;
907         return 1;
908 }
909
910
911 int
912 syscall_fixup(tcp)
913 struct tcb *tcp;
914 {
915 #ifndef USE_PROCFS
916         int pid = tcp->pid;
917 #else /* USE_PROCFS */  
918         int scno = tcp->scno;
919
920         if (!(tcp->flags & TCB_INSYSCALL)) {
921                 if (tcp->status.PR_WHY != PR_SYSENTRY) {
922                         if (
923                             scno == SYS_fork
924 #ifdef SYS_vfork
925                             || scno == SYS_vfork
926 #endif /* SYS_vfork */
927 #ifdef SYS_fork1
928                             || scno == SYS_fork1
929 #endif /* SYS_fork1 */
930 #ifdef SYS_forkall
931                             || scno == SYS_forkall
932 #endif /* SYS_forkall */
933 #ifdef SYS_rfork1
934                             || scno == SYS_rfork1
935 #endif /* SYS_fork1 */
936 #ifdef SYS_rforkall
937                             || scno == SYS_rforkall
938 #endif /* SYS_rforkall */
939                             ) {
940                                 /* We are returning in the child, fake it. */
941                                 tcp->status.PR_WHY = PR_SYSENTRY;
942                                 trace_syscall(tcp);
943                                 tcp->status.PR_WHY = PR_SYSEXIT;
944                         }
945                         else {
946                                 fprintf(stderr, "syscall: missing entry\n");
947                                 tcp->flags |= TCB_INSYSCALL;
948                         }
949                 }
950         }
951         else {
952                 if (tcp->status.PR_WHY != PR_SYSEXIT) {
953                         fprintf(stderr, "syscall: missing exit\n");
954                         tcp->flags &= ~TCB_INSYSCALL;
955                 }
956         }
957 #endif /* USE_PROCFS */
958 #ifdef SUNOS4
959         if (!(tcp->flags & TCB_INSYSCALL)) {
960                 if (scno == 0) {
961                         fprintf(stderr, "syscall: missing entry\n");
962                         tcp->flags |= TCB_INSYSCALL;
963                 }
964         }
965         else {
966                 if (scno != 0) {
967                         if (debug) {
968                                 /*
969                                  * This happens when a signal handler
970                                  * for a signal which interrupted a
971                                  * a system call makes another system call.
972                                  */
973                                 fprintf(stderr, "syscall: missing exit\n");
974                         }
975                         tcp->flags &= ~TCB_INSYSCALL;
976                 }
977         }
978 #endif /* SUNOS4 */
979 #ifdef LINUX
980 #if defined (I386)
981         if (upeek(pid, 4*EAX, &eax) < 0)
982                 return -1;
983         if (eax != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
984                 if (debug)
985                         fprintf(stderr, "stray syscall exit: eax = %ld\n", eax);
986                 return 0;
987         }
988 #elif defined (S390)
989         if (upeek(pid, PT_GPR2, &gpr2) < 0)
990                 return -1;
991         if (gpr2 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
992                 if (debug)
993                         fprintf(stderr, "stray syscall exit: gpr2 = %ld\n", gpr2);
994                 return 0;
995         }
996 #elif defined (POWERPC)
997 # define SO_MASK 0x10000000
998         if (upeek(pid, 4*PT_CCR, &flags) < 0)
999                 return -1;
1000         if (upeek(pid, 4*PT_R3, &result) < 0)
1001                 return -1;
1002         if (flags & SO_MASK)
1003                 result = -result;
1004 #elif defined (M68K)
1005         if (upeek(pid, 4*PT_D0, &d0) < 0)
1006                 return -1;
1007         if (d0 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1008                 if (debug)
1009                         fprintf(stderr, "stray syscall exit: d0 = %ld\n", d0);
1010                 return 0;
1011         }
1012 #elif defined (ARM)
1013         if (upeek(pid, 4*0, (long *)&r0) < 0)
1014                 return -1;
1015         if ( 0 && r0 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1016                 if (debug)
1017                         fprintf(stderr, "stray syscall exit: d0 = %ld\n", r0);
1018                 return 0;
1019         }
1020 #elif defined (HPPA)
1021         if (upeek(pid, PT_GR28, &r28) < 0)
1022                 return -1;
1023 #elif defined(IA64)
1024         if (upeek(pid, PT_R10, &r10) < 0)
1025                 return -1;
1026         if (upeek(pid, PT_R8, &r8) < 0)
1027                 return -1;
1028         if (ia32 && r8 != -ENOSYS && !(tcp->flags & TCB_INSYSCALL)) {
1029                 if (debug)
1030                         fprintf(stderr, "stray syscall exit: r8 = %ld\n", r8);
1031                 return 0;
1032         }
1033 #endif
1034 #endif /* LINUX */
1035         return 1;
1036 }
1037
1038 int
1039 get_error(tcp)
1040 struct tcb *tcp;
1041 {
1042         int u_error = 0;
1043 #ifdef LINUX
1044 #ifdef S390
1045                 if (gpr2 && (unsigned) -gpr2 < nerrnos) {
1046                         tcp->u_rval = -1;
1047                         u_error = -gpr2;
1048                 }
1049                 else {
1050                         tcp->u_rval = gpr2;
1051                         u_error = 0;
1052                 }
1053 #else /* !S390 */
1054 #ifdef I386
1055                 if (eax < 0 && -eax < nerrnos) {
1056                         tcp->u_rval = -1;
1057                         u_error = -eax;
1058                 }
1059                 else {
1060                         tcp->u_rval = eax;
1061                         u_error = 0;
1062                 }
1063 #else /* !I386 */
1064 #ifdef IA64
1065                 if (ia32) {
1066                         int err;
1067
1068                         err = (int)r8;
1069                         if (err < 0 && -err < nerrnos) {
1070                                 tcp->u_rval = -1;
1071                                 u_error = -err;
1072                         }
1073                         else {
1074                                 tcp->u_rval = err;
1075                                 u_error = 0;
1076                         }
1077                 } else {
1078                         if (r10) {
1079                                 tcp->u_rval = -1;
1080                                 u_error = r8;
1081                         } else {
1082                                 tcp->u_rval = r8;
1083                                 u_error = 0;
1084                         }
1085                 }
1086 #else /* !IA64 */
1087 #ifdef MIPS
1088                 if (a3) {
1089                         tcp->u_rval = -1;
1090                         u_error = r2;
1091                 } else {
1092                         tcp->u_rval = r2;
1093                         u_error = 0;
1094                 }
1095 #else
1096 #ifdef POWERPC
1097                 if (result && (unsigned) -result < nerrnos) {
1098                         tcp->u_rval = -1;
1099                         u_error = -result;
1100                 }
1101                 else {
1102                         tcp->u_rval = result;
1103                         u_error = 0;
1104                 }
1105 #else /* !POWERPC */
1106 #ifdef M68K
1107                 if (d0 && (unsigned) -d0 < nerrnos) {
1108                         tcp->u_rval = -1;
1109                         u_error = -d0;
1110                 }
1111                 else {
1112                         tcp->u_rval = d0;
1113                         u_error = 0;
1114                 }
1115 #else /* !M68K */
1116 #ifdef ARM
1117                 if (r0 && (unsigned) -r0 < nerrnos) {
1118                         tcp->u_rval = -1;
1119                         u_error = -r0;
1120                 }
1121                 else {
1122                         tcp->u_rval = r0;
1123                         u_error = 0;
1124                 }
1125 #else /* !ARM */
1126 #ifdef ALPHA
1127                 if (a3) {
1128                         tcp->u_rval = -1;
1129                         u_error = r0;
1130                 }
1131                 else {
1132                         tcp->u_rval = r0;
1133                         u_error = 0;
1134                 }
1135 #else /* !ALPHA */
1136 #ifdef SPARC
1137                 if (regs.r_psr & PSR_C) {
1138                         tcp->u_rval = -1;
1139                         u_error = regs.r_o0;
1140                 }
1141                 else {
1142                         tcp->u_rval = regs.r_o0;
1143                         u_error = 0;
1144                 }
1145 #else /* !SPARC */
1146 #ifdef HPPA
1147                 if (r28 && (unsigned) -r28 < nerrnos) {
1148                         tcp->u_rval = -1;
1149                         u_error = -r28;
1150                 }
1151                 else {
1152                         tcp->u_rval = r28;
1153                         u_error = 0;
1154                 }
1155 #endif /* HPPA */
1156 #endif /* SPARC */
1157 #endif /* ALPHA */
1158 #endif /* ARM */
1159 #endif /* M68K */
1160 #endif /* POWERPC */
1161 #endif /* MIPS */
1162 #endif /* IA64 */
1163 #endif /* I386 */
1164 #endif /* S390 */
1165 #endif /* LINUX */
1166 #ifdef SUNOS4
1167                 /* get error code from user struct */
1168                 if (upeek(pid, uoff(u_error), &u_error) < 0)
1169                         return -1;
1170                 u_error >>= 24; /* u_error is a char */
1171
1172                 /* get system call return value */
1173                 if (upeek(pid, uoff(u_rval1), &tcp->u_rval) < 0)
1174                         return -1;
1175 #endif /* SUNOS4 */
1176 #ifdef SVR4
1177 #ifdef SPARC
1178                 /* Judicious guessing goes a long way. */
1179                 if (tcp->status.pr_reg[R_PSR] & 0x100000) {
1180                         tcp->u_rval = -1;
1181                         u_error = tcp->status.pr_reg[R_O0];
1182                 }
1183                 else {
1184                         tcp->u_rval = tcp->status.pr_reg[R_O0];
1185                         u_error = 0;
1186                 }
1187 #endif /* SPARC */
1188 #ifdef I386
1189                 /* Wanna know how to kill an hour single-stepping? */
1190                 if (tcp->status.PR_REG[EFL] & 0x1) {
1191                         tcp->u_rval = -1;
1192                         u_error = tcp->status.PR_REG[EAX];
1193                 }
1194                 else {
1195                         tcp->u_rval = tcp->status.PR_REG[EAX];
1196 #ifdef HAVE_LONG_LONG
1197                         tcp->u_lrval =
1198                                 ((unsigned long long) tcp->status.PR_REG[EDX] << 32) +
1199                                 tcp->status.PR_REG[EAX];
1200 #endif
1201                         u_error = 0;
1202                 }
1203 #endif /* I386 */
1204 #ifdef MIPS
1205                 if (tcp->status.pr_reg[CTX_A3]) {
1206                         tcp->u_rval = -1;
1207                         u_error = tcp->status.pr_reg[CTX_V0];
1208                 }
1209                 else {
1210                         tcp->u_rval = tcp->status.pr_reg[CTX_V0];
1211                         u_error = 0;
1212                 }
1213 #endif /* MIPS */
1214 #endif /* SVR4 */
1215 #ifdef FREEBSD
1216                 if (regs.r_eflags & PSL_C) {
1217                         tcp->u_rval = -1;
1218                         u_error = regs.r_eax;
1219                 } else {
1220                         tcp->u_rval = regs.r_eax;
1221                         tcp->u_lrval =
1222                           ((unsigned long long) regs.r_edx << 32) +  regs.r_eax;
1223                         u_error = 0;
1224                 }
1225 #endif /* FREEBSD */    
1226         tcp->u_error = u_error;
1227         return 1;
1228 }
1229
1230 int syscall_enter(tcp)
1231 struct tcb *tcp;
1232 {
1233 #ifndef USE_PROCFS
1234         int pid = tcp->pid;
1235 #endif /* !USE_PROCFS */        
1236 #ifdef LINUX
1237 #if defined(S390)
1238         {
1239                 int i;
1240                 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1241                         tcp->u_nargs = sysent[tcp->scno].nargs;
1242                 else 
1243                         tcp->u_nargs = MAX_ARGS;
1244                 for (i = 0; i < tcp->u_nargs; i++) {
1245                         if (upeek(pid,i==0 ? PT_ORIGGPR2:PT_GPR2+(i<<2), &tcp->u_arg[i]) < 0)
1246                                 return -1;
1247                 }
1248         }
1249 #elif defined (ALPHA)
1250         {
1251                 int i;
1252                 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1253                         tcp->u_nargs = sysent[tcp->scno].nargs;
1254                 else 
1255                         tcp->u_nargs = MAX_ARGS;
1256                 for (i = 0; i < tcp->u_nargs; i++) {
1257                         /* WTA: if scno is out-of-bounds this will bomb. Add range-check
1258                          * for scno somewhere above here!
1259                          */
1260                         if (upeek(pid, REG_A0+i, &tcp->u_arg[i]) < 0)
1261                                 return -1;
1262                 }
1263         }
1264 #elif defined (IA64)
1265         {
1266                 if (!ia32) {
1267                         unsigned long *out0, *rbs_end, cfm, sof, sol, i;
1268                         /* be backwards compatible with kernel < 2.4.4... */
1269 #                       ifndef PT_RBS_END
1270 #                         define PT_RBS_END     PT_AR_BSP
1271 #                       endif
1272
1273                         if (upeek(pid, PT_RBS_END, (long *) &rbs_end) < 0)
1274                                 return -1;
1275                         if (upeek(pid, PT_CFM, (long *) &cfm) < 0)
1276                                 return -1;
1277
1278                         sof = (cfm >> 0) & 0x7f;
1279                         sol = (cfm >> 7) & 0x7f;
1280                         out0 = ia64_rse_skip_regs(rbs_end, -sof + sol);
1281
1282                         if (tcp->scno >= 0 && tcp->scno < nsyscalls
1283                             && sysent[tcp->scno].nargs != -1)
1284                                 tcp->u_nargs = sysent[tcp->scno].nargs;
1285                         else
1286                                 tcp->u_nargs = MAX_ARGS;
1287                         for (i = 0; i < tcp->u_nargs; ++i) {
1288                                 if (umoven(tcp, (unsigned long) ia64_rse_skip_regs(out0, i),
1289                                            sizeof(long), (char *) &tcp->u_arg[i]) < 0)
1290                                         return -1;
1291                         }
1292                 } else {
1293                         int i;
1294
1295                         if (/* EBX = out0 */
1296                             upeek(pid, PT_R11, (long *) &tcp->u_arg[0]) < 0
1297                             /* ECX = out1 */
1298                             || upeek(pid, PT_R9,  (long *) &tcp->u_arg[1]) < 0
1299                             /* EDX = out2 */
1300                             || upeek(pid, PT_R10, (long *) &tcp->u_arg[2]) < 0
1301                             /* ESI = out3 */
1302                             || upeek(pid, PT_R14, (long *) &tcp->u_arg[3]) < 0
1303                             /* EDI = out4 */
1304                             || upeek(pid, PT_R15, (long *) &tcp->u_arg[4]) < 0
1305                             /* EBP = out5 */
1306                             || upeek(pid, PT_R13, (long *) &tcp->u_arg[5]) < 0)
1307                                 return -1;
1308
1309                         for (i = 0; i < 6; ++i)
1310                                 /* truncate away IVE sign-extension */
1311                                 tcp->u_arg[i] &= 0xffffffff;
1312
1313                         if (tcp->scno >= 0 && tcp->scno < nsyscalls
1314                             && sysent[tcp->scno].nargs != -1)
1315                                 tcp->u_nargs = sysent[tcp->scno].nargs;
1316                         else
1317                                 tcp->u_nargs = 5;
1318                 }
1319         }
1320 #elif defined (MIPS)
1321         {
1322                 long sp;
1323                 int i, nargs;
1324
1325                 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1326                         nargs = tcp->u_nargs = sysent[tcp->scno].nargs;
1327                 else 
1328                         nargs = tcp->u_nargs = MAX_ARGS;
1329                 if(nargs > 4) {
1330                         if(upeek(pid, REG_SP, &sp) < 0)
1331                                 return -1;
1332                         for(i = 0; i < 4; i++) {
1333                                 if (upeek(pid, REG_A0 + i, &tcp->u_arg[i])<0)
1334                                         return -1;
1335                         }
1336                         umoven(tcp, sp+16, (nargs-4) * sizeof(tcp->u_arg[0]),
1337                                (char *)(tcp->u_arg + 4));
1338                 } else {
1339                         for(i = 0; i < nargs; i++) {
1340                                 if (upeek(pid, REG_A0 + i, &tcp->u_arg[i]) < 0)
1341                                         return -1;
1342                         }
1343                 }
1344         }
1345 #elif defined (POWERPC)
1346         {
1347                 int i;
1348                 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1349                         tcp->u_nargs = sysent[tcp->scno].nargs;
1350                 else 
1351                         tcp->u_nargs = MAX_ARGS;
1352                 for (i = 0; i < tcp->u_nargs; i++) {
1353                         if (upeek(pid, (i==0) ? (4*PT_ORIG_R3) : ((i+PT_R3)*4), &tcp->u_arg[i]) < 0)
1354                                 return -1;
1355                 }
1356         }
1357 #elif defined (SPARC)
1358         {
1359                 int i;
1360
1361                 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1362                         tcp->u_nargs = sysent[tcp->scno].nargs;
1363                 else 
1364                         tcp->u_nargs = MAX_ARGS;
1365                 for (i = 0; i < tcp->u_nargs; i++)
1366                         tcp->u_arg[i] = *((&regs.r_o0) + i);
1367         }
1368 #elif defined (HPPA)
1369         {
1370                 int i;
1371
1372                 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1373                         tcp->u_nargs = sysent[tcp->scno].nargs;
1374                 else 
1375                         tcp->u_nargs = MAX_ARGS;
1376                 for (i = 0; i < tcp->u_nargs; i++) {
1377                         if (upeek(pid, PT_GR26-4*i, &tcp->u_arg[i]) < 0)
1378                                 return -1;
1379                 }
1380         }
1381 #else /* Other architecture (like i386) (32bits specific) */
1382         {
1383                 int i;
1384                 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1385                         tcp->u_nargs = sysent[tcp->scno].nargs;
1386                 else 
1387                         tcp->u_nargs = MAX_ARGS;
1388                 for (i = 0; i < tcp->u_nargs; i++) {
1389                         if (upeek(pid, i*4, &tcp->u_arg[i]) < 0)
1390                                 return -1;
1391                 }
1392         }
1393 #endif 
1394 #endif /* LINUX */
1395 #ifdef SUNOS4
1396         {
1397                 int i;
1398                 if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1399                         tcp->u_nargs = sysent[tcp->scno].nargs;
1400                 else 
1401                         tcp->u_nargs = MAX_ARGS;
1402                 for (i = 0; i < tcp->u_nargs; i++) {
1403                         struct user *u;
1404
1405                         if (upeek(pid, uoff(u_arg[0]) +
1406                             (i*sizeof(u->u_arg[0])), &tcp->u_arg[i]) < 0)
1407                                 return -1;
1408                 }
1409         }
1410 #endif /* SUNOS4 */
1411 #ifdef SVR4
1412 #ifdef MIPS
1413         /*
1414          * SGI is broken: even though it has pr_sysarg, it doesn't
1415          * set them on system call entry.  Get a clue.
1416          */
1417         if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1418                 tcp->u_nargs = sysent[tcp->scno].nargs;
1419         else
1420                 tcp->u_nargs = tcp->status.pr_nsysarg;
1421         if (tcp->u_nargs > 4) {
1422                 memcpy(tcp->u_arg, &tcp->status.pr_reg[CTX_A0],
1423                         4*sizeof(tcp->u_arg[0]));
1424                 umoven(tcp, tcp->status.pr_reg[CTX_SP] + 16,
1425                         (tcp->u_nargs - 4)*sizeof(tcp->u_arg[0]), (char *) (tcp->u_arg + 4));
1426         }
1427         else {
1428                 memcpy(tcp->u_arg, &tcp->status.pr_reg[CTX_A0],
1429                         tcp->u_nargs*sizeof(tcp->u_arg[0]));
1430         }
1431 #elif UNIXWARE >= 2
1432         /*
1433          * Like SGI, UnixWare doesn't set pr_sysarg until system call exit
1434          */
1435         if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1436                 tcp->u_nargs = sysent[tcp->scno].nargs;
1437         else
1438                 tcp->u_nargs = tcp->status.pr_lwp.pr_nsysarg;
1439         umoven(tcp, tcp->status.PR_REG[UESP] + 4,
1440                 tcp->u_nargs*sizeof(tcp->u_arg[0]), (char *) tcp->u_arg);
1441 #elif defined (HAVE_PR_SYSCALL)
1442         if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1443                 tcp->u_nargs = sysent[tcp->scno].nargs;
1444         else
1445                 tcp->u_nargs = tcp->status.pr_nsysarg;
1446         {
1447                 int i;
1448                 for (i = 0; i < tcp->u_nargs; i++)
1449                         tcp->u_arg[i] = tcp->status.pr_sysarg[i];
1450         }
1451 #elif defined (I386)
1452         if (tcp->scno >= 0 && tcp->scno < nsyscalls && sysent[tcp->scno].nargs != -1)
1453                 tcp->u_nargs = sysent[tcp->scno].nargs;
1454         else
1455                 tcp->u_nargs = 5;
1456         umoven(tcp, tcp->status.PR_REG[UESP] + 4,
1457                 tcp->u_nargs*sizeof(tcp->u_arg[0]), (char *) tcp->u_arg);
1458 #else
1459         I DONT KNOW WHAT TO DO
1460 #endif /* !HAVE_PR_SYSCALL */
1461 #endif /* SVR4 */
1462 #ifdef FREEBSD
1463         if (tcp->scno >= 0 && tcp->scno < nsyscalls &&
1464             sysent[tcp->scno].nargs > tcp->status.val)
1465                 tcp->u_nargs = sysent[tcp->scno].nargs;
1466         else 
1467                 tcp->u_nargs = tcp->status.val;
1468         if (tcp->u_nargs < 0)
1469                 tcp->u_nargs = 0;
1470         if (tcp->u_nargs > MAX_ARGS)
1471                 tcp->u_nargs = MAX_ARGS;
1472         switch(regs.r_eax) {
1473         case SYS___syscall:
1474                 pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
1475                       regs.r_esp + sizeof(int) + sizeof(quad_t));
1476           break;
1477         case SYS_syscall:
1478                 pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
1479                       regs.r_esp + 2 * sizeof(int));
1480           break;
1481         default:
1482                 pread(tcp->pfd, &tcp->u_arg, tcp->u_nargs * sizeof(unsigned long),
1483                       regs.r_esp + sizeof(int));
1484           break;
1485         }
1486 #endif /* FREEBSD */
1487         return 1;
1488 }
1489
1490 int
1491 trace_syscall(tcp)
1492 struct tcb *tcp;
1493 {
1494         int sys_res;
1495         struct timeval tv;
1496         int res;
1497
1498         /* Measure the exit time as early as possible to avoid errors. */
1499         if (dtime && (tcp->flags & TCB_INSYSCALL))
1500                 gettimeofday(&tv, NULL);
1501
1502         res = get_scno(tcp);
1503         if (res != 1)
1504                 return res;
1505
1506         res = syscall_fixup(tcp);
1507         if (res != 1)
1508                 return res;
1509
1510         if (tcp->flags & TCB_INSYSCALL) {
1511                 long u_error;
1512                 res = get_error(tcp);
1513                 if (res != 1)
1514                         return res;
1515                 u_error = tcp->u_error;
1516
1517
1518                 internal_syscall(tcp);
1519                 if (tcp->scno >= 0 && tcp->scno < nsyscalls &&
1520                     !(qual_flags[tcp->scno] & QUAL_TRACE)) {
1521                         tcp->flags &= ~TCB_INSYSCALL;
1522                         return 0;
1523                 }
1524
1525                 if (tcp->flags & TCB_REPRINT) {
1526                         printleader(tcp);
1527                         tprintf("<... ");
1528                         if (tcp->scno >= nsyscalls || tcp->scno < 0)
1529                                 tprintf("syscall_%lu", tcp->scno);
1530                         else
1531                                 tprintf("%s", sysent[tcp->scno].sys_name);
1532                         tprintf(" resumed> ");
1533                 }
1534
1535                 if (cflag && tcp->scno < nsyscalls && tcp->scno >= 0) {
1536                         call_count[tcp->scno]++;
1537                         if (tcp->u_error)
1538                                 error_count[tcp->scno]++;
1539                         tv_sub(&tv, &tv, &tcp->etime);
1540 #ifdef LINUX
1541                         if (tv_cmp(&tv, &tcp->dtime) > 0) {
1542                                 static struct timeval one_tick =
1543                                         { 0, 1000000 / HZ };
1544
1545                                 if (tv_nz(&tcp->dtime))
1546                                         tv = tcp->dtime;
1547                                 else if (tv_cmp(&tv, &one_tick) > 0) {
1548                                         if (tv_cmp(&shortest, &one_tick) < 0)
1549                                                 tv = shortest;
1550                                         else
1551                                                 tv = one_tick;
1552                                 }
1553                         }
1554 #endif /* LINUX */
1555                         if (tv_cmp(&tv, &shortest) < 0)
1556                                 shortest = tv;
1557                         tv_add(&tv_count[tcp->scno],
1558                                 &tv_count[tcp->scno], &tv);
1559                         tcp->flags &= ~TCB_INSYSCALL;
1560                         return 0;
1561                 }
1562
1563                 if (tcp->scno >= nsyscalls || tcp->scno < 0
1564                     || (qual_flags[tcp->scno] & QUAL_RAW))
1565                         sys_res = printargs(tcp);
1566                 else
1567                         sys_res = (*sysent[tcp->scno].sys_func)(tcp);
1568                 u_error = tcp->u_error;
1569                 tprintf(") ");
1570                 tabto(acolumn);
1571                 if (tcp->scno >= nsyscalls || tcp->scno < 0 ||
1572                     qual_flags[tcp->scno] & QUAL_RAW) {
1573                         if (u_error)
1574                                 tprintf("= -1 (errno %ld)", u_error);
1575                         else
1576                                 tprintf("= %#lx", tcp->u_rval);
1577                 }
1578                 else if (!(sys_res & RVAL_NONE) && u_error) {
1579                         switch (u_error) {
1580 #ifdef LINUX
1581                         case ERESTARTSYS:
1582                                 tprintf("= ? ERESTARTSYS (To be restarted)");
1583                                 break;
1584                         case ERESTARTNOINTR:
1585                                 tprintf("= ? ERESTARTNOINTR (To be restarted)");
1586                                 break;
1587                         case ERESTARTNOHAND:
1588                                 tprintf("= ? ERESTARTNOHAND (To be restarted)");
1589                                 break;
1590 #endif /* LINUX */
1591                         default:
1592                                 tprintf("= -1 ");
1593                                 if (u_error < nerrnos && u_error < sys_nerr)
1594                                         tprintf("%s (%s)", errnoent[u_error],
1595                                                 sys_errlist[u_error]);
1596                                 else if (u_error < nerrnos)
1597                                         tprintf("%s (errno %ld)",
1598                                                 errnoent[u_error], u_error);
1599                                 else if (u_error < sys_nerr)
1600                                         tprintf("ERRNO_%ld (%s)", u_error,
1601                                                 sys_errlist[u_error]);
1602                                 else
1603                                         tprintf("E??? (errno %ld)", u_error);
1604                                 break;
1605                         }
1606                 }
1607                 else {
1608                         if (sys_res & RVAL_NONE)
1609                                 tprintf("= ?");
1610                         else {
1611                                 switch (sys_res & RVAL_MASK) {
1612                                 case RVAL_HEX:
1613                                         tprintf("= %#lx", tcp->u_rval);
1614                                         break;
1615                                 case RVAL_OCTAL:
1616                                         tprintf("= %#lo", tcp->u_rval);
1617                                         break;
1618                                 case RVAL_UDECIMAL:
1619                                         tprintf("= %lu", tcp->u_rval);
1620                                         break;
1621                                 case RVAL_DECIMAL:
1622                                         tprintf("= %ld", tcp->u_rval);
1623                                         break;
1624 #ifdef HAVE_LONG_LONG
1625                                 case RVAL_LHEX:
1626                                         tprintf("= %#llx", tcp->u_lrval);
1627                                         break;
1628                                 case RVAL_LOCTAL:
1629                                         tprintf("= %#llo", tcp->u_lrval);
1630                                         break;
1631                                 case RVAL_LUDECIMAL:
1632                                         tprintf("= %llu", tcp->u_lrval);
1633                                         break;
1634                                 case RVAL_LDECIMAL:
1635                                         tprintf("= %lld", tcp->u_lrval);
1636                                         break;
1637 #endif
1638                                 default:
1639                                         fprintf(stderr,
1640                                                 "invalid rval format\n");
1641                                         break;
1642                                 }
1643                         }
1644                         if ((sys_res & RVAL_STR) && tcp->auxstr)
1645                                 tprintf(" (%s)", tcp->auxstr);
1646                 }
1647                 if (dtime) {
1648                         tv_sub(&tv, &tv, &tcp->etime);
1649                         tprintf(" <%ld.%06ld>",
1650                                 (long) tv.tv_sec, (long) tv.tv_usec);
1651                 }
1652                 printtrailer(tcp);
1653
1654                 dumpio(tcp);
1655                 if (fflush(tcp->outf) == EOF)
1656                         return -1;
1657                 tcp->flags &= ~TCB_INSYSCALL;
1658                 return 0;
1659         }
1660
1661         /* Entering system call */
1662         res = syscall_enter(tcp);
1663         if (res != 1)
1664                 return res;
1665
1666         switch (tcp->scno + NR_SYSCALL_BASE) {
1667 #ifdef LINUX
1668 #if !defined (ALPHA) && !defined(SPARC) && !defined(MIPS) && !defined(HPPA)
1669         case SYS_socketcall:
1670                 decode_subcall(tcp, SYS_socket_subcall,
1671                         SYS_socket_nsubcalls, deref_style);
1672                 break;
1673         case SYS_ipc:
1674                 decode_subcall(tcp, SYS_ipc_subcall,
1675                         SYS_ipc_nsubcalls, shift_style);
1676                 break;
1677 #endif /* !ALPHA && !MIPS && !SPARC */
1678 #ifdef SPARC
1679         case SYS_socketcall:
1680                 sparc_socket_decode (tcp);
1681                 break;
1682 #endif
1683 #endif /* LINUX */
1684 #ifdef SVR4
1685 #ifdef SYS_pgrpsys_subcall
1686         case SYS_pgrpsys:
1687                 decode_subcall(tcp, SYS_pgrpsys_subcall,
1688                         SYS_pgrpsys_nsubcalls, shift_style);
1689                 break;
1690 #endif /* SYS_pgrpsys_subcall */
1691 #ifdef SYS_sigcall_subcall
1692         case SYS_sigcall:
1693                 decode_subcall(tcp, SYS_sigcall_subcall,
1694                         SYS_sigcall_nsubcalls, mask_style);
1695                 break;
1696 #endif /* SYS_sigcall_subcall */
1697         case SYS_msgsys:
1698                 decode_subcall(tcp, SYS_msgsys_subcall,
1699                         SYS_msgsys_nsubcalls, shift_style);
1700                 break;
1701         case SYS_shmsys:
1702                 decode_subcall(tcp, SYS_shmsys_subcall,
1703                         SYS_shmsys_nsubcalls, shift_style);
1704                 break;
1705         case SYS_semsys:
1706                 decode_subcall(tcp, SYS_semsys_subcall,
1707                         SYS_semsys_nsubcalls, shift_style);
1708                 break;
1709 #if 0 /* broken */
1710         case SYS_utssys:
1711                 decode_subcall(tcp, SYS_utssys_subcall,
1712                         SYS_utssys_nsubcalls, shift_style);
1713                 break;
1714 #endif
1715         case SYS_sysfs:
1716                 decode_subcall(tcp, SYS_sysfs_subcall,
1717                         SYS_sysfs_nsubcalls, shift_style);
1718                 break;
1719         case SYS_spcall:
1720                 decode_subcall(tcp, SYS_spcall_subcall,
1721                         SYS_spcall_nsubcalls, shift_style);
1722                 break;
1723 #ifdef SYS_context_subcall
1724         case SYS_context:
1725                 decode_subcall(tcp, SYS_context_subcall,
1726                         SYS_context_nsubcalls, shift_style);
1727                 break;
1728 #endif /* SYS_context_subcall */
1729 #ifdef SYS_door_subcall
1730         case SYS_door:
1731                 decode_subcall(tcp, SYS_door_subcall,
1732                         SYS_door_nsubcalls, door_style);
1733                 break;
1734 #endif /* SYS_door_subcall */
1735 #ifdef SYS_kaio_subcall
1736         case SYS_kaio:
1737                 decode_subcall(tcp, SYS_kaio_subcall,
1738                         SYS_kaio_nsubcalls, shift_style);
1739                 break;
1740 #endif
1741 #endif /* SVR4 */
1742 #ifdef FREEBSD
1743         case SYS_msgsys:
1744         case SYS_shmsys:
1745         case SYS_semsys:
1746                 decode_subcall(tcp, 0, 0, table_style);
1747                 break;
1748 #endif
1749 #ifdef SUNOS4
1750         case SYS_semsys:
1751                 decode_subcall(tcp, SYS_semsys_subcall,
1752                         SYS_semsys_nsubcalls, shift_style);
1753                 break;
1754         case SYS_msgsys:
1755                 decode_subcall(tcp, SYS_msgsys_subcall,
1756                         SYS_msgsys_nsubcalls, shift_style);
1757                 break;
1758         case SYS_shmsys:
1759                 decode_subcall(tcp, SYS_shmsys_subcall,
1760                         SYS_shmsys_nsubcalls, shift_style);
1761                 break;
1762 #endif
1763         }
1764
1765         internal_syscall(tcp);
1766         if (tcp->scno >=0 && tcp->scno < nsyscalls && !(qual_flags[tcp->scno] & QUAL_TRACE)) {
1767                 tcp->flags |= TCB_INSYSCALL;
1768                 return 0;
1769         }
1770
1771         if (cflag) {
1772                 gettimeofday(&tcp->etime, NULL);
1773                 tcp->flags |= TCB_INSYSCALL;
1774                 return 0;
1775         }
1776
1777         printleader(tcp);
1778         tcp->flags &= ~TCB_REPRINT;
1779         tcp_last = tcp;
1780         if (tcp->scno >= nsyscalls || tcp->scno < 0)
1781                 tprintf("syscall_%lu(", tcp->scno);
1782         else
1783                 tprintf("%s(", sysent[tcp->scno].sys_name);
1784         if (tcp->scno >= nsyscalls || tcp->scno < 0 || 
1785             ((qual_flags[tcp->scno] & QUAL_RAW) && tcp->scno != SYS_exit))
1786                 sys_res = printargs(tcp);
1787         else
1788                 sys_res = (*sysent[tcp->scno].sys_func)(tcp);
1789         if (fflush(tcp->outf) == EOF)
1790                 return -1;
1791         tcp->flags |= TCB_INSYSCALL;
1792         /* Measure the entrance time as late as possible to avoid errors. */
1793         if (dtime)
1794                 gettimeofday(&tcp->etime, NULL);
1795         return sys_res;
1796 }
1797
1798 int
1799 printargs(tcp)
1800 struct tcb *tcp;
1801 {
1802         if (entering(tcp)) {
1803                 int i;
1804
1805                 for (i = 0; i < tcp->u_nargs; i++)
1806                         tprintf("%s%#lx", i ? ", " : "", tcp->u_arg[i]);
1807         }
1808         return 0;
1809 }
1810
1811 long
1812 getrval2(tcp)
1813 struct tcb *tcp;
1814 {
1815         long val = -1;
1816
1817 #ifdef LINUX
1818 #ifdef SPARC
1819         struct regs regs;
1820         if (ptrace(PTRACE_GETREGS,tcp->pid,(char *)&regs,0) < 0)
1821                 return -1;
1822         val = regs.r_o1;
1823 #endif /* SPARC */
1824 #endif /* LINUX */
1825
1826 #ifdef SUNOS4
1827         if (upeek(tcp->pid, uoff(u_rval2), &val) < 0)
1828                 return -1;
1829 #endif /* SUNOS4 */
1830
1831 #ifdef SVR4
1832 #ifdef SPARC
1833         val = tcp->status.PR_REG[R_O1];
1834 #endif /* SPARC */
1835 #ifdef I386
1836         val = tcp->status.PR_REG[EDX];
1837 #endif /* I386 */
1838 #ifdef MIPS
1839         val = tcp->status.PR_REG[CTX_V1];
1840 #endif /* MIPS */
1841 #endif /* SVR4 */
1842 #ifdef FREEBSD
1843         struct reg regs;
1844         pread(tcp->pfd_reg, &regs, sizeof(regs), 0);
1845         val = regs.r_edx;
1846 #endif  
1847         return val;
1848 }
1849
1850 /*
1851  * Apparently, indirect system calls have already be converted by ptrace(2),
1852  * so if you see "indir" this program has gone astray.
1853  */
1854 int
1855 sys_indir(tcp)
1856 struct tcb *tcp;
1857 {
1858         int i, scno, nargs;
1859
1860         if (entering(tcp)) {
1861                 if ((scno = tcp->u_arg[0]) > nsyscalls) {
1862                         fprintf(stderr, "Bogus syscall: %u\n", scno);
1863                         return 0;
1864                 }
1865                 nargs = sysent[scno].nargs;
1866                 tprintf("%s", sysent[scno].sys_name);
1867                 for (i = 0; i < nargs; i++)
1868                         tprintf(", %#lx", tcp->u_arg[i+1]);
1869         }
1870         return 0;
1871 }
1872
1873 static int
1874 time_cmp(a, b)
1875 void *a;
1876 void *b;
1877 {
1878         return -tv_cmp(&tv_count[*((int *) a)], &tv_count[*((int *) b)]);
1879 }
1880
1881 static int
1882 syscall_cmp(a, b)
1883 void *a;
1884 void *b;
1885 {
1886         return strcmp(sysent[*((int *) a)].sys_name,
1887                 sysent[*((int *) b)].sys_name);
1888 }
1889
1890 static int
1891 count_cmp(a, b)
1892 void *a;
1893 void *b;
1894 {
1895         int m = call_count[*((int *) a)], n = call_count[*((int *) b)];
1896
1897         return (m < n) ? 1 : (m > n) ? -1 : 0;
1898 }
1899
1900 static int (*sortfun)();
1901 static struct timeval overhead = { -1, -1 };
1902
1903 void
1904 set_sortby(sortby)
1905 char *sortby;
1906 {
1907         if (strcmp(sortby, "time") == 0)
1908                 sortfun = time_cmp;
1909         else if (strcmp(sortby, "calls") == 0)
1910                 sortfun = count_cmp;
1911         else if (strcmp(sortby, "name") == 0)
1912                 sortfun = syscall_cmp;
1913         else if (strcmp(sortby, "nothing") == 0)
1914                 sortfun = NULL;
1915         else {
1916                 fprintf(stderr, "invalid sortby: `%s'\n", sortby);
1917                 exit(1);
1918         }
1919 }
1920
1921 void set_overhead(n)
1922 int n;
1923 {
1924         overhead.tv_sec = n / 1000000;
1925         overhead.tv_usec = n % 1000000;
1926 }
1927
1928 void
1929 call_summary(outf)
1930 FILE *outf;
1931 {
1932         int i, j;
1933         int call_cum, error_cum;
1934         struct timeval tv_cum, dtv;
1935         double percent;
1936         char *dashes = "-------------------------";
1937         char error_str[16];
1938
1939         call_cum = error_cum = tv_cum.tv_sec = tv_cum.tv_usec = 0;
1940         if (overhead.tv_sec == -1) {
1941                 tv_mul(&overhead, &shortest, 8);
1942                 tv_div(&overhead, &overhead, 10);
1943         }
1944         for (i = 0; i < nsyscalls; i++) {
1945                 sorted_count[i] = i;
1946                 if (call_count[i] == 0)
1947                         continue;
1948                 tv_mul(&dtv, &overhead, call_count[i]);
1949                 tv_sub(&tv_count[i], &tv_count[i], &dtv);
1950                 call_cum += call_count[i];
1951                 error_cum += error_count[i];
1952                 tv_add(&tv_cum, &tv_cum, &tv_count[i]);
1953         }
1954         if (sortfun)
1955                 qsort((void *) sorted_count, nsyscalls, sizeof(int), sortfun);
1956         fprintf(outf, "%6.6s %11.11s %11.11s %9.9s %9.9s %s\n",
1957                 "% time", "seconds", "usecs/call",
1958                 "calls", "errors", "syscall");
1959         fprintf(outf, "%6.6s %11.11s %11.11s %9.9s %9.9s %-16.16s\n",
1960                 dashes, dashes, dashes, dashes, dashes, dashes);
1961         for (i = 0; i < nsyscalls; i++) {
1962                 j = sorted_count[i];
1963                 if (call_count[j] == 0)
1964                         continue;
1965                 tv_div(&dtv, &tv_count[j], call_count[j]);
1966                 if (error_count[j])
1967                         sprintf(error_str, "%d", error_count[j]);
1968                 else
1969                         error_str[0] = '\0';
1970                 percent = 100.0*tv_float(&tv_count[j])/tv_float(&tv_cum);
1971                 fprintf(outf, "%6.2f %4ld.%06ld %11ld %9d %9.9s %s\n",
1972                         percent, (long) tv_count[j].tv_sec,
1973                         (long) tv_count[j].tv_usec,
1974                         (long) 1000000 * dtv.tv_sec + dtv.tv_usec,
1975                         call_count[j], error_str, sysent[j].sys_name);
1976         }
1977         fprintf(outf, "%6.6s %11.11s %11.11s %9.9s %9.9s %-16.16s\n",
1978                 dashes, dashes, dashes, dashes, dashes, dashes);
1979         if (error_cum)
1980                 sprintf(error_str, "%d", error_cum);
1981         else
1982                 error_str[0] = '\0';
1983         fprintf(outf, "%6.6s %4ld.%06ld %11.11s %9d %9.9s %s\n",
1984                 "100.00", (long) tv_cum.tv_sec, (long) tv_cum.tv_usec, "",
1985                 call_cum, error_str, "total");
1986 }