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